From 3296909c82ce20c587c8919646d96b01cc10203e Mon Sep 17 00:00:00 2001 From: Rene Vergara Date: Wed, 24 Apr 2024 11:57:00 -0500 Subject: [PATCH] Fix Sapling spend parsing --- CHANGELOG.md | 1 + librustzcash-wrapper/src/lib.rs | 16 ++++++++-------- test/Spec.hs | 26 +++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7d844c..e077efd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Orchard note nullifier calculation +- Sapling spend field parsing ## [0.5.5.2] diff --git a/librustzcash-wrapper/src/lib.rs b/librustzcash-wrapper/src/lib.rs index e42f374..ab7c934 100644 --- a/librustzcash-wrapper/src/lib.rs +++ b/librustzcash-wrapper/src/lib.rs @@ -401,9 +401,9 @@ impl ToHaskell for HSBundle { impl HSBundle { pub fn from_bundle(sb: &SaplingBundle) -> HSBundle { - let s = Cursor::new(Vec::new()); - sb.authorization().binding_sig.write(s.clone()).unwrap(); - return HSBundle {empty: false, spends: Hspend::pack(sb.shielded_spends()) , outputs: HshieldedOutput::pack(sb.shielded_outputs()) , value: i64::from(sb.value_balance()) , sig: s.into_inner() } + let mut s: Vec = Vec::new(); + sb.authorization().binding_sig.write(&mut s).unwrap(); + return HSBundle {empty: false, spends: Hspend::pack(sb.shielded_spends()) , outputs: HshieldedOutput::pack(sb.shielded_outputs()) , value: i64::from(sb.value_balance()) , sig: s } } } @@ -428,11 +428,11 @@ impl Hspend { pub fn pack(sp: &[SpendDescription]) -> Vec { let mut r = Vec::new(); for s in sp { - let rk = Cursor::new(Vec::new()); - let authsig = Cursor::new(Vec::new()); - s.rk().write(rk.clone()).unwrap(); - s.spend_auth_sig().write(authsig.clone()).unwrap(); - r.push(Hspend {cv: Hhex{bytes:s.cv().to_bytes().to_vec()}, anchor: Hhex{bytes:s.anchor().to_bytes().to_vec()}, nullifier: Hhex{bytes:s.nullifier().to_vec()}, rk: Hhex{bytes: rk.into_inner()}, proof: Hhex{bytes:s.zkproof().to_vec()}, authsig: Hhex{bytes:authsig.into_inner()}}); + let mut rk = Vec::new(); + let mut authsig = Vec::new(); + s.rk().write(&mut rk).unwrap(); + s.spend_auth_sig().write(&mut authsig).unwrap(); + r.push(Hspend {cv: Hhex{bytes:s.cv().to_bytes().to_vec()}, anchor: Hhex{bytes:s.anchor().to_bytes().to_vec()}, nullifier: Hhex{bytes:s.nullifier().to_vec()}, rk: Hhex{bytes: rk}, proof: Hhex{bytes:s.zkproof().to_vec()}, authsig: Hhex{bytes:authsig}}); } return r } diff --git a/test/Spec.hs b/test/Spec.hs index 49e985c..be1b49a 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -798,7 +798,11 @@ main = do let h = hexString "0400008085202f8900010829d200000000001976a91484ae5002305847e7176362d7c12c19c5bdbbaf8088ac0000000023392a00f02cd200000000000192331caef004cc758fb666bed1908e61daa82d5c9835c0544afd8369589d350b04a7488a9870983860779ca2e0079a286fe71f60d5c583c3427d24ff968bad3246c1c838b90f465becc1ddfea5839b730ec219d577ed182f6da8f493350b422c86943b7c8ff42de8aee0fe01f4b91c8bb204008f06f85c3dffdb622632d2d4e8b8f0c7457cfa0f4238c7ef4c8903a89559e9307c26e844747ccb9b8dd5e7e83637983746b2fec3de051312306eb8b15db4766b3ef5fe3086d53d388cf2b3b209389ff3644e47d6bfdbe2fafef1bc2311093ad0b49f4600925f55328da337e73f01f83097acd8f2aca7a85f28e75fb4efec6551e026a1ebb35c25efde455cc44002bb8cc79288ed738423432558ebb583874aa5c356abe5be794e1bfaeaf6a7eccf67e5d938751a3a351bc21d4422d2ff0f36f5b30759d79b1ef2d83618d9c1769694454002d2f2be74de3ac10d39829369c87a70e1e9769e7d5ae7c865282a04487a8ae4cf5beeecaea6a3be1c864bdd8d61df88f08a76ac49d28a3a069d2c0d02068a10e88674b39c9d03da49256d914319d267c0d1db08ee7777668e90a94c50a065977222ee620f2291f6ca3fa464fafe8fc3fedf64a836eef5a2ca16aaae5573ee082a77f046d388750fa4ce3853c846ae3f338741c7976f72db4ade4abd4211e8d335ec8c83309bc7d7140a99dfb64a29839b9acc74de4ac0949bcbec4e76be9096a45ab6ca19b165f4097e24ab92d7b58694b0897789c3cdcca2b3d4b0a9da153fafe68f940031b6548d3c37c1301faa9adcfc41c417e613c0838340e28801f72610289d7435910fd276ca243d119541e0a121d263fdda149ac40f293e6fee6d5ddc32532ad947548eb5d20a5bfea97543965fe09313f1a5a78ce51ecac9c36b54cb573780da15d197f5ffacf1fa0d2b5495057a29104d610936c1898d1058f6f7b90e614bc2e3ff56b1e75aa4708128e3782f602dbdd29ece268311965592ddd536ea63841ea953b20677e0dd911852d23b85a3382420d22cd276b216e81638540b04966210a9308e8f9fb46958c967e3c2e36ae081a95cec8865a87d85d5689f660fe6c616ebfc2dab0f6e41d3e8c2906405fb98a506d90a8e8c6201d520a0deaa65e92e91f965288128101427d58e0b1e3ad8a49526feed27f3bcc6d505591483e2e4cc4a9b678d63f3abc905f26f91083bc595b89ff0b6cc3caa9d93013127ab7b30fbe18fad6f7f380fd6d5668fb6c3fdea3771fdd3004994e5752275ff7b186f9ad95f9d7ff01263f1165de34c1ae867e8954d66186880a90d73eace4dc1b8b17c76815242342821b4fab93755c3dc24e60aafd1cd3e283a7414de3af18c61328d92e9141916b8bb816de024a5a047a66508340a3287f698a41804e297916ff04f2921a0eeb8fcc5690c7fc024f57ab1fb6c6bc9a0caf9bf9e0e9aad64ceb2634bedbda6716235e4b93b67cd07ae06fde6abd2893143b55628be83fd4b347ce407dabf28e288f99d23b031376bfc1b1552cac1557e4730b03be581a92feae7d39fa2cf1c565a6cbe59a83b64b90ef8fc73ff6f8b9562d77fae1221df8f5ddb029f12ae80c3f128b87e56f78224b875af54a2fa1434749bb2e1c7ad9331497a71015ae0fc63903f36023e7f34b97c6ec5976ba3740845e5870c85f1b2042cdca86620881e08595215332de7d5828844e9e44124e42e1c60f6821cb71640c6643b01681553c932d310632a8b21154445176eb1a9a3c87dff22508bdbe4f1500e19131a072c42ff1d106ade135722a9e37e95e7e93917378e7907aae4be92dab78b1cd5a771d6064f6e3afc26ff84943a84de7f6ca6b0ab5993d1013b061da4053d77398cbeb329a6ae16f76493f85df1164b4f1fdff69bf113c8f18274a4ce6a05dd4c1ccbacb8d2c3760210e312c3a344294b43b23d06b7ce7263d3178e4fd530ba5838dc0e517b7d6fff2a0d9c4d69105a8fdab3f0c51a219c1ec10337b7cf05f8f3b1fb0a09f600308e5c21ae6ae06d6f87a6766d29e3a34f331f520d80524d580bd54b25716b6b937534233b856e022d20e53779b3a4a3615a3d62d1824c2bfa906e7804d629cc6712a3aee8c3703e99ec807cdb2d381acf126d63b83a2ce1d8f5cb768270bf41ae5637976acbaad8a1fa52cfb7a2f012966f3d29867cf2c28e504043a09eeff91917f6e96dc35a7df124074da73a20b87c7c8e2196f344cc08bd4c2406daaf6064488b5f9983131d90141fba82b13b0b1ff60565be66d53c36df3a9b4c772bffd428b34f94060ad32c59c9c029eba5fabd7a01b4e7252406c0ce7bb93c831034b100cc71090b37a436f96ce902973e2dca9594886b602ed6142697413aa448652529fe688a2e62fa96f8031ade066bb2bdc682f0ae3a526c7ad3c5d01e243b999a58aa5f6816dcd7a0cdd49202e128b99436f71e7fb7033bf96d8e3930e39e024530ec4b7932d334e54a66bfc3630b472336b6719d5a38e6e9bed938f71fe49e0af0b20c5db5408cabb3227b1690e904ea3116ee568330f56a5a698b914570962da4d831f5f5acde9acb257d272d0cd14e3133c89307f2d1575e32b8cc1582d1e4a680d35a1a2cace6233dfb4b0a7fea26f41785e1ac6007dd20d8b6dc3bd6857fa487c52b39f86647a67931b33910b746331305199d20ecd2e4d3b454226a134240831ea5a35c1e2d603c48eea209868b839c79a9318b6fd1078bc0f2bb9b0e931b64d63fbbcbf22b41e3cf7bee5cecb3c0e7b3ae39cf736fce8645ab33becbc9586a9154e29dd88f42ec7deecb2a4c08ac020ce54607f8006d2aa05a689ea688419215f0a10043820d85965a0001f102915fa6b2edfc4d6db7011a725db79b3974e9c1fc1636781bc9609359cfb0c5c921b83fc1115f7ed2568e49991ef93f8b8ff93a0d778251f0bcaa00ad64de8438d40aa05adbd1d1d1d2bca05ea9471a2c1a3733e92bcdf896d47dbe41b9f0d8b8b75de1ccd7cd7b7802fc01c4536a1a7b52ce70736e2cdfc547b58401023e34a608c1b09d0f13ab83d7b3fcde0e050c8cb4635508ddc143a9e6edb1e5a489a48ae0f4d5b0cede7d1b0ed8177709edbd61d859f6d9bad93a4c640684b7b8d994d8f5c0c8773da2b7a5b57d28b58d3f00c53430671d4af1537a262e8ea44a1b943c9bfc5082ad86d6690de32bb6527c815da065061bf79562d292e3d4799aa0df968fb939f64203f541dd4d006e5bd0b34b39215a972c36b229fc2f8e7f10e154b369d7b8f85f89daaaba6ec9836ad748dd79be4a58210341a458202a16e152ca2b0338a116a8490a7fa52c02" + let h1 = + hexString + "0400008085202f89014b6ded3d2ee43e54135c04f9a305b473d7d741bbe6f383aa636e03e948705e0d01000000fdfd0000483045022100b34ca0fb34959230b95a48e9de95521dc4c013bdc0e6bd2a77a67b373fadea42022030a1b13f16993ab212d9f674b7b8dd3c6723137c183dbd41a9bbfcf66d7811c40147304402200f0bd12663a52ccb5e6211ec633932bbc7f0151ab51194038534abf88f689025022051fe62591dfa11a96095b4aeee2114c77a0d773242939f7ac2fa8e5262ff0865014c6952210231ee0c161e846bc133ad41d295f560d7e24829415afc78ead24d4b10198bb7342103b0b11f2dd10611d06cd6232233678dce736ce2b2141c62bdf0b4fe6f79d736da21029cbeda22b05352f66a338561604cbe11e8332f836385f16abf5088045c39d4dd53aefdffffff02b63500000000000017a91499a8b5b1f3d3a1a12e92dd4f3d94bee8fc34c527873362fa020000000017a914d75fe4791fcd50f2874f1b7457fca5833293b3a38700000000000000000000000000000000000000" let t = readZebraTransaction h + let t1 = readZebraTransaction h1 it "Transparent output is identified" $ do case t of Nothing -> assertFailure "Couldn't decode" @@ -820,7 +824,27 @@ main = do (\(TxOut v s) -> s) (head (tb_vout myTb')) pkHash `shouldBe` maybe "" (hexBytes . tr_bytes) (t_rec addr) - myTb `shouldNotBe` Nothing + it "Transparent input is identified" $ do + case t1 of + Nothing -> assertFailure "Couldn't decode" + Just t1' -> do + let tb1 = zt_tBundle t1' + print tb1 + let txInHex = + HexString + "Km\237=.\228>T\DC3\\\EOT\249\163\ENQ\180s\215\215A\187\230\243\131\170cn\ETX\233Hp^\r" + toText txInHex `shouldBe` "Blank" + it "Sapling component is read" $ do + case t of + Nothing -> assertFailure "Couldn't decode" + Just t' -> do + let sb = zt_sBundle t' + fromRawSBundle sb `shouldNotBe` Nothing + describe "Raw transaction with Sap spend" $ do + let h = + hexString + "050000800a27a726b4d0d6c200000000c3c02a0000000111ac7f9600d034fec892f50600006b09ad88c990a8f3c5bffb6856beebd0ce356c5d1413c63a9a88db71c3f41dc12cd60197ee742fc75b217215e7144db48bd3fa55de211e0c8d7da70aba0efe17124b5250fc9fa095c8e50b53168142eb7ec402289a84ab762ddafb0f972fc07c61eb45249922752dfac17fd704a3b6156a6955286c04587f37fc781a9a0b28e92664dde2300c6321dd21d367c16b4c2b510e5d0a4358624e1ceb816da155e588726f783ed6bf396eaecada3d3bde7a0722419014c509a7fe264003af5388c5c8cdf2076137b26cf66383b41dea2af415f3d16767124616609b96789e2811f7bc8b36c0b746d225c0aa2c98b370fd39b2015eea43d523e5fbccc7ca127e59bc92ac8ad32d05243d278a26f07f33f45df23c3e8dd40d72af35a70068cc3f8445478c9cd3a56d3515e207a1b95c39c9d8b45e66827cf63e6018bf1012a47aa23ec0174735949f62036df3f677f92d3aa10365e2d358d92f77e9a6294c245eb8536493e8480f5215cdf7c863623727efa188fd8679f95318d0072915dc2be8e77b5778c48d3a2ea614990984c29dfaf7c582d269f0e9ffe6e3c475c99dbf5f8756c334b3c7b5954d68549c65fc2648bb389ba63397525829c48f7f32e43e866dfbc8ad86f54a867e592524f9c43b007328b78220cab4537c2d65f64c819ecc19ae09e17b3c84208cc169c2eaf8831d452dc83527a966b288aacce6f261aa8ed23e2c0613c48161c1eb0199915ee9c1f9cf0e7e5445539f5016b3ff701408b45557154a53e48998b49a2d149a67202caa6b585348b42fbeda770e084128760c742537743ba8cec4f997fe575db9cb370d89278c607a598ff06f1ece047855ea0a3d808d84272e22bcdeb2eb5bbe5754947be5d6fe42038d26f13313e039adf7e1091a901a6daa24b247b13c810eb5b50cd6040463c6bfa209a792d77eafb0f063167b11777d97ad05ca7eec1f1a45698e33f8e8b11a0ab0ad16ec10e4abba6de69255e0e00c7e712503a107012a46fcb9c5186a1fc5be96dcc279fa3dd18e69ee4a8ba75edaff105716b4751717aa818d514620ddd13a6716729417571a342dcc8a6f341d05db7614e729491095e4bcc6fbdec2908b6f74d7db81106ab2e1c0ee6217ba3cbb174232a42f2e6aba7e92eb2934dcd91c5a36eae1aac5160bf6076a39baeea84b8bad043c565eb8c4206a74b68c9342f9d7b1b31eec86bb9c5c73549313dd2cbe3bce55ecfdd952f3eb4dd5fa7c2000727b62a0faeb0fac1cf05246221c37560359c44610ee8f93cdd1179fc35fbd808152f507e790eb2140faccb2f6c9897a3a219d8752388e846c7277d82dc80850aeef2de46eb2d81563d53714d39e3553f5133abeae6c487d10664e1b10a90a5319adfa7471aa429095bd272ff4d3df227bdc6075e0cafba54201bddc44edcdfd2317f682f40a25e582273c4845b550b17724eca81e89268eafef9e98533b85bb2c54cdcb6beb4d6f2fc0459a2b36cbb43fcbab720678553fc930063c64a09445ff637c12d0ade4acdef1e19e8481a0b7c2dd968a2ceb7f50efbb76fe21f49d8829d8a26b10453626593a694586a828705c5ab02cccd60e351171aea3e1aaeda07cd960e0f5205019766ff3afe124a47f4ef16f0e671e1968e662c7974ee54872538c7019cc5396f165013f4c482d400ed4ff5fb34189c75e92d336cb25563867215dc3aa195f736e06657c9e27f1468acd580ee51ca44220be83c215c1223758a7676d376ea0d0aa74b73032b85a45f69e6f8d4ec3efb6861d5adc35f57e6112dfa7334ba6fbd64b14498a89d8596423125b6486d9208937e9aa010831edcc168be8b7abe7ac21cae4794fe5f019abe1715d5d8601b646767d396e1b7fb8ff50aa43d88a2426545270093ce80be1aaa849dd2edc0310e3cb0bc13a23108776a44e3250fe5aa89b6d62159206377e03e302e3dabff9ecd8675870c7d55e33cb915d7e73b765d1c61f9ba0d504429fe99516df0534cf6a5ad53424b9be39e4835dfb301ae5cbd9edd628f0cdb6c54bd4986a9fba65f60e833bf17b461746ffcc312d9584a55c55c42c8e760d017be56f54a4e1423648c3877f8a44e3a56c21bf2bf85550f3d8a8f040c8c6687aadb2c4d1e1613626a11d30fb25340f5f14b6a7752c5e6c7b866b10f1155360f35ddc8f07ed591fa3366948fbcde1a16c35a589457ded90b69675bad01a1fa9386e68dd2001498d41033a6effe882d9e864ea7991e0c71b3e65c158cba64014f800000000003b38927526d5fc5a1b2f16addcd4aa162272f280e977087de02ec2969f10d25ea3de9a5d3d3975b4b683897bf828be631813bd5b949ddf9c3c5b103b69aa483f5fc46485bc7a5dd51a47543f57d346e680e12d9429ef7c21cacf407656779235d205dffae23666e01d92fb18c063d1bd7cd00935f029149c7e20b3d72b1b951117f0629b1ef1e49047532a59fd8bc1817343d45e832078806eb10304b8e034fdce70464d33cf6c66e857fbda170573a7965f8eed58e6cb7edec4e9f8a666fbca0aeeca2d4d161caae23005f6e0adf6859c8f1bece409aa5d44d285a8e8e9fe86365af4e92384dce318724443e8a95cc790df47cdd3e8aa9ccf19acc5eb19b4cb517c3f63e59512c037a66312786cb6cd2bcd4480e0a21ac63a83b7b9c84d3207a6410aa51a60d15b5526e3ffb4cbb02ee9f43f7ce316ef01dd75544224481d4b8ad2a8944928e2b4432812d1b20aeae3b51808028321588952ea70afeef1709eff5a75463a2201299484ecc421c8452e1700ca9f4932b0aba6b5d46f36e80f2f0297eaf7f44a79cbd21046ca53073ee60d5f2ffe2352b2538326e3e7ed851e8a62612a9b974ceb5757835b974892b049a7a0c531390a4455657b5b5afc5f0f09f8bf838313f403c96c4c2c72c4ced6e642e86b0eff220c1cd3388ffc902af68f87a1b7e8920d7f014e6cd2694b926fcbef23dc645cd75b051add0fc2f99c0346d45c2521b27a00a13dc9754306222f54a2b4f3058e80e0821d6c78e5e80a509525631f34c343567513636855d1c318c49debc651212938c487e069c390868ce700c4d19e1e52eb7b536e1568d03421c3769b920224113bea4d345510bd0393efa1ec22b87e973c663be75c84e7278108ada31af0311796de927257f59823f1ee9955f0f39b618054476658c165ef443d169afe46007ac80a0efa3d678c2707a7a001812f02dac999796872d3328eeaab4b61cadb8be9c4ee0ff9104d417ba71076054735c12fabd5d78f6de83a57f46b8d071e3c273c60a226fa6d555fa3580002cf3b6f3e50a8f5616eef66e7bb28523858315b3cde381003ab885ece89973aa4e228cd5da0d24ebd876097e7664a2b903430963517bb895435703029ea30081a874d15f4997dec3b89cd728075a0b21d838a57052f02fad03c1a3f74427d149c6225b41339a00dd764b452fca190a0245e7118224965942e3a6d798365c34631585288b7ac6c67346b1d9ab1ee7d24e8cb7e35f2d2b5401a89af6a1648d19f8fcd14973c4c2db543d772b81bc363e707bc534f00b872df0e3d4c73e9bc513b2e6c49e07d4475f251c21d60cf8dc2c9aed2922e4efbe8cad80db14531a63e629f4cfb01df3f61fc470123a7caa141f104fb37d2712628648eec56759bd59cff1da5e7cac043539a2040b6d364f1449ec104bec6f487dd1f784dfe377d070fe704bcfaf4ca99cabf23f4ac1f58afdcd7c8a58ede5023034cb324722e349135c0125f49a7b4fcb22d81d641c06dd0cad8d0bcadd5c4ab7c2015ad7f98b1e4db7b89dd2aa3d057b13456f4ba3b0d52d3d0c4efb35deae8d1bfa39f593be4cd8311f6e89ac462a116ab4776576c1f87b7aff41ddc728fbc601aac334148307d9a3be7c11c4b122045ef2ff913eea3af62bff2b71433f3b65f8ea939fdc19877e98a70c8cce6b94eb2bf4d696392183f8224132b004a29db1fc0702b3c84e0d345d82cd622ff9fcf567b7dd88163ca21a32122f7c2c98c8d9d0861c02548a831e5e99a064b2be13774f76669b80f90cf8c1c0749dd646dabd68d18bb6e6f84dd8ee32acc2edce1c7d02b3b145f416b54b7bbeece8087eb03f75dd317caacfe8cb2c4573f4ff9beaa2c5ddc75b427db079c7951b88acdb8a7f4dbde154cd399cf579aa683e30bb430533b3241c8703bc6576666ffd299fb4d623f277b1f8be372f705ffe594644eed3ef2bb7070e843851b11252ae8aa8414ba17c94e63685815376246361ddc46301c995a2a6857004376bdee9c92f908595977109a0074ea3a8ea89131454429deb02d6431e3514e50632000117106dba12cae3925f260d527a7bb2cd6851cc91e5d4162a2b66b88540c1110cee4672b23b32a9269eeb86063df9d076ece42a9c7938c6fd5d037a4e4ac46942c365c75b75aa08c403690de155f96ddd23a3183653a9db614f2bf069620be62842947f6aa8abc340140aea22fa3b1fa7fb552a4f0a43fc89b3790cd3721967624451f94983d90d65063d4d9c60bad78f7bb11bdb8e6af9f806bcb34d7fdb8a2da4f6c3bc27ce4a48ad529f6a5b6e055f35c344a1dd2d6a085d1fa5bbfe9fcf6bda46b320e02c864db8b574f165f616d48e2f12eb25099b5c90186af26d9e50f5058863e7f01c4200214e2969fb6c0fab8dc4ddb8475e28a21eb6b902d542dba5e4ad0b3b89b76ea777e6d9152feab5b0dd55f4f2d3db5f4e4013e8eb6f637f661f4f5b6ea8a73437437d14190bab1fc44df4fa78558c2b53e23283f4553101daf28f7c4ec5d9d93c47ace2ccf6d0514e0d33ea597b07f88ba4c272def6ba368f0239ba59003728fc20e9cc3e3c367a04f8faefb5a9725f0c8fa298aae306089908168cd53ea4fe769175863360f8838dbb3a185612d35b97aabd00c4fcc40245349196190a01f3b74fe6ac7f1dc854be928108bb23c67742fe4845b79b6286d99771d85bd9145b20d94b38ad9b273ccbad0ddeb5b7ba1ac322a20619b4d1ca9476ce741a0cca4c90b3b783f3b3d5064a7c15f72b97836db164d77661d415b12df263b1ad2e2efe92c5ccc50ba10c2d5d2debf89132649aa3163a23648f9d53bf14f183b920d0379ea04897a6b9245aa22ed2e4d913bace308307ea05d31753a43f62968f2653a6aad5fb483e4e78bbc42b4b853d92c81bb9c4c03934dafc8daf9ad16b3252d29028a9e5ea4278e928570c1bd112d6900df3da90a8eea441fcd1a73a1d982b010e6e7f73023dc36fbff9600f788da14b1410b31fff4ab2cd895f318aa9cc7baf9aaff1066ae4be169f663b6bdca53fa462174b56c6883e1b4b84df12b1f246de72e1af85f913000407ac30410149d1e4255ce94bc26b6ae62223f238be472f0dc9c812d137d88a7fa3fc0808693f9add9db0827d40d3dfca3dac9000a12b56d8803aff5517682e9cda163128fe166033397b79afee3f74528ccc31e3c5289812ee730cf5011ae15b0c86740644806048ac2282b7ddaed2e469c289cc70689a385e2c0459affae17a3e6d3815433363be215da2c110369a6ae12325d3c40340df4d77d09106f75d51d0c481bcf8228a4152c4dc45026f4e8de1270e04b60ac57ba0bf116fa003cc65d8ecc210e757365287203582608ffffffffffbc221f01e2f8306f906e82bb3b0952ca54890e06591275b726215e27c828761bfd601ce344fd29dfbfb9b37d62c86723a0d6a75fa6d2d8bd0c6ce822109d0ce816c8add2ea6343855d5e9ad63f3a730020eb46909af6d606ee3b5811cb807b9bfe2b2033d9ac8732b2b0eb9b28bec9eb6133f6c20b4c05e1dfa77155d289bbaa3ea6042e65326d32224e00b96f4a7af04461e1dd662284d566d6a9de2e435caca9c51fee6b665d6a1f641509b176cb29ff3fc67401e766f5ca1fab7584b36396eaba2f05e5ad0cbbba29c5372d5443f9afb4e2411f1284da03f9cbd2827ca725afe395024bc9436910053f8f8c4cef37acfc78cc05d7de0c77fc1492ef46469d93c49aadd42036c5fd6ef8d0c70d7c57e0e0e9f75ac94bbfaac9373ddc202f3393bc0f37b0a7769fca64300cd3594a29536692e575c9ef4e5dd544e108cad4ff895b24b431a86f1da264ede7b4b452e600035a38c902557b1ebb2abead1783765e778e7bec298ac9e021c82fbca82acf80094093afaa499f55a164237303d2ddfd0f8726320a0260dc2d59961c33c2d89ba40e65d46075b2d3206d76b27d00575a963489d2f168a53a0b5f04227d4cf935a2e82917c018270b7714b5598c838ed82e9ddfbdaa4448858db050cd14c500ac0e5fd566610e1d4ae2534565715cc96e499e5c190be37eea9d8fd23814658038fcc761b887568097da83232ee39b47e73c9ac854b8e70f38f6999e6f889a16ade97b9b206eae237f597f8ba0d2f2bf8f3794ea782f2264e9688a717f20431734d1bb989bfb4e40d3f4e8ccf1b8e938802a27402bd3a02d3d073e555acc5c4d941d5fbb3fef890b2e59a6a745b2e966c1903a988d586b53f63bc2a9253c7afb73f204fd3aa4a82332b0b010da159f29176ba146769d340399225d61bfad40ee21f765c641552d41b46bf5113de89318a6b0ab66ce02aea59ee302d8db4b2b1b4c71693b5159fd53627844f3b24288f585f536a52a3dcc4c71227b3a1489a5d31fc37e5a708bd724a889efec04c0c57730352493c5aead0eeb412b03a7514c24f4f3e659d529796218bb825c901da92869bc2b93afd359e24c8d55006d883e2380be6aa77d55218e831a7d5c4d566e293e4110b02ccc0508902a3d876dfd31f83b7b51b7d0d82d5838f6ed96ebb7dacf438526387a0b5053b522db03e5241b8069e9d43042922d4cb2a8c1112b05ccaae37e23511cdc90c6895713f7574f615df37c425d7cfa368ec72703a464b1d347c6db13d6496ffbb868594a330c213fd222a0ac618f1b312f4d6f5dd078ceafa20691aec35fd3b8d6479a63b82bff06a6eb619ae87ade1a5542b9582b1effde9e5d1db3c619458fab459ea2f91232089b716afa2de4ac9830830ce49284de17556de89400e2555960fee44db6379085636a5e4b938b1cd067f8d5bece171d463b432225a1290c306727187e1d2d482662c783736700be93e3f9304e0113d244e8fe4e1b38be3ec342a5a5c062cf1e20f3dc60f519947156221ee244b7e14c39f495720e4b727daf2e39c2e352b0a247660550ca8f82796db4e424be367d3d1ab70eb9b37649d9634c456d889354be44a45c61c37b5def297fc36a76d9dd676c2f643d997ab97b7735f914fbdd38f86508406a8de7dac15a1cb5ac5d9f90eb1f8b2301906c52d5c21674fe09e7f3b9c5990250efb5a890c420aeb1c5fe137755416d69aecc7549168876eb00f71865d04c946f11976cae4085eebd4e73be71ed8505470b0bfb446d735fe1afa33380ceeece76a8347e8fe2f58e34a579fd57468968d712218cbc99a68c3377a6ac542888542fc36fef2cf55c0a99266766abe6ecdbd00675c0935afe8cf8d938c1df6f6f4c849d72f354da1f09b6e7fc9b497544cf6930050d6ab8980e09feb965eebd50e91efebdb234e533372a67445de2088803328f429a8d6923899b849fb7f0af2132808544cb6bf99d0b18abe3df119bb5fdf5818e836064e5a0b329339c35ec7481628a71d35a7f5021001f72bc2b98a15aaabb4c5c462b44db100efb3a3589ec4b9f5e7900dc293443d9e655c8a50e51a00980be62f3821174c918500f9f06a25e109d3f7d63d588271a2a502e89a2d084350af0089aa4ca95be15133fac659f79df3bdde5384c2c25cdc4f94cffccfc125aba0fcdbfaa5fa9a18821f17a807aae39e4307f3b6d207a45f81877a988615473bbab0a580ae41e911fc54edd3b0cfa2391ba4c88945d2fdfd63c9a9905c2f847beb833d429af910fecd4a301e09244743d21439a66ec026ccf1ef1fd5f89d8600eaa5e07328c315205c005ed4caa4514df692a59db7b218e7543499323d4f90004398e425f77dccb3e35374bdbfc1daf35a4eed54758a1cdbe35a52d597f9cf0b3414d00d2dd5cf8dcfe51b2af90ddb2c0c59b391bead7b8fa2073061b4dd04406f2e7cda52ff000bc15dc02bf2bf22838e0ef641845bc4ce6c143d56e9a3b833e5cf4186978bf7c0e13b40e5e7f1d0ef28a3b388fa16619c13bb47d5eab57fb1c4ecc0b2ebfbf26200075b0cf5137e8f13703b7fdebd72218f32b8a0050c6633b5f1a3b9c62c83e81fc1c55741e759c1274d77a029eb7af4c3fd689331b69f80343332f541d1026a66c49fc5bd7012847d4d48be2b41064293785105872300f2ef8cd8f8b9892e96309456ecebfc893404da002867264d0a3caab84867488bb269e1ecc346d1ef7c1c76b6d16882dc5ea9dbee597dfa2d3be8e79091236dd750ad10a50e2f9f6adc1722f6131cc4986b41cd4acbe479f6ece8eb0892345662a2a0064ed74cd74957e796c4fac9c7145b0103e60750bc351f9d6d72faf2858ef23b107c07caff3940696ccf74e41001f17aa29edb068eeb6ec0b0bff10fab2571356ff5a3cff63767cad097f9dd4a5919700bd7e24182acdabf903171788800f17d5005dc07d6d5bed1dec81e13bb33196852dbcf978b45932bc28e60a83900502b11f09ff61feb208682500654cc9d2b42b60ecf99724bec398dd6829bd44a30151ab5d05c39284be657e7dde539668b5dd0b8ddcb331c4fcacb7b9c9520cc01c421c9955d7b168a9416e36c6e436e6d328d9e0fadd441fbd0d1d5bdbebbe9c19a3607746d06282c0d440ac8a243c47c27f04ac2d24620ee83fa6b1319fb4a137d1c82c436676f8d75f1b9d99b01c6f9cb4a91027631cc5717d07961179bac417ef8ae8bec969828872794cdda7b6f2e7472c50497a35782ca5841d5419ef3805c9fb30b8205f8fad2226e67048a4923de049ff3ae1f804b3ed33637c81e7530e970e2f51f9bc435e2d4ce3ebc8aea207115a4ec369a4caa7a3fc814224e8fa0e9a85f1c928ba24507d2ba16e176ad8cac7c125b5edef7d8efe1423c857949a1768748377a988d68098502720e75e138abda3f73eb9b2afdd50ef2f8d20ed5f36343fddeb59a8a591582d2d4c66ec0a89dccab3bc6cdc5aaf93a7518dd1c3a92ca486b6833bed70294d6d04b02803e4841a7faf9ab06a9c05ef672ba2b61c5e004bdfd6e490da458ccfa58be7dfef9dcc0dc79179f14659d8c4456045e48ce0039982580b9d7240209d4e5767b0bb391ef1f8929bf06d5e3c8226ecbdf8844902eab10f22b9f23381ba1b5f5c241a614b0a3cde02559669e0520ba5116f58e12fca16603e129e2e5315d581acc0d2c6ff9caaa7742b6c3e28d37f0766ed08a33f39cff6919af762d4ad2168614a190700aa87a95759951364d8445e680cc9ad0b75827810546a9510926d97835d62a65a3e5a375150b6e9a96fdca74a59269b2dd788320b96d92186f3226031684c45ab69c26cb754296a2a40c0026eb95c4f0b64db9872710d731d42c7510922dc4459600886d44586099fb957f0b6158ad703d11569699664e839d8acff3a5261f8b72cc43763f02568dea203b65be9cb06161a09d17203f168cd8469d805475dccc7c76ae2ef216e068f39ec7344f05c3d2ad794cacca891b3d0bfed335c1519203d289f74b896cb6c33c15ca0791ffeaf11c9d91b95438be68769f91d08997b77905d5a89460a3619dd44d5d92b5f88542521763c815ce15bf4f34c018297d777a602e27276021619a82a21be68cb5f4b321bca1baa7befd5cdffc80121a1fa379004f441148057d6f1f66863921c3bdd3117bb5d9ad52c45ac9a45391ec83cee3c6dcdfc40ddb3ed25a87f793430dc440a6d33218a04426b5bb7031d33b2439f01ab2fc2f64a43d2a482b1428ff5417d2d33c818166c20effbf46811d50d9d05f7ef1a37d249f64689cb37d8cbca2dd7086e141caea4c00b35286c9601f5f1cb6186452405c4a975e1c13cc10cf33e5908287f5f3fe36af89f374d172403dadf01bd06055582753b0a0a387361b91f233e6beb112b9b1eaf0a835b4d14c82477ef46868d09d03601a88f4da2dc7cef2a04a62e61311cc0284e8e48c571f622bf5ee95992ef425227d6b9272b6727b10005c53778ae7a6b155f3a7f00086e1e952527cee0d40ddd5e0caefdb19a082ea43d85dec0168d5641b570fbcbbe9058e49ed4dc546fec49d1c2041b6343dee68a09beb95df54eacdfe2792307c88b20408692eef15bb3e370ac877e927cf58ace1931e2dde4ddbd228de70fc718a5bb30d68e0196bd2d00c1a3ef138adf1640403c513c07a0e8aefdca2bfd3a9404f4c9af683bf52980c43d48912ac5347c438100eb50613a082270e1bdb9a1a2241310fcf422611ff6b67cca4c9988489d344215b9b8f8b6247903edbd5689733427c555656a916d106fe6ebba66c25c1c659d27f86b712bfac6705301f03584da09b9da428092504dae0bda0b95cb7efbed8224349462ddd2a6966cffc455ddf78d3964d1b320dddd31e3e7edd4aa40afbe0d1d01ef0b1b2eab7a266201b3ed078199c33167da82795a3dca83aa06e921a4802fc34ff1e66bf31b2e047734ae2eaf765184498e127a296c5226af7a7a03ab5815efd8ee2660a4ae67a26b88d90665f5143b503998374a0175f2e2f6ac5bd25f21fc62ff01bf96ea49a15b1585441c91bde7e634ced455dec7d3a6ba115ff3b12bcfe04cbecf6af5afb4fc5b98392d2fc2deb203ad0c5f3b7ffc2fe116d7a4c40487f5d56421b031f17ef5592e9d2f052fbd8e62dc004b9caf7ced9204fc49cb2ba40ab94bffebc09851f785230ff2137e992a04aa7f63305c9d2e3b6f07f94a09b17fb79eb6cbd5f76f84ec738e80b75a229df1215931a14bc22f14a7d85a2f2f9ba9e7cb01be437e6117178c7640b766eed27820449bb3a477d3bc9f75acd433701d2a01d2dd0d7d29deaafce62cc16b83e0fa72229c045af4f16d9cf33e1e3e8a137e7da245a9906e0968fde8037a6c6a6de0ca425650c10ce8311fc1290f02ad70256bec8a70501866c727c1abd2ec9e38bee97010e2f6727888ec24d15235f58458f6436545aee826d06569824efc250d8064406cbeb735e6e2a5c0c04b2fb267952091813646018655d1bc38828d4ff512fa4c127245ee0436ad4f39272cf0024eacfeefc8adabb6947d7ca619a5fdf16e45cce1bab1b93881eba5827332e4f6449871e1281e94b61e8e4a0827314b502af91e4dc372034dc4a76beabd158014fe0909c4218308ec23258a09de7c2761bb90c07736faa900e44c1d46252fdeaa69dff7de1b235950537043d28b8f55faac068f7cc307716524d691d11d2f9243ed14b10686e7ad6507d91ba599f76e4b82b8b7b3aeb91355cae7595b913b280b6e2063544a350d855e06732d72bbeae44c4aeb3c2617b137ae71ec54f0073b0aea31ddc7f9cc230542410be56f25ff12bfad25a02753a051bdbb793fc1388ef1a294b525afb5d1f00909d9b267ae4ccc7e62cb6418edb56a9752619ada13cf24c7c383c68f33daf425bca04b9b991cafaa21932e248ede5f0ba666ddc92dfc894627ef08847726002572e51a952e48c875a9f3daf5529b80734622d2ff33c1361dbcf2db76b5a76408eaf5060428763de6150cb883997488cd2936b1f92ff9bbe5eea42c55f090e11affba3154c01261267b65ab13ceebd58ed5676ccd1340e922109ec3a5b7dc115511486c308db7de52b192f642f2e9f5344b66e57d0f380b2bd318c435a9c095db5133ed53c9dde09879743b172c3f3464a0526cc3083d04c8da3b467eb9197d696e3888e3cd59bdd01261b529eb7da5ac57143c130195f5b5d7c0cf75c2bdbfc9e98b56b449f8e9b4eec249a140a3bf22498bcba318c35a7394acd36f79d67942147df440b6c249ad6f4a650ad12479fc7dbd474b34415fe6ed5b1ae62116f2d0738e84cb74814365c2eaae75d75c1e97ed02e65012e3f78505e42017786cbbaa290db6104da5df3ce5eb84dbe2f4cf2a0a36e5391814e4d05b2fb4a876636367e9c44fc975e77e4f56e62edc1cecfe6bc75550c00f2a0d3629f3b2314cb8dbda80b03437fd88eff616a3a4a03000ba3936b2d33229b09823de81235d67577d92e61a9bc8f31f5656db69ff54c97c1e410d2281c40e8ea799a3a8fe19383398856c12fa95693d545567d3df118494c401c9d77236045bd62a651af5c4842f0b119996312a2b555cb4799bec2890ba4a4624ce3eaf38e988510a7f5bf9573611d0b9b88b8606cfd1b7e57355a28110f9f0a8b46a2f235f9470ba45f0063556084640f79d837c8071b34408ff7bb78d08ffcac535fa3de0685b5daa94a89ced1a1c6d32ab63bbbb1b50c1d6033e9e4c377d5eccd0533b53587f4728291d7bba94c9dc15c64df469f29bdfd5cc621fee43bb33b5969111de0aa7cd65dcf0c927edf37ca242bc64f810c9c7c6ea9652f876d05219ea660688d07d7e0e85625e47afd3652b4bf13d5e28dc94076b12f7640edfe303bd5a1dd07ddfcd29675632f62843b8268a3291f38c53fb115f5325f8e71b5f728319296d7181d8dd5df7524b1d0908edc699c48fa5868f5e7f6015f649b6d82998d43e061cf94fbfc3562c72dccfd085fd0842be56d141c081d4431d7efe66c3c9581e68f74c739bec99b003890c5f9e37497353d6937da0a355128c4ba0d657177518157e811454c0000a340b6ea94d644fc967a3b1934806e4ffb2b6c44fd68f0d0771854cd92db6a4cacb4a51cba72e98077b8de6867885151c9d5a6875764e230f2ca135d546f10057a2f243c0227c92ce23cb1c219cc8225ced38a987ec5c80148bb8fcd36c5fe12d1b097cca1c669739ed04641d14a5614852b71e600f39f100b48bc384befa6e9184eda4515f30e48f2d8e7da182994a2d8039a5f167743e3a83ae225772c31dc15ed64829b285dce99d29d8ffc28b77bae6a5db570b676327eaca9a081330b3d950b25cf9b0199dbd9d734407a7b6788eb1c7b190b326161f86133f7061573dab25df10bdb9ad0327bcd8e6376d60b011265bb48603bf2730e8737fd3675bb1fbacf0971ac3818eaef2e48d264d80b74033992b6dccaa3309b771cacbabc31f1b5df9c5ca982c8cdc813956b9c7afa7651e781f31161bb61e68141b0bc9bb46de37e468170cdeaea20c730b81eaef4a7d51506a6e8d40e6355aeb1e3b51d43cd39ff4eeba80cdb70a6a0d85dbadcd64a80898df76cedb8506902f2e63206225147df250d4226fd9cf1c6f5cea87167a81630d7234e4048216a7758da572a26702d5083b1e1906281bf92eedfc2f988ec2828dd7079430bd2f0111edcac208beea9c4bb01ad70123a7d335d191fabfd6c637e9899fbf50262addadf5a3cf4a138954738b456bb9c8605625b2aae94128991e91c0e62828ad204e522ba6a55ab1c3064d56514da5c46943a1d8421fac70d584daea333df201203be96e5b6effe1725e541deedbedfb1c99d73d857321b5c79bc7e5078d34763f5ecdf30bf8ce3509263ff8516cc11b0d4e7892442f6756e23f05a98759de5209589c86c716d28ec30376b1aa2603a35615d9f712aa112c19b4364cdd55947c12dd8704ed1e6d804a6f3947fedb1c22e6b5d9ec4182ce82248484f1c077d8fb18ea2633caeff87daa396089a27078c0670fcdaba1d61091e2565950799be18b329f57e4cf4c80010c48ce4d970bffb525ba672ef04cf1ccd1feaf4d91a7f4b60011945364a4888d78e0538abfc2c85c4079e0895718a5802098fbca9570219d11d695164cc61e58502be4f8f3a3a2f4b5765d870ff98bb237b86180fef9029d0093b7fe806893d1a25440698b239a1ff3db8f7c8a687739f3d180d81fbe75bb323585016d69348c8d20c9704547fedfbcb90f82bfd3337e280f81fa7cefc7fc2b71645de84bb5e75a52227b773ed01aa743182c1716e3b8fb62984300696c2c29a14cdeb8033ff2952105b54d50e4a2bfb590f59a794dc6e3cd293106f806e838451e7a45d953a214dc1d630563b895880aabfce34ce9261c87a6be925eb37316382a0f8c5440254be1aad69e7685730d42bbcd0576627c38848bdc92b16ef61366fb6632202f483f25032043f06f85009b4e13015865a387bfdd7c6aa4436b32ab04041848b968bb97e0d19a0c0e0c0899c1f463547e9250ba8d13109dc52e216b614f1193a6f44d58959e8b4acd4511d9d1c4adedb9aa9c3cdaaa5e65c6641b8194bca4a574ea98a907b79f0e10b1d729c9a1e42a87b8df7abf1d73cb835a3df2469b47696d9512576d9aef15ae943e48cb86c535bee7370589f9b288f1062f9c16fd7d5e9033b8a1efe20773a313c68ee4219f9d449fbd9e67f55d276f6a21c305edddfeefae11444635ef64f2a9e69e6de505fa9dc82822033265a1d86a1a301695d0ae9310d9e29b253f31af878631b6e750e150004b1aea96be32d6a4380e2952c0b67ccdbc2d363cac6cb66bde674cc0e413a195459503b78c9ab8a606da64a170c63479a96dd3051b1e97153be047747cb20fccaeac1512d28b8126136b95a4379f59382bef28ff51f6b04ff085ee6762b7772b81dcdb4efcb95b52175d52325c8e954c6864096e93b87ea0cbf575ac028eccc698a5fc6f4a07ceea0ade09f88abd662057f7fb3a520d2c473cccb2a7047fc28f797936c16d993f2011e9524fca9d46832acdcd6ef1a8027bbe285d916bd31617d59ed53c7e1289661106b25a937c68e755d23cfa9491056c2c3e12c503c4d2c72ed942e55f2359243c85569cc240b7d9a81eb5e7836431cb4b5c5e26fd627e24a9e7d1487c4e7f64232ca1f23048158092016ef5e7647e0ae4d313a6422be0e998446fbf79cb7d70b33962e0f6c2ceea814a8ce8d8ea72186fec4f5dcc63ef82a577f5a8e84579623f6993b5b6c76e4a5390b5557d7b8a085229827c08f2ee968dfa49997e59ed068d4118b0339605305b8a2b1ba3a54cd9eb915acf75eeb0748da73e2b20c81de83de1b74181574e8648315a12a39276361845bbeaad5604229d7f4e3a08af4a9eaf93fbb8db90b0015992587e6520cc603516374320ab70b61c9ac5c1e8e81c97b1fe15916f7791b7f657c27f5fa5c0db41245a9615a4b50d3802fbdad494b6eb22abc3bcf030622c7e4067dc6941b961ec685fb554acde232580c42608d4eb9c0dd0659567348696cb99e33efc5063455cc0820f886e4b3b2cce680c0f77dd77098eb87d7f35474f1e5f2dba3329dccba450c6f97f5d2298056afd4218aca1ee835621896838a791e2e04d17f0b4f7f3a3f30a0fb717e054bf11f775e20d7a5aac4841c31cb8d3570855504be775c4582963bb2538189e204a8bfdfa59955a2bac2705dd78a6f8c9f3259326febcf70a337166ee934856fc8234a2d61b044578b940179b590b40363159538658a9b39ce9d39d51aface156c9149f47912f50dfb5b8e241c2e60f78bfa45e2996a981bf51afe1989bb2ad6a8cd6ecab3424893eb760aa4ac1ad724b15d7859915bcd9d625624570e454b5e1eb69b441c729d42a2755bfc3fc8d7e7a5c38fc07b576ae9904eae0104652be03e99b8e98183b175596708f40aced3e814c940b590a26d34206808438a41d169a6a33b6b47f3d3c4a2c8ae643d8cf184833cd6c9a0de44070557be274e0cbe89991ee768df8a98bcf180159187fafc44d9a91e3fabbd81e2d66ea303b963059c215562aba48b8e76c215b06757bbe70d2452fc57d003f4a5081fc4c4849bccf0ac8cf9504f34fb2c383eebad5a6d105c16d83a902b1adbd347dff749bec214d209cfddc171b6ee5ea3b201c07c622d2b7e4ecaf989ff8ecf7b4682b83b0c84d0766547e77ea1d63cb8e45e86b6df0e912b4ac70c3e15784484d714f8873e91ef724ec0b5396e2700d35607cd73847cb966bd95a18ce5b3d32456a76cb1a96172034f8391f2b63c305132e745cbe5426c5c31a30e77108459507674ac0aa22c2e6df15f11285529ddf11e1865d4b3616fe0f04aa186eb8d9cfcce8440fac9fee9cf0fc1872f4a0ad28236f3e66d8123d80d08590d5ad6d31dd69ea10b762b3698ece119d190d53f004b65c947d46b3967db026d76b9460bd78f67077eb78e8828f2d6a2fe2452ccbe006f201977461bf38e3b136e04293b65b07bb1f08070bbd8cf284b76ee4b21faa01c880ee6376b9746f03c9ad034fefce1fd5df27ad9073299966771be915e68636" + let t = readZebraTransaction h it "Sapling component is read" $ do case t of Nothing -> assertFailure "Couldn't decode"