diff --git a/beef/bump.go b/beef/bump.go index d5f1b41..db42840 100644 --- a/beef/bump.go +++ b/beef/bump.go @@ -28,6 +28,7 @@ const ( txIDFlag ) +// CalculateMerkleRoot will calculate the merkle root for the BUMP func (b BUMP) CalculateMerkleRoot() (string, error) { merkleRoot := "" @@ -56,23 +57,34 @@ func calculateMerkleRoot(baseLeaf BUMPLeaf, bump BUMP) (string, error) { calculatedHash := baseLeaf.Hash offset := baseLeaf.Offset - for _, bLevel := range bump.Path { + for i := 0; i < len(bump.Path); i++ { + bLevel := bump.Path[i] + var previousBLevel []BUMPLeaf + + if i-1 >= 0 { + previousBLevel = bump.Path[i-1] + } newOffset := getOffsetPair(offset) leafInPair := findLeafByOffset(newOffset, bLevel) if leafInPair == nil { - return "", errors.New("could not find pair") + if previousBLevel == nil { + return "", errors.New("cannot compute leaf from children at base level") + } + + var err error + leafInPair, err = calculateFromChildren(newOffset, previousBLevel) + if err != nil { + return "", err + } } leftNode, rightNode := prepareNodes(baseLeaf, offset, *leafInPair, newOffset) str, err := merkleTreeParentStr(leftNode, rightNode) - if err != nil { return "", err } calculatedHash = str - offset = offset / 2 - baseLeaf = BUMPLeaf{ Hash: calculatedHash, Offset: offset, @@ -98,6 +110,31 @@ func findLeafByOffset(offset uint64, bumpLeaves []BUMPLeaf) *BUMPLeaf { return nil } +func calculateFromChildren(offset uint64, bumpLeaves []BUMPLeaf) (*BUMPLeaf, error) { + offsetChild := offset * 2 + offsetChildPair := offsetChild + 1 + leaf := findLeafByOffset(offsetChild, bumpLeaves) + if leaf == nil { + return nil, errors.New("could not find child") + } + + leafInPair := findLeafByOffset(offsetChildPair, bumpLeaves) + if leafInPair == nil { + return nil, errors.New("could not find child") + } + + leftNode, rightNode := prepareNodes(*leaf, offset, *leafInPair, offsetChildPair) + str, err := merkleTreeParentStr(leftNode, rightNode) + if err != nil { + return nil, errors.New("could not find pair") + } + + return &BUMPLeaf{ + Hash: str, + Offset: offset, + }, nil +} + func prepareNodes(baseLeaf BUMPLeaf, offset uint64, leafInPair BUMPLeaf, newOffset uint64) (string, string) { var baseLeafHash, pairLeafHash string diff --git a/spv/spv_test.go b/spv/spv_test.go index 02ba6fc..4211fb0 100644 --- a/spv/spv_test.go +++ b/spv/spv_test.go @@ -2,9 +2,10 @@ package spv import ( "context" - "github.com/bitcoin-sv/go-paymail/errors" "testing" + "github.com/bitcoin-sv/go-paymail/errors" + "github.com/bitcoin-sv/go-paymail/beef" "github.com/stretchr/testify/require" ) @@ -13,6 +14,10 @@ func TestExecuteSimplifiedPaymentVerification_ValidTransaction_Success(t *testin t.Parallel() const validFullMinedBeef = "0100beef04fe4c7c0c000e02fd460302d2e6252f996ab1a6fcbe8911e8f865bb719c0e11787397fd818b5bb1ff554a3cfd470300d67d0a32df0ecd5976479f068f19ff671e0a285570b915bc6e6658e98a9c0e3401fda20100eafe36c6f1adef584b1d199286c5024a4791eb16f35161c4b69cc119c1c9493c01d00077605d020124b1f6e039f1b2ccebf3e46acf45584bc559b654b57179b99d906a0169002c4fe7d1d2b2990df28e5132b059e10cc6ce9be85a79f834546eee881a8f968d013500a187befab2d1cc22004f96045afecd929e2edc7017a044aaf0f530847afa1644011b00bf5108b8176d4abba8c80f935607abc6a6bc38b9461c86a812369975ad2abb1e010c002efe8c4f9a630b0d0f4a410d93523d7003085dd166248d6e76f405fe8fc606720107007043c5b1be3e6952859bca6d6320f5a0f6c5bba5d5fbfd8a195f1d9ec4e0964c010200822378b29fd273a3bf38a4b852089e8f5a1251b5fedeee6ee2f548c0ee93a14e010000788ff2bf42a41c2e32bd59504fa59fd8b2ab0058430f9d4d2988ee8341ccac1b010100470c98a5fb48ed000ca746a05c7d398d2b76efe70a65c67c1cec14a8c8c84cce010100de821cfed42c83ab4dfc3fef452ec5f4086d18fb7324c046826cd51e0fea2c8b0101006422ad7eb4999dc4ca89a3488862f03b4101c32ed49c19e3df7563958e6e480201010087ce3715a94573ac7746f3b66e4070d313b4a8df6114509678ab08c425250b06fe137c0c000e04fde00a02827f1758c64b4a0b1226c54316ddeed4618500f026602ebca3cd4b96174a690afde10a001a906867a2cbd98095453400107f814e5380640443bf4504eb6fe412acba674bfdac0d001f3da43722e72c749846913dbce0623b1d22fa8499bbca49f3f9aec4cd5b3d70fdad0d02213e4fca3103f812ffcba253caf452c6811947ff6f2fb99b4e18baa1233e84b602fd7105001399fab1150a4f8013dca738bec4ae8c5b215e301697d6453f648230b36cd431fdd70600282c33fe4ec70f91818781daa6a97e85022bc2031a370202a385f2aeb9086a1a02fdb90200fd35a389307434d05891122dc81f3a5246f577334de368ebcfc15836648e73a8fd6a0300ed1732da6c0666a7270d63ca0d4af8ba1c9a80c149bccd5e1ac039159418740a02fd5d010019dc6865859cc67245c5d9b04bc3a9141a4e6fda17ba33d24271600244b2dd35fdb40100ccb07e295f3bbac75957015c58c5f7f64be4904865c95ebf4181c40d0089429602af002d31340de572c9cdbe9c75c62474ad3130e417d7a61b370aab7345901f69badfdb006c6b6e5958eb5f2ae497e4b7d8ecc90ac614856ada2458f35e1f2880fd155530025600efb95e533fbed11730d7eb9f2c891a885cb658f4ca058fdf6bed8d348c9415de6c0056e17aded7bd785e6a44cf023a294440bd89886dfa5d48ce28386199361e4b47022a003c5a68cac12c161d6a3c5a1e8ba77d9df937954a3c5ebb669fc5d3f04883c22237003978958e578f7326e8271b058ad60c85f1d2d404bdf75611ef9192de27ce644d021400692e79f2246540d6526e8261bda1b430f218be172a2672ae0a58e5fe20c359331a00595cbb11c5591f7630c31a779fe71b5a48526b525078a37492b087dcff4f1314020b00d6a30d5bccc4f3d9387e56e9e1f32de9db91c52c8fb4179aab7732a38df8df600c009fe2e3698677771d5fd4819796ee8342277ae3bdcd68e4e38ad3c04d207df06d0204007635530acf3aff406ca2ae825aa7253c3c1fb92cadf0124145a4565477c9198f0700f1f84a4c5efaeb4d5660968aa9234db2a98c5bca3f5942ec1d007dc2d996822f0202003578890ece8c5028080f613c01b8662df60c4c5ea6cc858e35ec266f3e8c8bf80300d2fcdb70b5967e0b53341b6bcc517511aa977ec6c98e587035e734bafb2df40201000050e8890913d743a6a49e244dab275bcafb7ec2fd8828163e6a07560351b77b2e01010039787d0d5252e1347883ebcad07c141448e366d2b40d3241211482ef52f34d97010100278ecd209c80ea49e6581c8b9e03b118e66cbc39e4acb14b26bda7d378fe2117feeb7b0c000f02fdd438020dacf934645c462a155ca35453ab578e7d510687fda689a565e000fc4df11cd5fdd53800de97bf2bdde019a90f6c784c3731b71a45ade39a58c436e2c70a4c9f83371e1d01fd6b1c00aaccb26fe28312165b6a2fd6414c651dd178a8053324d25008b8f533af7ad30a01fd340e0010cd00845ba8b3e5e08a057de308885b01ec1cb2f4cc56da6583ff1f3f9d98ff01fd1b0700d712139ba223278e95809bd1aebd6d334288ef66b989116a344485c603e9998d01fd8c0300097e0e68b5f5aab8ef48a8983b4b4fa992d80bd4cc2fd2c3069be71407d73b0001fdc701008be1cc85f6bb068b86ad60cfbd321878c2774c99274e953530cf4d7611227f3b01e2000453717a6dee5b33d9c379e7b262d17ddcd6267b159fd8a0b980603d03ce31b601700050992dd58d2332d87df4874852f9275eeb9c7813e1a6c1e1cad1a74a9e5560a10139003fdc83bc63d0af296cd6a71e45355eab21634d829f6b17e769fe0d2308a99484011d001eb98912db04c69f675a4cfb64a57167d9b136d174c0d0e1f2635840a27a2819010f00b0a43e31d356c1ccd7cd1733f8bf5885013361d7f02627629136b360c55aa43a010600a7b2280eb6bc6f398f7f5423033bd011e819caf0beeb248f26a1498fbc7e4bb1010200152e881046cdb491d33c93d799f28e07686708db2cdc8a3011c375f7b9bef87a010000851add544d85300e318ec60be010f38f2bea85cc86ce5a972df28b94e53f5801010100a7308e947ed378dcf6e6f79ba0bb8d062f7c7ffcc025e5d08fc30a3288e87ef5fe1c7c0c000e02fd5a1902e5232220aee5069017d31cc30818bcc971de3e6418f6e62b8cc9a3430d64f3e9fd5b19004359d0c4ca1b47399960cb57ff4b0d2c850c825ba56a2119c3ff875fece11a4001fdac0c003c0fd4b7a8621c97bf7b6adad9569fe1f07a52c41d472d1e3407f9e37b3400d701fd5706006400dbcd6c1ea8a5c8cccfa153eb02076bf03b4ac7fef38db8e3a5032d908f3101fd2a0300ceac7150203519610ec78f93d64bbdc2e76e9cfadb72a83070d5fc72c8c0291a01fd94010058dde4e9d746faed13b29bd0f44ea86cdab712bc3d430a88e8cec22364e19cfd01cb001f77543e1a81dc8d4fdef4a4b132cf907b8a22de393400035a40391904fcb5c20164002cc86783ce17e19b7a56e0d08ba4c5d94cfd586771dd28e2fe1284d887db1285013300ceb2afce84f3e257bce737ebaef9ded331348d750d17f408c22d79dc8e9de9e9011800d939fb970c2044768981bea25d19be80302773a4b0d469566315258d39db5059010d00c815d2c629a1d419d6ef3c33a670da1bc64f7f23a840365fc292aab7d7b4f770010700828ced5731867ba622104fe64bd18a2132097623f8fe4a834537b329dbb6d06a010200f9df4e876faa4ddd9f909bfafed085ad24297f80003a3700bd13250498e252190100004834f3f8c1be8c4f43bb61dd6d0eea6ab996bae149aefd5f9aced05c54b3395901010036679c2ca45cd1d37b4b0d1d4a9a0e923d80f6241957fd61969b641ca1a2b62c060100000001aa5df6cc8e5f41e8770d222d06d2dfdea647769871044df714c99b59d3528858000000006b483045022100d65cb97677ba806e752d63ea988faf5fb00cabd0df78bb78fe9f42a079e7ae540220158a2d51ca8b03f18691eab1c4fa5e85b6f21846df9bfaf797c995b1c9f34e47412103597c97b42c5f880e27eaf2eb2de0fb0fe5a81d689c646b2c6527acbc9c2509c7ffffffff0264000000000000001976a914e5c8e12ec010e7bf318ebc94efcb887ff751069c88ac8e010000000000001976a914ae791b7e9d0108b4000ac4138c2b47d8cfea404288ac0000000001010100000001a25525c35101ad7ad7653e16d5d525762f3826e4c7b87077a096aebabe292ad9000000006b4830450221009fa60fe23a004850fd671a834534b278d4a2a9a4e7d8dfc0e4f9ffcb2899c1ef022010a8e718b608dfd308cdbc382e6f666583c8148b5f70819fbb7df1f1edd8cc164121023d72bbb613c7e8a4230c080ffaff1abc038df9008046b2157f888f36f427d2f0ffffffff0228000000000000001976a914596ce4dbbefd792d782ccb7ce5652726fd0c676288acca010000000000001976a9143e8a2536d8bc8f2a995800f16e068ee85aa1939288ac00000000010301000000017a7123cf30268df225315c47b6ccbfd3e4f5c19f765bb9abc8fbeed134eb0b7f010000006a47304402201715f13c3456310f7b73386ca947621b53f71f27d2a23c0d1f09deb4b8931ca7022000d9c8daa400b1c2ad34df4c22e024e0d9191ecefe83160f47fbf53026fb4d53412102b6f13a7f2599f7312cf55ca1524bf9ebefeed22daa1f80ffed82df038db0167affffffff012d000000000000001976a9148e4221cdcf3f547ffd0aee46411b40a3248fdb3688ac0000000001020100000001a25525c35101ad7ad7653e16d5d525762f3826e4c7b87077a096aebabe292ad9010000006a47304402202ed74a7c67dd15fa9594ae600775e3a289511ceda7994b7914bd94435a269c7202205767d4deaf8db2c7c3a862a2b0e8f43f377a597bbbbed10409819bc2239064804121024ffdb4c74d0f3e92dbfe41348ee5295a8a8aa91f7eea1c17c879baf3d31492c3ffffffff01e7030000000000001976a914424cc7a221a4bf81790a850014a5e1a1663d3b5888ac0000000001010100000001213e4fca3103f812ffcba253caf452c6811947ff6f2fb99b4e18baa1233e84b6000000006a47304402202b577840e0fbab66a150a79feeb9ea2e0469df83f44a4aebb4779c35ea1d7b5402204764d20a211b112e8907a3a80e418dcc933ba4e49dea7072bd5814cca8a76e664121027db94b451dafb7368da30ed73abbf064a622ebcffc1bd3362802fd8eaaf5fc6dffffffff0163000000000000001976a9144451354c29626cbeb4f130e6bb7ddd54151c6b3b88ac0000000001000100000005d2e6252f996ab1a6fcbe8911e8f865bb719c0e11787397fd818b5bb1ff554a3c000000006a4730440220179e09c88dc5d83e6db5abcf2a46c989ba766612f3be664f66f9d5932681b42e02207ea73be5317362c511e76a40f3b416ca2ec99ce891bd55fbbfc60f3e2598c1be41210277e25e8e4ab96e46d94a037411d195b537810b1d7301c2d72e9eb40bb47aae34ffffffff827f1758c64b4a0b1226c54316ddeed4618500f026602ebca3cd4b96174a690a000000006b4830450221008a9418e0be1b65b45ac27449071bf8a7cb55d9008ae5c8d28da47bce9bc2cc28022056aa8ffd170eb4b86b2be7da81b1d01dd0f026d0488645c3b27f6e521eebb51a412103138a3aac623a5fc9789cd9476efad0605dea61f3e7cd5089195eb0b446b6ab4effffffff0dacf934645c462a155ca35453ab578e7d510687fda689a565e000fc4df11cd5000000006a4730440220147729079aef1449d0c1b08f79c1fa4749d685190d0fdd25801725845d0186740220796be61c7a059e65b4e418d1fec99a596ea565b179683d334dc7a2e2312ed466412103ba49c495254796f5ccf0e28f205f62965fafc33367b2b8d6609e5de30c206ad4ffffffff213e4fca3103f812ffcba253caf452c6811947ff6f2fb99b4e18baa1233e84b6010000006b483045022100e5374c185ffb992bcabec480572427f402911cdaeda92246f2a94813a32f33ab0220676121e6bd049c981593a8093f779927cc95bdf56d50069b7786ad9b9fe528c84121035d1d732dbe247c0886753c84dc3d2fc96a9eac26662e8664fe9ce8f67ab6dd98ffffffffe5232220aee5069017d31cc30818bcc971de3e6418f6e62b8cc9a3430d64f3e9010000006a473044022048e3532181d848dcf69a4da9b8ae296b90b4660a27f880b928ce15e9d3c5979e02205cef48653b1defbc2a87d93b268693c8d078199b69eb5bba32ba10f301727bf641210343caa07997898400cefe7a28445b233d30463d13359c1d87ac42ea5da61432a0ffffffff01ce070000000000001976a9145c21ae83ea5892dea33b9b002eb1d8450b581ea888ac0000000000" + + const validBeefWithoutLeafOptimalization = "0100beef01fe41800c000b06fd2c0402e01e74cab9a0571ab5a7d86794826f756a9c65dd0dea3bb3720c4051c488cf50fd2d0400d9060c543afb1c0faafb96667ed788324d4d1c338142a0841fe3ab9c30922cb4fd90040208c461a39a8877db46472f5cc59e5a108e417b1c9ea3091b71b65346d218f471fd910400ff8fa1e395088748feae2d7729ab9d5da0225f5ed80b2f295625f7c77da087f4fdcc05022256c94d07451664749e440f55cec8a37da1c46cf30a97579e2f9696b84ad484fdcd0500aecbe0a519d483bad8758c3a69cdc0dc12b19a363fded579ebc993edf510746503fd170200dd5d795e63f8777ef7a82453946150946435e52d4076089ce0cb15d8a1237c84fd4902000f3311a938e3f7977bb7a2db5ca912e4e0f26bd12744051333cd22cd3a2fad89fde702008695a1dfeec9393365a21690b089018c9d7dd94bbbf85b62f48701424e0e611c03fd0a010022373d021864aba56583c796bf9131c804a2ea40acede728b279af38b48dfdd2fd2501005e5f986a28e1cdf2b55b6e5bbcfa34742c45e016f7a920518f376c4b0cbfa868fd7201001287267e0f74f28a0dc5e3e0376fbf28c5ab06424a4dcfd02bb7a65b62d9849d038400a8109eb92b03a106ef15c9d120d7c34ff07ac280636632561e42280499f020659300a60aa07079a19a3600e7fc87cc6a72455f0c2f2735dd3d4039bdaf498469c4d3b800685a26978dfc493d1e03efd9a1c9cac0122d6d0bf027b523be85a4e2a2df3df90343006f78c5d6f4372c65cad0546446bd893db8c47f65e3eae2803ced606f4fd272924800b4a9bae40c785222f38e4127a169fbcbe45085b3e9c59d9631032d5a48dab2a35d00559d25e90b990524eb274251a22508ae04b36125dc894c4e1be21c43c19ab93c03200046bc3f2f79d2aa7da31093e690bb6c10a011a67f2a382937c5eaf423b903df5325006daf88be61cc906f104ac405b04d19f4771a63857a25915e376b53250abe112e2f0037461e9fa1f435caca254303b400b21cc452343572a68ad80d9d3287c2bd8f0f031100f14eebaa20670ebb3d9dab73d074550e3a93cfcb29d90c56dcc205aa8b6a51ab1300597b51a0440a0afe4c346f3b89c5f7aaa7478449f3eb6283e1e1f55b24e54b3b16001009f8ce41536d05ace952e35ce67fc94da2e97b6550f55fbc1d5aa5f3266829030800b668767e12637b80a04de0decb4b96b980b19bd0480557adebfc0c6a46cff1140900d24cec3667bedd9ff7e8bc26dff6ec5fcf8af5cc09f500cad08fdfa2ab2ccf870a00ebea0722a541a4f9e7c4659fdcad062e5806b8abba40cba82eba6882896a763d02040036de4d36e7fc3f273ddd83171a030a19c8668a1f5e03dd62ad53866f3afc127705005c9dc967c9a6dd0dd9c80660dd8e86faa3d7f070ed086f1b2d137147d0f52af00103008e9919d62be144a097dd23e1bf924b2e468022c12ccf50db6ceab3d043cdfd8d010000ae98483a460252d92b031d49f591d571e29f1c8b0ae9e2596e4cd24b1c549d3c0401000000019ed68f94dfa952554d777dbaa9e5c01acb3df767e40cabad7b6fb7547bfa871a010000006a4730440220287534d6ff51166e014ad91a2b677be4bd88cf08785624006cdb66553eafc8cf02204862f38e9d2982a5ee95a7850222f2208bff38637349ecfe41abe185498e4ead4121035ca1a2c6d2b46c61fd29e7697018f5ce2bae1ae735e23627046a2dd17ca8fb24ffffffff02de000000000000001976a914f5c9505bf02a4a2fb591e3568183f9c53cf157be88aca62b0000000000001976a91489b5e639bce3209e0888ea8b7eb4203de1c6148888ac000000000100010000000154aa46f1b3b7bde36c02e293b74d53e6c6eaed7411d286183b1dca766f42879a010000006b483045022100cd21d346073b4a0788018ff6938c44395d14cf5759fcc35a0899a8fe35a3c2a0022064eb9a005c3d0be03b61ab0e1c8757ed566dd935dacac37fcd1452adba4994b541210272d67492c31d0e6bead28c934fb1c9bb50ba9b46f886209fe95fb6a3e43bb27bffffffff0257040000000000001976a9140501308b6409cca5a7b5768c18ff2de8da4c1fa388ac39420000000000001976a91417e3d89f4aeacd5b4929fe04edc32c79b6182e1988ac0000000001000100000001e230ab1b300ac3ce334590fc308fee93ddbb252f6e4645e0a20f7e30dd541289010000006b483045022100a611fdf01eca42289d80e1265584e5bd487faa72e6142ebbc140a676f7c5037c0220409282aaadf580f458d97d61db43c94ac343e0b40674a80fd3ac47f43fd0c66c4121020a87e70cc26f7d5fe775f622d2705f27cfd6f5d2b574fea75401d6412a58b91affffffff02d2040000000000001976a9145d2117c4f66bdb335ce2707a74c46fa46d02cdb388acf23b0000000000001976a914effd80ee9df812990a8d7834fa8610491cbeb91688ac0000000001000100000003e01e74cab9a0571ab5a7d86794826f756a9c65dd0dea3bb3720c4051c488cf50000000006b483045022100bc7fc6ace1a5b1ab8601599d56b3adad4a11b7f11757f3225e96b46ca1ab7f7c0220324d6074aa987a7c63c404ac5b03c26e55d3c4209e298b4ca9df0e90aca43ef3412103ee05b34332b5662830c600b73f9c908bb8bff1813bc9b2690e9cad00fad23d3cffffffff08c461a39a8877db46472f5cc59e5a108e417b1c9ea3091b71b65346d218f471000000006b483045022100a936c496423ec03b1ad0f3bfe2348572d7b29ab14e4435c0c8e2ee093d930fde02203d9e86647ea18043c150289f74c6cf2ceb9ca3b228ae31c7b19c4eef813fb68d412103a19014bcc672ccdf18abb6972dd699367baed89c29b704385253ce2ae0eddad5ffffffff2256c94d07451664749e440f55cec8a37da1c46cf30a97579e2f9696b84ad484000000006b48304502210091b0bcf2e84d9ee65de437e8396b379941345e4cffac331af2ae29b8a16968a602205a00eed18a7ffe36f59ae6eb477d9002324cfc249c875260e6ade5bce852692d4121021446bd1df2b61952088a22a516550e43cd95e47ca2a778822d21268bd8b1cebeffffffff02c4090000000000001976a91497ebeffef6d9dd88ffbce922f1df97cbcd7f88d388ac42000000000000001976a91449457f2c101859d1c8ff90096385d3cc30e5488388ac0000000000" + + const validBeefWithLeafOptimalization = "0100beef01fe41800c000b06fd2c0402e01e74cab9a0571ab5a7d86794826f756a9c65dd0dea3bb3720c4051c488cf50fd2d0400d9060c543afb1c0faafb96667ed788324d4d1c338142a0841fe3ab9c30922cb4fd90040208c461a39a8877db46472f5cc59e5a108e417b1c9ea3091b71b65346d218f471fd910400ff8fa1e395088748feae2d7729ab9d5da0225f5ed80b2f295625f7c77da087f4fdcc05022256c94d07451664749e440f55cec8a37da1c46cf30a97579e2f9696b84ad484fdcd0500aecbe0a519d483bad8758c3a69cdc0dc12b19a363fded579ebc993edf510746503fd170200dd5d795e63f8777ef7a82453946150946435e52d4076089ce0cb15d8a1237c84fd4902000f3311a938e3f7977bb7a2db5ca912e4e0f26bd12744051333cd22cd3a2fad89fde702008695a1dfeec9393365a21690b089018c9d7dd94bbbf85b62f48701424e0e611c03fd0a010022373d021864aba56583c796bf9131c804a2ea40acede728b279af38b48dfdd2fd2501005e5f986a28e1cdf2b55b6e5bbcfa34742c45e016f7a920518f376c4b0cbfa868fd7201001287267e0f74f28a0dc5e3e0376fbf28c5ab06424a4dcfd02bb7a65b62d9849d038400a8109eb92b03a106ef15c9d120d7c34ff07ac280636632561e42280499f020659300a60aa07079a19a3600e7fc87cc6a72455f0c2f2735dd3d4039bdaf498469c4d3b800685a26978dfc493d1e03efd9a1c9cac0122d6d0bf027b523be85a4e2a2df3df90343006f78c5d6f4372c65cad0546446bd893db8c47f65e3eae2803ced606f4fd272924800b4a9bae40c785222f38e4127a169fbcbe45085b3e9c59d9631032d5a48dab2a35d00559d25e90b990524eb274251a22508ae04b36125dc894c4e1be21c43c19ab93c03200046bc3f2f79d2aa7da31093e690bb6c10a011a67f2a382937c5eaf423b903df5325006daf88be61cc906f104ac405b04d19f4771a63857a25915e376b53250abe112e2f0037461e9fa1f435caca254303b400b21cc452343572a68ad80d9d3287c2bd8f0f031100f14eebaa20670ebb3d9dab73d074550e3a93cfcb29d90c56dcc205aa8b6a51ab1300597b51a0440a0afe4c346f3b89c5f7aaa7478449f3eb6283e1e1f55b24e54b3b16001009f8ce41536d05ace952e35ce67fc94da2e97b6550f55fbc1d5aa5f3266829030800b668767e12637b80a04de0decb4b96b980b19bd0480557adebfc0c6a46cff1140900d24cec3667bedd9ff7e8bc26dff6ec5fcf8af5cc09f500cad08fdfa2ab2ccf870a00ebea0722a541a4f9e7c4659fdcad062e5806b8abba40cba82eba6882896a763d0105005c9dc967c9a6dd0dd9c80660dd8e86faa3d7f070ed086f1b2d137147d0f52af00103008e9919d62be144a097dd23e1bf924b2e468022c12ccf50db6ceab3d043cdfd8d010000ae98483a460252d92b031d49f591d571e29f1c8b0ae9e2596e4cd24b1c549d3c0401000000019ed68f94dfa952554d777dbaa9e5c01acb3df767e40cabad7b6fb7547bfa871a010000006a4730440220287534d6ff51166e014ad91a2b677be4bd88cf08785624006cdb66553eafc8cf02204862f38e9d2982a5ee95a7850222f2208bff38637349ecfe41abe185498e4ead4121035ca1a2c6d2b46c61fd29e7697018f5ce2bae1ae735e23627046a2dd17ca8fb24ffffffff02de000000000000001976a914f5c9505bf02a4a2fb591e3568183f9c53cf157be88aca62b0000000000001976a91489b5e639bce3209e0888ea8b7eb4203de1c6148888ac000000000100010000000154aa46f1b3b7bde36c02e293b74d53e6c6eaed7411d286183b1dca766f42879a010000006b483045022100cd21d346073b4a0788018ff6938c44395d14cf5759fcc35a0899a8fe35a3c2a0022064eb9a005c3d0be03b61ab0e1c8757ed566dd935dacac37fcd1452adba4994b541210272d67492c31d0e6bead28c934fb1c9bb50ba9b46f886209fe95fb6a3e43bb27bffffffff0257040000000000001976a9140501308b6409cca5a7b5768c18ff2de8da4c1fa388ac39420000000000001976a91417e3d89f4aeacd5b4929fe04edc32c79b6182e1988ac0000000001000100000001e230ab1b300ac3ce334590fc308fee93ddbb252f6e4645e0a20f7e30dd541289010000006b483045022100a611fdf01eca42289d80e1265584e5bd487faa72e6142ebbc140a676f7c5037c0220409282aaadf580f458d97d61db43c94ac343e0b40674a80fd3ac47f43fd0c66c4121020a87e70cc26f7d5fe775f622d2705f27cfd6f5d2b574fea75401d6412a58b91affffffff02d2040000000000001976a9145d2117c4f66bdb335ce2707a74c46fa46d02cdb388acf23b0000000000001976a914effd80ee9df812990a8d7834fa8610491cbeb91688ac0000000001000100000003e01e74cab9a0571ab5a7d86794826f756a9c65dd0dea3bb3720c4051c488cf50000000006b483045022100bc7fc6ace1a5b1ab8601599d56b3adad4a11b7f11757f3225e96b46ca1ab7f7c0220324d6074aa987a7c63c404ac5b03c26e55d3c4209e298b4ca9df0e90aca43ef3412103ee05b34332b5662830c600b73f9c908bb8bff1813bc9b2690e9cad00fad23d3cffffffff08c461a39a8877db46472f5cc59e5a108e417b1c9ea3091b71b65346d218f471000000006b483045022100a936c496423ec03b1ad0f3bfe2348572d7b29ab14e4435c0c8e2ee093d930fde02203d9e86647ea18043c150289f74c6cf2ceb9ca3b228ae31c7b19c4eef813fb68d412103a19014bcc672ccdf18abb6972dd699367baed89c29b704385253ce2ae0eddad5ffffffff2256c94d07451664749e440f55cec8a37da1c46cf30a97579e2f9696b84ad484000000006b48304502210091b0bcf2e84d9ee65de437e8396b379941345e4cffac331af2ae29b8a16968a602205a00eed18a7ffe36f59ae6eb477d9002324cfc249c875260e6ade5bce852692d4121021446bd1df2b61952088a22a516550e43cd95e47ca2a778822d21268bd8b1cebeffffffff02c4090000000000001976a91497ebeffef6d9dd88ffbce922f1df97cbcd7f88d388ac42000000000000001976a91449457f2c101859d1c8ff90096385d3cc30e5488388ac0000000000" const validNotMinedBeef = "0100beef03fe4e6d0c001002fd9c67028ae36502fdc82837319362c488fb9cb978e064daf600bbfc48389663fc5c160cfd9d6700db1332728830a58c83a5970dcd111a575a585b43b0492361ea8082f41668f8bd01fdcf3300e568706954aae516ef6df7b5db7828771a1f3fcf1b6d65389ec8be8c46057a3c01fde6190001a6028d13cc988f55c8765e3ffcdcfc7d5185a8ebd68709c0adbe37b528557b01fdf20c001cc64f09a217e1971cabe751b925f246e3c2a8e145c49be7b831eaea3e064d7501fd7806009ccf122626a20cdb054877ef3f8ae2d0503bb7a8704fdb6295b3001b5e8876a101fd3d0300aeea966733175ff60b55bc77edcb83c0fce3453329f51195e5cbc7a874ee47ad01fd9f0100f67f50b53d73ffd6e84c02ee1903074b9a5b2ac64c508f7f26349b73cca9d7e901ce006ce74c7beed0c61c50dda8b578f0c0dc5a393e1f8758af2fb65edf483afcaa68016600e32475e17bdd141d62524d0005989dd1db6ca92c6af70791b0e4802be4c5c8c1013200b88162f494f26cc3a1a4a7dcf2829a295064e93b3dbb2f72e21a73522869277a011800a938d3f80dd25b6a3a80e450403bf7d62a1068e2e4b13f0656c83f764c55bb77010d006feac6e4fea41c37c508b5bfdc00d582f6e462e6754b338c95b448df37bd342c010700bf5448356be23b2b9afe53d00cee047065bbc16d0bbcc5f80aa8c1b509e45678010200c2e37431a437ee311a737aecd3caae1213db353847f33792fd539e380bdb4d440100005d5aef298770e2702448af2ce014f8bfcded5896df5006a44b5f1b6020007aeb01010091484f513003fcdb25f336b9b56dafcb05fbc739593ab573a2c6516b344ca532fede850c000d02fd860c00661459da8afa777590dc3c736af35ded5fc51b602688a3a7c93edaebe6a4652bfd870c029fc71a2f88088174c4d0e0348e7087c9b355a4e93e5b2ec4a5f41fdd69272f8601fd420600a5a336c4022e226e5695521b7ff33ae86afd0f1eeb17ee0dc62501f385fc5b0901fd20030018013a8fbb3176ba39c193948c2c57cec747ec73aa362f52f0720c3391a7c66701fd91010014d30a290a1b63e7e6e16f8e09e2e93a71042462451e1f0b2f9ec8971e0c736a01c900421970e542d08b8b52eb3ba45541226d885dcad9dbe7ccec4111c9cd4c54acb30165005ae426e8c77d1b1153b2425b935ede63f1b98e7852e9eee493415e7bcf2ec56301330039eb742b6167dcb3d9f680e60d13af943f6fff7f6a84dc6ac5680eb32c51e728011800d47cdf86aa745c735cb1de8b5c72dc43d927c58500b76e108b86556845c3aa53010d00725cc42f64c415e1d17803764a441ece296509ecdc77e5962141641df91e276b0107007dd3c756b59f354d81efe05248242d603e4baf5a568b34cfa84b1152c65d2b440102001083fd215308c82b36ab82b7aaf8ef5016edd1f7fe3d7cd0d7c7026d17d6841c010000848831afed0a0552896bf420ad66647af4d0dc8c76d19a6e912a1987ac925dba0101004d4fe46bfd107d575616f76b860ab00906e6ac47250d776a4c2cc67345eef4e8fef3850c000b04fde00502f8aea749791d0907e46bbb7df82dc52f84a9b83434e563e3a6496b95239fc08dfde1050076c8b774bf78f74252cee9698b49fccf87937ae4f2b01b7a87f23b060336585dfd26060295e93ce1a376cfd842ffbd849f0ee37330d6b62a51cddfacfbed9c1a4d49cce7fd270600d232986aa95c1db58e9f56fd3caf52cd812428ffc3fdcdf5be21edea66af1e3802fdf10200eef6a321ca9dcd30df8eb9eeaeacdb0a0535e269279e6ed87c6ab5bfdd14f167fd120300f38cdc9cf336f46aa742e3a1ddd3a50418ca5d52fb2d613a49e9d1f0821fde6c02fd790100e1e3d7d90c3859990c6ea7588f05419fab6eebff078edf3f66a6cd8a87faa7c5fd880100b0f4a9b7219d01ca579ad5e6741fdf677c899f1de9855945f13a286c0452e9b202bd007f0f30d4d1ffc36093444b54cb39693d6c34f4810863850adc824733aeaa55e9c500c37b5a7df0dcc18fe9943b9f2927122d2bd3aaaa8c4bac71d9bbecceee1be782025f00b0126c6c3ede9904454251478bd667b1396678a4567bcbcae0fb33f73e0d7aab6300fe3589fe0e5afc3827d35b1065b7aad956021d388fc6ccb1d5d81657d092b1e2022e00bbcd586527ec559f3ecf031064f631b3c372e7b31d1361be3a9b41bd21a09e84300051af813b88ba08d1526fd4418305a0464f499c51ee1e1bc7231ebbf68d33b812021600e822218713eb86174c91b4cc924dbe8c8e2319309b8195e845e94e0b0760ea191900e8ec605b869f93cf6b1e2d74bcbc9aba1be3d9b4f9bd2e82563fd797b8cd4a3e020a000be8607accf5ae93e80c274bc3e045a3d4e8387b3725dbb1e9583a4ed310ef4b0d0084309da5e0385c79ea670be940324a3416ed96e122a24aca17773cb5899b407b02040036bd04fa34848574dc1665ba52bbe49038b9595635fa4b525d7de6ef9c8988210700c4c2ef77377913248dd9fe8e659c6f0f80b9b72fa98ffed670f8fadc5c91f3930202007a3e5caea9497ee7595c8aa9bcb6a08c2d06e215154085f224345aaf3ede4e870300e9bb93416e69b38eacd6aba4258afde7a007ac52dcaa28aabd65aad90ac3bc1b010000c1006f88da5f5841323cd779a19689a43d9311785be06efb22ad98c3cc6be1260901000000029ceda549c273cb093678c42c5765354c735c005cc1feb72e1a291f6bf3b3e312000000006a47304402204c992ff3b4185f9858e72e0b3d01d6d4ed144e363c13afe662c8edf37744e612022018fcd7e2492e365f738fb07fa5c1dfa84ab9f49469559f5540be1e115104066b4121031499e4d192d8e2b2409cb757608bee58701cf6d58d55cff97fa584671bce4728fffffffffc67309c8602eb6a14b805c27641337f114314ac09fa96b2974d73d11997639d010000006a473044022069eeddbc83b657ea6f40d1c6ae535a7993943ce5624494d6069b64fc45d17cef02202346f9131101d94bd15b0fb122f25fbc41e6d0b941b42eb79549c7cfb78e5ac441210242cf3c106badb9695cbf7c64039bce81b0a58cbf89b3a04d90577bc801b2a9efffffffff03e8030000000000001976a914ff98769820cd542ba0c6fc8f0db003ef51a6f84d88ac1f070000000000001976a914e11d3852660e0630189bfd178ed7652fb0be25de88acb8260000000000001976a9141fbd24e6a4b10ce1f04775d0e8e42c4406e3824b88ac00000000010101000000027b0a1b12c7c9e48015e78d3a08a4d62e439387df7e0d7a810ebd4af37661daaa000000006a47304402207d972759afba7c0ffa6cfbbf39a31c2aeede1dae28d8841db56c6dd1197d56a20220076a390948c235ba8e72b8e43a7b4d4119f1a81a77032aa6e7b7a51be5e13845412103f78ec31cf94ca8d75fb1333ad9fc884e2d489422034a1efc9d66a3b72eddca0fffffffff7f36874f858fb43ffcf4f9e3047825619bad0e92d4b9ad4ba5111d1101cbddfe010000006a473044022043f048043d56eb6f75024808b78f18808b7ab45609e4c4c319e3a27f8246fc3002204b67766b62f58bf6f30ea608eaba76b8524ed49f67a90f80ac08a9b96a6922cd41210254a583c1c51a06e10fab79ddf922915da5f5c1791ef87739f40cb68638397248ffffffff03e8030000000000001976a914b08f70bc5010fb026de018f19e7792385a146b4a88acf3010000000000001976a9147d48635f889372c3da12d75ce246c59f4ab907ed88acf7000000000000001976a914b8fbd58685b6920d8f9a8f1b274d8696708b51b088ac00000000010001000000028ae36502fdc82837319362c488fb9cb978e064daf600bbfc48389663fc5c160c000000006b483045022100c5db842085740c8467a6755693e7048b2f4134371a0f01509ee1db9b7274403f022064de309ec9fbdca4ca1ab220cd35d6efd04028217f535cc43649f96250bb53154121028fd1afeee81361e801800afb264e35cdce3037ec6f7dc4f1d1eaba7ad519c948ffffffff9fc71a2f88088174c4d0e0348e7087c9b355a4e93e5b2ec4a5f41fdd69272f86000000006b4830450221009bc74c7331b010f8befcc4a7ee630876282bee47775f04796567dc875ec83c05022064b558766a1f8badc0c26c0b3d7bcde99cf9d774f88a87f8f45d440ca54043a241210336abf8512542305fa13788dae2e4e9f0fb2ae5dc57cb1ced980eaee6e88f343fffffffff02dc050000000000001976a914ddfbaa2cd75b86cf24135603b5ddd2b1968bc62d88acf3010000000000001976a9148360b65a14e83a68aef2fae3f9cf472a90dd4da488ac00000000000100000002418eb1b58f47af50a079e1c695e6ce86f79c092caf050128f0d7785381d960d3010000006a47304402207b019f395fdedfe3632433df49eba13e33d8c8f0328834eb0366635853c3e8ff0220505ef2df0702e918897019e49a486ecf8238b179d102cc3c0920564dd6a84d064121034e92b3e62017ee88487a69f8ecda9d17b4daf590d6e06362a4139b1d993dd044fffffffffea6861820d117e799caf1553ce075435f3ea153aff26c9551c71047be4089bb020000006a47304402207b58b596f1094c3e0570f136f1c86ae883a260b6fe671b07ccda85136561bab80220410924b50aa6a7ba9c864f8d206f1bba2c7b384127984e2a1e9db066f82379ca41210301b1d251f89768ff33a01c192a400de69573bdfc44fa67fde13eb259eb81ea64ffffffff03f4010000000000001976a914601d40068f463ce0124e1b18466e1bd7d6b333a388acf4010000000000001976a914668c08cab622e65e3aaa1c1365b8e4c029a6365688acb9260000000000001976a914e861b54724209a7eb9b0512f31c50c1ae2a07cb588ac000000000102010000000195e48d7d5679e0740c85f3a9e1e69a9f5c8493f7ec7c454b0193c15dcc7007cd010000006a47304402205babaf7fb8cc6e9347c0cc743c9f044bf8a3820f05fdc57a3591d4cf2df86bc402202e816d35e9a937cffe8cde4f68ee64b06fc5e070335c0c2262fdf016eaca47b94121033733254e143eba5ee6989fe898647d4e6170c0d82faa72fbce1c1e701960edb9ffffffff0264000000000000001976a914ddfbaa2cd75b86cf24135603b5ddd2b1968bc62d88ac8e010000000000001976a9148360b65a14e83a68aef2fae3f9cf472a90dd4da488ac000000000001000000029fc71a2f88088174c4d0e0348e7087c9b355a4e93e5b2ec4a5f41fdd69272f86010000006a47304402203a5c238e8ceccff7b7db05a4dba524f6694599014dbac5ae92dc0c62635c8763022078cab36b04a16eeead80fa49dd4d1c22f14d8084c78977917cfe76fee9d95a84412102993285bd72def003516c414b4fb3c3718d5d003c90f08c75bd6eecc08910585fffffffff396915fa4cff57573f0e80b1d585d5a4f7692984e51577c8ea82e1d88f8404ce060000006a47304402205ba90f2ed3f70c779771185a473e3b1844ad0f8f86bddf39148ad277c9a2298902203df352b710b05501cc3d773e366854770038f9dea65c046b666fd28b124f303d412103c335fc77d28a0181bec42cd7afda547a4d524c5b1f04a7d9d0ec76f1217a0e5affffffff03f4010000000000001976a91494c77286c0552398575ea741337dc6143c7978ec88ac2b050000000000001976a91418d9eaafcf7d8e8ba29ac102ed19b9b3808376a088ac0f4e0000000000001976a914555b7d05b5327c78c7bf7f8748c1b3ce3552168888ac0000000001020100000001f8aea749791d0907e46bbb7df82dc52f84a9b83434e563e3a6496b95239fc08d000000006b483045022100a50ebc1429285edf0d39d77f0ab49e68eaf6e8f97d727671fcc51763235ca39a02200252a185b70fb5ac893ad32e8ffe1e8ade9d3d8993f8db4a8cb27dc6e32c18664121037b231d9fdd2f7a41181de9a14ae11a10b7332b1fdb5526c1a0060eb964f111d6ffffffff0296000000000000001976a914ddfbaa2cd75b86cf24135603b5ddd2b1968bc62d88ac5d010000000000001976a9148360b65a14e83a68aef2fae3f9cf472a90dd4da488ac0000000000010000000183d98243af506e20461097054c6692a09502ee7a99eba67cd20b0d5b66d081f0010000006a473044022055e323fc40f05fdeb836fadf19003d91f08abef97526e04f4c976156faedc83c022050f36b4d23329fa9d6f37bfee952ae3a0bf266573fc19a51ab42595ee674a26a4121033733254e143eba5ee6989fe898647d4e6170c0d82faa72fbce1c1e701960edb9ffffffff0264000000000000001976a914ddfbaa2cd75b86cf24135603b5ddd2b1968bc62d88ac29010000000000001976a9148360b65a14e83a68aef2fae3f9cf472a90dd4da488ac000000000001000000032a796907de322523a34e801e304ea43b6938cfa5afe3ff4fea7fbc34bd52164c010000006b483045022100ec1d2ab4bedca3a696a6f0589b65015b07d5a00b7517d03f783050323165b16902200c18cf37ba54454f0e28e610ec14e53be4cfc254182142e111c2571c3432f15d4121033733254e143eba5ee6989fe898647d4e6170c0d82faa72fbce1c1e701960edb9ffffffff73bd2e109d1e01d9c5828e15b7e3212e54dd3d9558ceae6514c97e07ad275110010000006b48304502210081d8eb51e97f6c50460a3f526f14f35f8882f51f9455c7b06f63a3aedd16c057022019e8014a1c2bed2b4f9c0e15989056a53400ae3e3ed1114f516fa9b6390af7154121033733254e143eba5ee6989fe898647d4e6170c0d82faa72fbce1c1e701960edb9ffffffff95e93ce1a376cfd842ffbd849f0ee37330d6b62a51cddfacfbed9c1a4d49cce7000000006a47304402202b185fd9848a68d76167383535de9d8adcdb2e219e8210641e4aead624532d3e02206f2f24fa29a81f73438a3cf7208bd021fb9fa8c1f30376b00af6bf7766b29d7e41210275aaa422bc13c303b70026b3fd1fff37c199e5e98bd0a429922217f9b861870effffffff024c040000000000001976a914ddfbaa2cd75b86cf24135603b5ddd2b1968bc62d88ac2d000000000000001976a9148360b65a14e83a68aef2fae3f9cf472a90dd4da488ac0000000000" tcs := []struct { @@ -23,6 +28,14 @@ func TestExecuteSimplifiedPaymentVerification_ValidTransaction_Success(t *testin name: "SPV on valid beef (full mined)", beef: validFullMinedBeef, }, + { + name: "SPV on valid beef (without leaf optimalization)", + beef: validBeefWithoutLeafOptimalization, + }, + { + name: "SPV on valid beef (leaf optimized)", + beef: validBeefWithLeafOptimalization, + }, { name: "SPV on valid beef (not mined)", beef: validNotMinedBeef,