{-# LANGUAGE OverloadedStrings #-} import Codec.Borsh import Control.Monad (when) import Control.Monad.Logger (runFileLoggingT, runNoLoggingT) import Data.Aeson import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS import Data.HexString import Data.Maybe (fromJust) import qualified Data.Text.Encoding as E import Database.Persist import Database.Persist.Sqlite import System.Directory import Test.HUnit hiding (State(..)) import Test.Hspec import ZcashHaskell.Orchard ( addOrchardNodeGetRoot , getOrchardFrontier , getOrchardNodeValue , getOrchardPathAnchor , getOrchardRootTest , getOrchardTreeAnchor , getOrchardTreeParts , isValidUnifiedAddress , parseAddress ) import ZcashHaskell.Sapling ( decodeSaplingOutputEsk , encodeSaplingAddress , getSaplingNotePosition , getSaplingWitness , isValidShieldedAddress , updateSaplingCommitmentTree ) import ZcashHaskell.Transparent ( decodeExchangeAddress , decodeTransparentAddress ) import ZcashHaskell.Types ( DecodedNote(..) , MerklePath(..) , OrchardCommitmentTree(..) , OrchardFrontier(..) , OrchardSpendingKey(..) , OrchardTree(..) , Phrase(..) , SaplingCommitmentTree(..) , SaplingReceiver(..) , SaplingSpendingKey(..) , Scope(..) , ShieldedOutput(..) , TxError(..) , ValidAddress(..) , ZcashNet(..) ) import ZcashHaskell.Utils (f4Jumble, makeZebraCall, readZebraTransaction) import Zenith.Core import Zenith.DB import Zenith.Tree import Zenith.Types main :: IO () main = do checkDbFile <- doesFileExist "test.db" when checkDbFile $ removeFile "test.db" hspec $ do describe "Database tests" $ do it "Create table" $ do s <- runSqlite "test.db" $ do runMigration migrateAll s `shouldBe` () describe "Wallet Table" $ do it "insert wallet record" $ do s <- runSqlite "test.db" $ do insert $ ZcashWallet "Main Wallet" (ZcashNetDB MainNet) (PhraseDB $ Phrase "one two three four five six seven eight nine ten eleven twelve") 2000000 0 fromSqlKey s `shouldBe` 1 it "read wallet record" $ do s <- runSqlite "test.db" $ do selectList [ZcashWalletBirthdayHeight >. 0] [] length s `shouldBe` 1 it "modify wallet record" $ do s <- runSqlite "test.db" $ do let recId = toSqlKey 1 :: ZcashWalletId update recId [ZcashWalletName =. "New Wallet"] get recId "New Wallet" `shouldBe` maybe "None" zcashWalletName s it "delete wallet record" $ do s <- runSqlite "test.db" $ do let recId = toSqlKey 1 :: ZcashWalletId delete recId get recId "None" `shouldBe` maybe "None" zcashWalletName s describe "Wallet function tests:" $ do it "Save Wallet:" $ do pool <- runNoLoggingT $ initPool "test.db" zw <- saveWallet pool $ ZcashWallet "Testing" (ZcashNetDB MainNet) (PhraseDB $ Phrase "cloth swing left trap random tornado have great onion element until make shy dad success art tuition canvas thunder apple decade elegant struggle invest") 2200000 0 zw `shouldNotBe` Nothing it "Save Account:" $ do pool <- runNoLoggingT $ initPool "test.db" s <- runSqlite "test.db" $ do selectList [ZcashWalletName ==. "Testing"] [] za <- saveAccount pool =<< createZcashAccount "TestAccount" 0 (head s) za `shouldNotBe` Nothing it "Save address:" $ do pool <- runNoLoggingT $ initPool "test.db" acList <- runSqlite "test.db" $ selectList [ZcashAccountName ==. "TestAccount"] [] zAdd <- saveAddress pool =<< createWalletAddress "Personal123" 0 MainNet External (head acList) addList <- runSqlite "test.db" $ selectList [ WalletAddressName ==. "Personal123" , WalletAddressScope ==. ScopeDB External ] [] getUA (walletAddressUAddress (entityVal $ head addList)) `shouldBe` "u1trd8cvc6265ywwj4mmvuznsye5ghe2dhhn3zy8kcuyg4vx3svskw9r2dedp5hu6m740vylkqc34t4w9eqkl9fyu5uyzn3af72jg235440ke6tu5cf994eq85n97x69x9824hqejmwz3d8qqthtesrd6gerjupdymldhl9xccejjwfj0dhh9mt4rw4kytp325twlutsxd20rfqhzxu3m" it "Address components are correct" $ do let ua = "utest1mvlny48qd4x94w8vz5u2lrxx0enuquajt72yekgq24p6pjaky3czk6m7x358h7g900ex6gzvdehaekl96qnakjzw8yaasp8y0u3j5jnlfd33trduznh6k3fcn5ek9qc857fgz8ehm37etx94sj58nrkc0k5hurxnuxpcpms3j8uy2t8kt2vy6vetvsfxxdhtjq0yqulqprvh7mf2u3x" isValidUnifiedAddress ua `shouldNotBe` Nothing describe "Note selection for Tx" $ do it "Value less than balance" $ do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" res <- selectUnspentNotes pool (toSqlKey 1) 14000000 res `shouldNotBe` ([], [], []) it "Value greater than balance" $ do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" let res = selectUnspentNotes pool (toSqlKey 1) 84000000 res `shouldThrow` anyIOException describe "Testing validation" $ do it "Unified" $ do let a = "utest1zfnw84xuxg0ytzqc008gz0qntr8cvwu4qjsccgtxwdrjywra7uj85x8ldymjc2jd3jvvvhyj3xwsunyvwkr5084t6p5gmvzwdgvwpflrpd6a3squ2dp8vt7cxngmwk30l44wkmvyfegypqmezxfnqj572lr779gkqj5xekp66uv4jga58alnc5j7tuank758zd96ap4f09udg6y6pxu" True `shouldBe` (case isValidUnifiedAddress (E.encodeUtf8 a) of Just _a1 -> True Nothing -> isValidShieldedAddress (E.encodeUtf8 a) || (case decodeTransparentAddress (E.encodeUtf8 a) of Just _a3 -> True Nothing -> case decodeExchangeAddress (E.encodeUtf8 a) of Just _a4 -> True Nothing -> False)) it "Sapling" $ do let a = "ztestsapling1tgjr4zppwk4ne8xy6gdq4z2gwq7dmf5jq8z2ctpn8nlmtse0a74fa5z0m8z383gmpgqz6q6duu4" True `shouldBe` (case isValidUnifiedAddress (E.encodeUtf8 a) of Just _a1 -> True Nothing -> isValidShieldedAddress (E.encodeUtf8 a) || (case decodeTransparentAddress (E.encodeUtf8 a) of Just _a3 -> True Nothing -> case decodeExchangeAddress (E.encodeUtf8 a) of Just _a4 -> True Nothing -> False)) it "Transparent" $ do let a = "tmGfVZHuGVJ5vcLAgBdkUU4w7fLTRE5nXm3" True `shouldBe` (case isValidUnifiedAddress (E.encodeUtf8 a) of Just _a1 -> True Nothing -> isValidShieldedAddress (E.encodeUtf8 a) || (case decodeTransparentAddress (E.encodeUtf8 a) of Just _a3 -> True Nothing -> case decodeExchangeAddress (E.encodeUtf8 a) of Just _a4 -> True Nothing -> False)) it "Check Sapling Address" $ do let a = encodeSaplingAddress TestNet $ SaplingReceiver "Z$:\136!u\171<\156\196\210\SUB\n\137Hp<\221\166\146\SOH\196\172,3<\255\181\195/\239\170\158\208O\217\197\DC3\197\ESC\n\NUL-" a `shouldBe` Just "ztestsapling1tgjr4zppwk4ne8xy6gdq4z2gwq7dmf5jq8z2ctpn8nlmtse0a74fa5z0m8z383gmpgqz6q6duu4" describe "Witnesses" $ do describe "Sapling" $ do it "max output id" $ do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" sId <- getMaxSaplingNote pool sId `shouldBe` toSqlKey 0 describe "Notes" $ do xit "Check Orchard notes" $ do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" oNotes <- getWalletUnspentOrchNotes pool (toSqlKey 1) oNotes `shouldBe` [] xit "Check Sapling notes" $ do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" oNotes <- getWalletUnspentSapNotes pool (toSqlKey 4) oNotes `shouldBe` [] xit "Check transparent notes" $ do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" oNotes <- getWalletUnspentTrNotes pool (toSqlKey 1) oNotes `shouldBe` [] describe "Tree tests" $ do let cmx1 = hexString "1712ead46028d4349e234abf59e94e0640fe7a0829e2e2e17e1a931631810400" let cmx2 = hexString "39f5ad39817fb432fa07c5feb3a957189fbe7662a4b5555ca95093b6d853cf07" let t0 = EmptyLeaf <> EmptyLeaf :: Tree OrchardNode let t1 = t0 <> EmptyLeaf :: Tree OrchardNode let t1a = t0 <> t0 it "Create leaf" $ do let n = leaf cmx1 0 0 :: Tree OrchardNode getLevel (value n) `shouldBe` 0 it "Create minimal tree" $ do let t = leaf cmx1 0 0 <> EmptyLeaf :: Tree OrchardNode getLevel (value t) `shouldBe` 1 it "Create minimal empty tree" $ do getHash (value t0) `shouldNotBe` hexString "00" it "Expand empty tree" $ do t1 `shouldBe` t1a it "Create empty tree non-rec" $ getEmptyRoot 2 `shouldBe` t1 it "Validate empty tree" $ do getHash (value (getEmptyRoot 32 :: Tree OrchardNode)) `shouldBe` getOrchardRootTest 32 it "Validate tree with one leaf" $ do let n = leaf cmx1 0 1 :: Tree OrchardNode let n1 = root n getHash (value n1) `shouldBe` addOrchardNodeGetRoot 32 (hexBytes cmx1) it "Validate size of tree from Zebra" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" case getOrchardTreeParts tree of Nothing -> assertFailure "Failed to get parts" Just t1 -> do case getOrchardFrontier tree of Nothing -> assertFailure "Failed to get frontier" Just f1 -> do orchardSize t1 `shouldBe` 1 + fromIntegral (of_pos f1) it "Deserialize commitment tree from Zebra" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" case getOrchardTreeParts tree of Nothing -> assertFailure "Failed to get frontier" Just t1 -> do length (ot_parents t1) `shouldBe` 31 it "Create commitment tree from Zebra" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" case getOrchardTreeParts tree of Nothing -> assertFailure "Failed to get tree parts" Just t1 -> do let newTree = mkOrchardTree t1 getLevel (value newTree) `shouldBe` 32 it "Validate commitment tree from Zebra" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" case getOrchardTreeParts tree of Nothing -> assertFailure "Failed to get tree parts" Just t1 -> do let newTree = mkOrchardTree t1 let ctAnchor = getOrchardTreeAnchor tree {- -getHash (value newTree) `shouldBe` ctAnchor -isFull (value newTree) `shouldBe` False -} getPosition (value newTree) `shouldBe` 39733 it "Validate appending nodes to tree" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" let cmx1 = hexString "1712ead46028d4349e234abf59e94e0640fe7a0829e2e2e17e1a931631810400" :: OrchardCommitment let cmx2 = hexString "39f5ad39817fb432fa07c5feb3a957189fbe7662a4b5555ca95093b6d853cf07" :: OrchardCommitment let cmx3 = hexString "84f7fbc4b9f87215c653078d7fdd90756c3ba370c745065167da9eb73a65a83f" :: OrchardCommitment let cmx4 = hexString "e55ad64e1ea2b261893fdea6ad0509b66e5f62d3142f351298c7135c4498d429" :: OrchardCommitment let finalTree = OrchardCommitmentTree $ hexString "0184f7fbc4b9f87215c653078d7fdd90756c3ba370c745065167da9eb73a65a83f01e55ad64e1ea2b261893fdea6ad0509b66e5f62d3142f351298c7135c4498d4291f0000014b1a76d3820087b26cd087ca84e17f3067a25ebed82ad23a93fa485affb5530b01ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" case getOrchardTreeParts tree of Nothing -> assertFailure "Failed to get tree parts" Just t1 -> do let newTree = mkOrchardTree t1 let updatedTree1 = append newTree (cmx1, 4) let updatedTree2 = append updatedTree1 (cmx2, 5) let updatedTree3 = append updatedTree2 (cmx3, 6) let updatedTree4 = append updatedTree3 (cmx4, 7) let finalAnchor = getOrchardTreeAnchor finalTree getHash (value updatedTree4) `shouldBe` finalAnchor it "Validate serializing tree to bytes" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" case mkOrchardTree <$> getOrchardTreeParts tree of Nothing -> assertFailure "Failed to build tree" Just t1 -> do let treeBytes = serialiseBorsh t1 LBS.length treeBytes `shouldNotBe` 0 it "Validate deserializing tree from bytes" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" case mkOrchardTree <$> getOrchardTreeParts tree of Nothing -> assertFailure "Failed to build tree" Just t1 -> do let treeBytes = serialiseBorsh t1 let rebuiltTree = deserialiseBorsh treeBytes rebuiltTree `shouldBe` Right t1 it "Create merkle path" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" let cmx1 = hexString "1712ead46028d4349e234abf59e94e0640fe7a0829e2e2e17e1a931631810400" :: OrchardCommitment let cmx2 = hexString "39f5ad39817fb432fa07c5feb3a957189fbe7662a4b5555ca95093b6d853cf07" :: OrchardCommitment case getOrchardTreeParts tree of Nothing -> assertFailure "Failed to get tree parts" Just t1 -> do let newTree = mkOrchardTree t1 let updatedTree = foldl append newTree [(cmx1, 4), (cmx2, 5)] case path 39735 updatedTree of Nothing -> assertFailure "Failed to get Merkle path" Just p1 -> p1 `shouldNotBe` MerklePath 0 [] it "Validate merkle path" $ do let tree = OrchardCommitmentTree $ hexString "0136a7886d7d73bc1845223165fd9cb0cef02046c707e8f88a7f61564720bd0f3501dca1fbdd7b5ba92a0809af5e85874626ce0db14d0532a48e41dde6f0f81b46011f0001fb48c27bd07e68f27aba47cd6e93fa961e0ef8c63f993963a614e56855d2013c0001ea572db9c5c2d24c7ad9132ae32b27179466bf67a580d59901d13b281d3f530b01c160348f10b9ad893d9731317ebe36ac8665e01c52cbe15a56aa9b72e4e6c41e000001cd7695156de2debdc5b13ea84d32e4e3ac020fb0aa7cd372c57ce765103bd70401746e6bc066a10e7f80a9ff8993dcb25c819edd64f2ca10ac248ef7848d41450500011e6191f91b3fceb62dc881a156e1b9d2e88e09dca25093cf9c4936c8869fb41a013bf8b923e4187754e85175748d9cce4824a6787e4258977b5bfe1ba59012c032000001f3bbdc62260c4fca5c84bf3487246d4542da48eeeec8ec40c1029b6908eef83c00000000000000000000000000000000" let cmx1 = hexString "1712ead46028d4349e234abf59e94e0640fe7a0829e2e2e17e1a931631810400" :: OrchardCommitment let cmx2 = hexString "39f5ad39817fb432fa07c5feb3a957189fbe7662a4b5555ca95093b6d853cf07" :: OrchardCommitment case getOrchardTreeParts tree of Nothing -> assertFailure "Failed to get tree parts" Just t1 -> do let newTree = mkOrchardTree t1 let updatedTree = foldl append newTree [(cmx1, 4), (cmx2, 5)] case path 39735 updatedTree of Nothing -> assertFailure "Failed to get Merkle path" Just p1 -> do getOrchardPathAnchor cmx2 p1 `shouldBe` getHash (value updatedTree) describe "Creating Tx" $ do describe "Full" $ do it "To Orchard" $ do let uaRead = parseAddress "utest1dl54utt6prjj5e0dnlknwumnxq9hycdjpkfr0sy6e6h522remqee8axe9zax0wsjrwpj76v555pdhvj9rnargpfyycs0vpkapq98xcdhem99gc4wchzn0ggepq3y6nz3a9sscwgqxgsh9vzhcad402y3x9szfregck5gslkya3c79d86xx0l33tpk8gnn7ew9vw37w43zh22u8dgdax" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 3) 3026170 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 (Just "Sending memo to orchard") ] Full case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` hexString "deadbeef" it "To Sapling" $ do let uaRead = parseAddress "ztestsapling136jp8z89v2jh6kqd5rs4dtvlxym90m43svzdwzxaplyvc5ttzppytpvx80ncllcsqzpmukxjl3y" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 4) 3001331 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 (Just "Sending memo to sapling") ] Full case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` hexString "deadbeef" it "To Transparent" $ do let uaRead = parseAddress "tmAmSa4AauSFuJieeanRBjkfnah45ysGtgZ" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 4) 3001331 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] Full tx `shouldBe` Left (PrivacyPolicyError "Receiver not capable of Full privacy") it "To mixed shielded receivers" $ do let uaRead = parseAddress "utest1dl54utt6prjj5e0dnlknwumnxq9hycdjpkfr0sy6e6h522remqee8axe9zax0wsjrwpj76v555pdhvj9rnargpfyycs0vpkapq98xcdhem99gc4wchzn0ggepq3y6nz3a9sscwgqxgsh9vzhcad402y3x9szfregck5gslkya3c79d86xx0l33tpk8gnn7ew9vw37w43zh22u8dgdax" let uaRead2 = parseAddress "ztestsapling136jp8z89v2jh6kqd5rs4dtvlxym90m43svzdwzxaplyvc5ttzppytpvx80ncllcsqzpmukxjl3y" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001331 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 (Just "Sending memo to orchard") , ProposedNote (ValidAddressAPI $ fromJust uaRead2) 0.004 Nothing ] Full tx `shouldBe` Left (PrivacyPolicyError "Combination of receivers not allowed for Full privacy") describe "Medium" $ do it "To Orchard" $ do let uaRead = parseAddress "utest1dl54utt6prjj5e0dnlknwumnxq9hycdjpkfr0sy6e6h522remqee8axe9zax0wsjrwpj76v555pdhvj9rnargpfyycs0vpkapq98xcdhem99gc4wchzn0ggepq3y6nz3a9sscwgqxgsh9vzhcad402y3x9szfregck5gslkya3c79d86xx0l33tpk8gnn7ew9vw37w43zh22u8dgdax" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 (Just "Sending memo to orchard") ] Medium case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` hexString "deadbeef" it "To Sapling" $ do let uaRead = parseAddress "ztestsapling136jp8z89v2jh6kqd5rs4dtvlxym90m43svzdwzxaplyvc5ttzppytpvx80ncllcsqzpmukxjl3y" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 (Just "Sending memo to sapling") ] Medium case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` (hexString "00") it "To Transparent" $ do let uaRead = parseAddress "tmAmSa4AauSFuJieeanRBjkfnah45ysGtgZ" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 4) 3001331 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] Medium tx `shouldBe` Left (PrivacyPolicyError "Receiver not capable of Medium privacy") it "To mixed shielded receivers" $ do let uaRead = parseAddress "utest1dl54utt6prjj5e0dnlknwumnxq9hycdjpkfr0sy6e6h522remqee8axe9zax0wsjrwpj76v555pdhvj9rnargpfyycs0vpkapq98xcdhem99gc4wchzn0ggepq3y6nz3a9sscwgqxgsh9vzhcad402y3x9szfregck5gslkya3c79d86xx0l33tpk8gnn7ew9vw37w43zh22u8dgdax" let uaRead2 = parseAddress "ztestsapling136jp8z89v2jh6kqd5rs4dtvlxym90m43svzdwzxaplyvc5ttzppytpvx80ncllcsqzpmukxjl3y" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001331 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 (Just "Sending memo to orchard") , ProposedNote (ValidAddressAPI $ fromJust uaRead2) 0.004 Nothing ] Medium case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` (hexString "deadbeef") describe "Low" $ do it "To Orchard" $ do let uaRead = parseAddress "utest1dl54utt6prjj5e0dnlknwumnxq9hycdjpkfr0sy6e6h522remqee8axe9zax0wsjrwpj76v555pdhvj9rnargpfyycs0vpkapq98xcdhem99gc4wchzn0ggepq3y6nz3a9sscwgqxgsh9vzhcad402y3x9szfregck5gslkya3c79d86xx0l33tpk8gnn7ew9vw37w43zh22u8dgdax" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] Low case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` (hexString "deadbeef") it "To Sapling" $ do let uaRead = parseAddress "ztestsapling136jp8z89v2jh6kqd5rs4dtvlxym90m43svzdwzxaplyvc5ttzppytpvx80ncllcsqzpmukxjl3y" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] Low case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` (hexString "deadbeef") it "To Transparent" $ do let uaRead = parseAddress "tmAmSa4AauSFuJieeanRBjkfnah45ysGtgZ" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] Low case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` (hexString "deadbeef") describe "None" $ do it "To Orchard" $ do let uaRead = parseAddress "utest1dl54utt6prjj5e0dnlknwumnxq9hycdjpkfr0sy6e6h522remqee8axe9zax0wsjrwpj76v555pdhvj9rnargpfyycs0vpkapq98xcdhem99gc4wchzn0ggepq3y6nz3a9sscwgqxgsh9vzhcad402y3x9szfregck5gslkya3c79d86xx0l33tpk8gnn7ew9vw37w43zh22u8dgdax" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] None tx `shouldBe` Left (PrivacyPolicyError "Shielded recipients not compatible with privacy policy.") it "To Sapling" $ do let uaRead = parseAddress "ztestsapling136jp8z89v2jh6kqd5rs4dtvlxym90m43svzdwzxaplyvc5ttzppytpvx80ncllcsqzpmukxjl3y" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] None tx `shouldBe` Left (PrivacyPolicyError "Shielded recipients not compatible with privacy policy.") it "To Transparent" $ do let uaRead = parseAddress "tmAmSa4AauSFuJieeanRBjkfnah45ysGtgZ" case uaRead of Nothing -> assertFailure "wrong address" Just ua -> do pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" tx <- runFileLoggingT "zenith.log" $ prepareTxV2 pool "localhost" 18232 TestNet (toSqlKey 1) 3001372 [ ProposedNote (ValidAddressAPI $ fromJust uaRead) 0.005 Nothing ] None case tx of Left e -> assertFailure $ show e Right h -> h `shouldNotBe` hexString "deadbeef"