diff --git a/Cargo.lock b/Cargo.lock index 4d9f893..b1ddb58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1852,8 +1852,7 @@ dependencies = [ [[package]] name = "rgb-psbt" -version = "0.11.1-alpha.2+unreviewed" -source = "git+https://github.com/RGB-WG/rgb?branch=revert_fix_same_blinded_transfer#bd3f36f8d144047385f2e809e3b93a61b29b118f" +version = "0.11.1-alpha.3+unreviewed" dependencies = [ "amplify", "baid64", @@ -1869,6 +1868,7 @@ dependencies = [ [[package]] name = "rgb-psbt" version = "0.11.1-alpha.3+unreviewed" +source = "git+https://github.com/RGB-WG/rgb?branch=revert_fix_same_blinded_transfer#8ab53d712e018a5681c189b1e2196efb0cca988b" dependencies = [ "amplify", "baid64", @@ -1883,8 +1883,7 @@ dependencies = [ [[package]] name = "rgb-runtime" -version = "0.11.1-alpha.2+unreviewed" -source = "git+https://github.com/RGB-WG/rgb?branch=revert_fix_same_blinded_transfer#bd3f36f8d144047385f2e809e3b93a61b29b118f" +version = "0.11.1-alpha.3+unreviewed" dependencies = [ "amplify", "baid64", @@ -1896,7 +1895,7 @@ dependencies = [ "getrandom 0.3.2", "indexmap 2.9.0", "nonasync", - "rgb-psbt 0.11.1-alpha.2+unreviewed", + "rgb-psbt 0.11.1-alpha.3+unreviewed", "rgb-std", "serde", "strict_types", @@ -1906,6 +1905,7 @@ dependencies = [ [[package]] name = "rgb-runtime" version = "0.11.1-alpha.3+unreviewed" +source = "git+https://github.com/RGB-WG/rgb?branch=revert_fix_same_blinded_transfer#8ab53d712e018a5681c189b1e2196efb0cca988b" dependencies = [ "amplify", "baid64", @@ -1917,7 +1917,7 @@ dependencies = [ "getrandom 0.3.2", "indexmap 2.9.0", "nonasync", - "rgb-psbt 0.11.1-alpha.3+unreviewed", + "rgb-psbt 0.11.1-alpha.3+unreviewed (git+https://github.com/RGB-WG/rgb?branch=revert_fix_same_blinded_transfer)", "rgb-std", "serde", "strict_types", @@ -1974,15 +1974,16 @@ dependencies = [ "bp-std", "bp-wallet", "chrono", + "commit_verify", "descriptors", "file-format", "once_cell", "psbt", "rand 0.8.5", - "rgb-psbt 0.11.1-alpha.2+unreviewed", "rgb-psbt 0.11.1-alpha.3+unreviewed", - "rgb-runtime 0.11.1-alpha.2+unreviewed", + "rgb-psbt 0.11.1-alpha.3+unreviewed (git+https://github.com/RGB-WG/rgb?branch=revert_fix_same_blinded_transfer)", "rgb-runtime 0.11.1-alpha.3+unreviewed", + "rgb-runtime 0.11.1-alpha.3+unreviewed (git+https://github.com/RGB-WG/rgb?branch=revert_fix_same_blinded_transfer)", "rgb-schemata", "rgb-std", "rstest", diff --git a/Cargo.toml b/Cargo.toml index 0841166..0631ab6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,8 @@ bp-wallet = { path = "./bp-wallet", features = [ "esplora", "fs", ] } +## client_side_validation +commit_verify = { path = "./client_side_validation/commit_verify" } ## rgb rgb-runtime = { path = "./rgb", features = [ "electrum_blocking", diff --git a/altered_submodules/rgb b/altered_submodules/rgb index bd3f36f..8ab53d7 160000 --- a/altered_submodules/rgb +++ b/altered_submodules/rgb @@ -1 +1 @@ -Subproject commit bd3f36f8d144047385f2e809e3b93a61b29b118f +Subproject commit 8ab53d712e018a5681c189b1e2196efb0cca988b diff --git a/rgb b/rgb index a9bba35..62423fb 160000 --- a/rgb +++ b/rgb @@ -1 +1 @@ -Subproject commit a9bba35ceed7e0c4bc4e477f663ab022d7b0a23e +Subproject commit 62423fbbb2d10abe279c567d1cf3592f3ac53831 diff --git a/rgb-core b/rgb-core index bbc63f8..732baf7 160000 --- a/rgb-core +++ b/rgb-core @@ -1 +1 @@ -Subproject commit bbc63f8429bf00d3a6588a01311987e4e22631de +Subproject commit 732baf7a74f15f5ca7633642a6e8fe40661375ce diff --git a/rgb-schemata b/rgb-schemata index 800a36f..ad02e64 160000 --- a/rgb-schemata +++ b/rgb-schemata @@ -1 +1 @@ -Subproject commit 800a36fbd8a16837047d5bf3eb511c70bc9fa6af +Subproject commit ad02e64cde6ffaf578969ff49c93b624f1d5c188 diff --git a/rgb-std b/rgb-std index cce223e..b940e6d 160000 --- a/rgb-std +++ b/rgb-std @@ -1 +1 @@ -Subproject commit cce223e3a705880e5a882f7a8dbd0ccfb32731d0 +Subproject commit b940e6d5fbf7ed21d3f3186de61420f7aebebb2d diff --git a/tests/fixtures/143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd.json b/tests/fixtures/143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd.json new file mode 100644 index 0000000..20cc2d2 --- /dev/null +++ b/tests/fixtures/143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd.json @@ -0,0 +1,29 @@ +{ + "version": 2, + "inputs": [ + { + "prevOutput": "4b8d99de8188a6769987e59faa7cdb70086608a05f38a336549770f047a64701:1", + "sigScript": "", + "sequence": 0, + "witness": [ + "3045022100ab6fefaa3d7ed732aee06229930d3af198183ed1c6968cb5ea49dd23d0ee6b660220474df6e8bed2f28a98814cdb39fd4a3d1e278f74dfcb5f1937cf7921a0b4fe1801", + "027b878223ac810d0dddf51a05d337cf09a84bfae5472582bdf3e31b6f72aec73a" + ] + } + ], + "outputs": [ + { + "value": 0, + "scriptPubkey": "6a204266173b9f445e4e0738d460c90ed778eb152822ad9c14366c7fc07b20fcbcc3" + }, + { + "value": 9000, + "scriptPubkey": "0014a38ad5e206733b28151e460e383991ffbdbdbfe9" + }, + { + "value": 99990600, + "scriptPubkey": "00146990e864fee7e996d191cf742d37d80fd47eab2f" + } + ], + "lockTime": 0 +} \ No newline at end of file diff --git a/tests/fixtures/333b0aea5cbf230791c57814de6dd86340e2626c1c1e8ac462f4f73c2645682c.json b/tests/fixtures/333b0aea5cbf230791c57814de6dd86340e2626c1c1e8ac462f4f73c2645682c.json new file mode 100644 index 0000000..7ced46a --- /dev/null +++ b/tests/fixtures/333b0aea5cbf230791c57814de6dd86340e2626c1c1e8ac462f4f73c2645682c.json @@ -0,0 +1,29 @@ +{ + "version": 2, + "inputs": [ + { + "prevOutput": "84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3:2", + "sigScript": "", + "sequence": 0, + "witness": [ + "30440220476ccfaefff85bb856cc432b3592635be809d928c84411717e837d769c7966860220233acde327f11f84aaf7aa62e016f43818a48feb69c1926ebc00eaaab558e78301", + "02891b2006e72bf14fd122bdf6d89522d6480be2bc55035421f1954bcbbf888e14" + ] + } + ], + "outputs": [ + { + "value": 0, + "scriptPubkey": "6a20ded4a8d8dba904936aeea30e8bc0ae524b64c3500bc9cfe94895dc77bfde35d9" + }, + { + "value": 9000, + "scriptPubkey": "0014fe9163be63b335ae4640e5011d610feb791713db" + }, + { + "value": 99971800, + "scriptPubkey": "0014282993ddc2ba6d84598e751a93429395d460c7f9" + } + ], + "lockTime": 0 +} \ No newline at end of file diff --git a/tests/fixtures/5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54.json b/tests/fixtures/5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54.json deleted file mode 100644 index ccd9a41..0000000 --- a/tests/fixtures/5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "version": 2, - "inputs": [ - { - "prevOutput": "5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9:2", - "sigScript": "", - "sequence": 0, - "witness": [ - "3044022002bc541ebc51300ffdbb08a6068624c36f0fca5a48f680ce1f6eff55d69f401802202c27f77f1c16fc029f7b8e2ae8c218a065c41fd8c46bafbb1626054d1c30c44001", - "03ee020029bdd3687de6ee181bbe9cca076e38c21f3c41942249e88ce1a0a914b3" - ] - } - ], - "outputs": [ - { - "value": 0, - "scriptPubkey": "6a20f165d1e9ce1ee99e0c26a614b060b8ba964d053de9d2591d27fda3a42c4a06ea" - }, - { - "value": 9000, - "scriptPubkey": "0014de56a95f365f2fdfac59c996d911807643318d45" - }, - { - "value": 99981200, - "scriptPubkey": "00140721467af22eceb7c10669839340d36b0550fb51" - } - ], - "lockTime": 0 -} \ No newline at end of file diff --git a/tests/fixtures/5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9.json b/tests/fixtures/5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9.json deleted file mode 100644 index d43fc13..0000000 --- a/tests/fixtures/5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "version": 2, - "inputs": [ - { - "prevOutput": "2697bf250bfbfdf0232329e1c4d504df0a3afc7f155372c8344d14aa477978eb:1", - "sigScript": "", - "sequence": 0, - "witness": [ - "3045022100b178bb7e6eea5ce23f9685624c6ecdafdc516ba82452361dab5cf304a4b173e402204857057b18e94f1a1220bd2147fff4ad065e4ddbf0df8d89a0f61088353d5bf701", - "025bba6dd99d47e587b4bc1466ec7fbf811b164406e9b2a0254361fdc454732eed" - ] - } - ], - "outputs": [ - { - "value": 0, - "scriptPubkey": "6a207d21d8c4829a93e3b28dc2624ce854dec0393025b252c884e15020be1fafa949" - }, - { - "value": 9000, - "scriptPubkey": "001402bff690f27911f8412cb4047779ebd9eea228db" - }, - { - "value": 99990600, - "scriptPubkey": "0014b31d8f364e330e328c0ab1baed3adb3873e3d9bb" - } - ], - "lockTime": 0 -} \ No newline at end of file diff --git a/tests/fixtures/84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3.json b/tests/fixtures/84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3.json new file mode 100644 index 0000000..e853d22 --- /dev/null +++ b/tests/fixtures/84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3.json @@ -0,0 +1,29 @@ +{ + "version": 2, + "inputs": [ + { + "prevOutput": "143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd:2", + "sigScript": "", + "sequence": 0, + "witness": [ + "3045022100dfcbed03e1118cf81ccd3c2462a707fa3534d48baccba2a2af2eefb6cc3a2fb80220191d94b5a51d9e4d765804c7756e5b66e58ef3e862082835e83f6ce85b0e17b101", + "03375b7c340ffbee5804ee0ce1e87f9f85386f998615e43604ef7a0136b0c50038" + ] + } + ], + "outputs": [ + { + "value": 0, + "scriptPubkey": "6a20ec7439f82cb704cdc0e867ec63c6f88ecdb352266915e7b95639b26360ebbb6e" + }, + { + "value": 9000, + "scriptPubkey": "00142842f7eabee95edda63fefc011bce78c69a9cd1d" + }, + { + "value": 99981200, + "scriptPubkey": "0014f62a638b6981c9396ea76109aed6ef5f5981a303" + } + ], + "lockTime": 0 +} \ No newline at end of file diff --git a/tests/fixtures/attack_bundles_pubWitness_data_input_sequence.json b/tests/fixtures/attack_bundles_pubWitness_data_input_sequence.json index 3f8ea04..f6814fc 100644 --- a/tests/fixtures/attack_bundles_pubWitness_data_input_sequence.json +++ b/tests/fixtures/attack_bundles_pubWitness_data_input_sequence.json @@ -2,14 +2,14 @@ "version": "v0", "transfer": true, "terminals": { - "9d4b73f7964529cfd46536f640c40d0ec5ac20bff54e00f7d101b26c16dfae13": [ - "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0" + "f5f7500948a8ae8ad6db4d551c6f317f5c02de23edb07bbff34cea2bfcbe4cb1": [ + "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90" ] }, "genesis": { "ffv": 0, "schemaId": "rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus", - "timestamp": 1747745043, + "timestamp": 1750883619, "issuer": "ssi:anonymous", "chainNet": "bitcoinRegtest", "sealClosingStrategy": "firstOpretOrTapret", @@ -31,9 +31,9 @@ "items": [ { "seal": { - "txid": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13", + "txid": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7", "vout": 1, - "blinding": 13113921856262959977 + "blinding": 15882975521680157652 }, "state": 666 } @@ -48,20 +48,20 @@ "version": 2, "inputs": [ { - "prevOutput": "c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9:1", + "prevOutput": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7:1", "sigScript": "", - "sequence": 0, + "sequence": 1, "witness": [] } ], "outputs": [ { "value": 0, - "scriptPubkey": "6a20f75dffbafa81de29f1b767a81f47e9ace789223e6854b388c8ff72b480e9bc65" + "scriptPubkey": "6a2004b86f6d44449be00a1b75a13d671ad44da9b388367102b2a6ee668389313b5b" }, { - "value": 99998800, - "scriptPubkey": "0014a6558396fcd09a1cb1773b09e9a7033ffe5f7843" + "value": 99999600, + "scriptPubkey": "00148467a4cb9231d8da59df02de1a82ce5761b6d59e" } ], "lockTime": 0 @@ -69,59 +69,52 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "7584c919969fced81f6309b7a6d817e0e2bc6240e5b41759d90719efec4235c3", - "048867a3370db6815e3a90093e0f3e8a16f19c39953e91af5bb426ab2a3aabfd", - "ad31b376af0d04b0f5088abf077b405cad2f9b9760e0c27dddc463cdad289af2" + "871af4b1c4ec5ab8d17b6ee08f50ba823f497b3e3e32e8d4ed6171cf101596c5", + "52e4b4229303ac38fcb7258d8bec1c2cf79344c1e80d55b9b3ce4328e5bef1d5", + "f35512c5b4e2cd46bf866036d0778d87d7c74bf460208fa6d08a7a35655c9d69" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291" - ] + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0" }, - "knownTransitions": { - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 12961427178433477692 - }, - "state": 539 - }, - { - "seal": "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0", - "state": 77 - } - ] - } - }, - "signature": null + "knownTransitions": [ + { + "opid": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 17454843376278179683 + }, + "state": 666 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -130,7 +123,7 @@ "version": 2, "inputs": [ { - "prevOutput": "e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0:1", + "prevOutput": "b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b:1", "sigScript": "", "sequence": 0, "witness": [] @@ -139,11 +132,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a201f129c99327c5cd54125d7c2091bb8962bf04147254459a38070587e1349d89c" + "scriptPubkey": "6a20bc53e837e022ea6083e4ad64efcca8371e031710118834615df7098715cf87a6" }, { "value": 99999200, - "scriptPubkey": "001438ef9ad1ee0663a43b8b30a7c1d4705f071779db" + "scriptPubkey": "00145c3afeb169a9fa6828c917b6e61ae123951806f4" } ], "lockTime": 0 @@ -151,59 +144,56 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "e194ceb0f09362d49969e8f4ddfee873ac6760ede382351fdead1dab3c0ab0d0", - "9bfdf671b70582032db385ec98c07f01060ff467918a9a812cf6c00bedb22180", - "e04fcb9eaf2a716f7c0c5e3a538cc3ed4580b3ae2e658fe0d2eef9e46fd952a6" + "ca3be1e1847652a7e803f4599f73f1cf200bf05ab9cceda8e30a372c8216fdfe", + "6471737aeb42e46cdcd5d7f57cd56406806d7630938b764c16ba04b547ef3bf4", + "27915b2641c8ad41aa1dd2198c752aa58a84f8d58849f50fba7c8252318a3ea0" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d" - ] + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941" }, - "knownTransitions": { - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 10003067900325773186 + "knownTransitions": [ + { + "opid": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 7476137096582570779 + }, + "state": 616 }, - "state": 616 - }, - { - "seal": "18a82040f68755c128b28eacdb9af7c8a0bed32b2a52f5dcba6c45b51d83bdf3", - "state": 50 - } - ] - } - }, - "signature": null + { + "seal": "88a6eddc7feb428eb58fbd64728a33bfdc673f375a57d4bd59371ca92369e40f", + "state": 50 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -212,20 +202,20 @@ "version": 2, "inputs": [ { - "prevOutput": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13:1", + "prevOutput": "b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2:1", "sigScript": "", - "sequence": 1, + "sequence": 0, "witness": [] } ], "outputs": [ { "value": 0, - "scriptPubkey": "6a204bba687d2198a9a049b75255ea3fbdf5b648437ffb7757c258a95cb1232a5fa6" + "scriptPubkey": "6a20d87aa6b06a714562dc4e9f5a9e24e6dfda5684d880480ba6f54262702c55a7a5" }, { - "value": 99999600, - "scriptPubkey": "00149aeec847f99c80464389ed96e80de8bb147d6227" + "value": 99998800, + "scriptPubkey": "001469ade53185b381ac4428fdd0edbca6368403e9d0" } ], "lockTime": 0 @@ -233,55 +223,56 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "315234829e1fd969c450b5651cd33d9282c081dc7f87cb7f321e34186ed2a476", - "6efee2e679ba3987921bbdb3ff2b5c254d823072fed90a7f661c82e5a9b97363", - "2608cec7dc2d6f14c1e89d3f8aaf81dcc79146c063c1b62b52a3923f1dec0ec9" + "a3a23db672daad69d0717c9740d1ffc937f8c95b479340a97a61c2979262a44d", + "ee360ceb6a0a463c92710b7213bbac8e0f3bfc1fafa7ad09fcc4782dff90ea9e", + "2f48a5c7ffff1fc60b698c18224bb847fd603359ecd61852f9b729e6e5bef414" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b" - ] + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938" }, - "knownTransitions": { - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "8f8ac47ea084bdff5550df2b43427cafc2aa6177f7043a855046a59e3c6f1a16", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 17520881827267755355 + "knownTransitions": [ + { + "opid": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 9119672638623966453 + }, + "state": 539 }, - "state": 666 - } - ] - } - }, - "signature": null + { + "seal": "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90", + "state": 77 + } + ] + } + }, + "signature": null + } } - } + ] } } ], diff --git a/tests/fixtures/attack_chain.json b/tests/fixtures/attack_chain.json index 5ba8b85..f9b3e72 100644 --- a/tests/fixtures/attack_chain.json +++ b/tests/fixtures/attack_chain.json @@ -2,14 +2,14 @@ "version": "v0", "transfer": true, "terminals": { - "9d4b73f7964529cfd46536f640c40d0ec5ac20bff54e00f7d101b26c16dfae13": [ - "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0" + "f5f7500948a8ae8ad6db4d551c6f317f5c02de23edb07bbff34cea2bfcbe4cb1": [ + "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90" ] }, "genesis": { "ffv": 0, "schemaId": "rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus", - "timestamp": 1747745043, + "timestamp": 1750883619, "issuer": "ssi:anonymous", "chainNet": "liquidTestnet", "sealClosingStrategy": "firstOpretOrTapret", @@ -31,9 +31,9 @@ "items": [ { "seal": { - "txid": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13", + "txid": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7", "vout": 1, - "blinding": 13113921856262959977 + "blinding": 15882975521680157652 }, "state": 666 } @@ -48,7 +48,7 @@ "version": 2, "inputs": [ { - "prevOutput": "c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9:1", + "prevOutput": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7:1", "sigScript": "", "sequence": 0, "witness": [] @@ -57,11 +57,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a20f75dffbafa81de29f1b767a81f47e9ace789223e6854b388c8ff72b480e9bc65" + "scriptPubkey": "6a2004b86f6d44449be00a1b75a13d671ad44da9b388367102b2a6ee668389313b5b" }, { - "value": 99998800, - "scriptPubkey": "0014a6558396fcd09a1cb1773b09e9a7033ffe5f7843" + "value": 99999600, + "scriptPubkey": "00148467a4cb9231d8da59df02de1a82ce5761b6d59e" } ], "lockTime": 0 @@ -69,59 +69,52 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "7584c919969fced81f6309b7a6d817e0e2bc6240e5b41759d90719efec4235c3", - "048867a3370db6815e3a90093e0f3e8a16f19c39953e91af5bb426ab2a3aabfd", - "ad31b376af0d04b0f5088abf077b405cad2f9b9760e0c27dddc463cdad289af2" + "871af4b1c4ec5ab8d17b6ee08f50ba823f497b3e3e32e8d4ed6171cf101596c5", + "52e4b4229303ac38fcb7258d8bec1c2cf79344c1e80d55b9b3ce4328e5bef1d5", + "f35512c5b4e2cd46bf866036d0778d87d7c74bf460208fa6d08a7a35655c9d69" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291" - ] + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0" }, - "knownTransitions": { - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 12961427178433477692 - }, - "state": 539 - }, - { - "seal": "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0", - "state": 77 - } - ] - } - }, - "signature": null + "knownTransitions": [ + { + "opid": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 17454843376278179683 + }, + "state": 666 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -130,7 +123,7 @@ "version": 2, "inputs": [ { - "prevOutput": "e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0:1", + "prevOutput": "b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b:1", "sigScript": "", "sequence": 0, "witness": [] @@ -139,11 +132,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a201f129c99327c5cd54125d7c2091bb8962bf04147254459a38070587e1349d89c" + "scriptPubkey": "6a20bc53e837e022ea6083e4ad64efcca8371e031710118834615df7098715cf87a6" }, { "value": 99999200, - "scriptPubkey": "001438ef9ad1ee0663a43b8b30a7c1d4705f071779db" + "scriptPubkey": "00145c3afeb169a9fa6828c917b6e61ae123951806f4" } ], "lockTime": 0 @@ -151,59 +144,56 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "e194ceb0f09362d49969e8f4ddfee873ac6760ede382351fdead1dab3c0ab0d0", - "9bfdf671b70582032db385ec98c07f01060ff467918a9a812cf6c00bedb22180", - "e04fcb9eaf2a716f7c0c5e3a538cc3ed4580b3ae2e658fe0d2eef9e46fd952a6" + "ca3be1e1847652a7e803f4599f73f1cf200bf05ab9cceda8e30a372c8216fdfe", + "6471737aeb42e46cdcd5d7f57cd56406806d7630938b764c16ba04b547ef3bf4", + "27915b2641c8ad41aa1dd2198c752aa58a84f8d58849f50fba7c8252318a3ea0" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d" - ] + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941" }, - "knownTransitions": { - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 10003067900325773186 + "knownTransitions": [ + { + "opid": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 7476137096582570779 + }, + "state": 616 }, - "state": 616 - }, - { - "seal": "18a82040f68755c128b28eacdb9af7c8a0bed32b2a52f5dcba6c45b51d83bdf3", - "state": 50 - } - ] - } - }, - "signature": null + { + "seal": "88a6eddc7feb428eb58fbd64728a33bfdc673f375a57d4bd59371ca92369e40f", + "state": 50 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -212,7 +202,7 @@ "version": 2, "inputs": [ { - "prevOutput": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13:1", + "prevOutput": "b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2:1", "sigScript": "", "sequence": 0, "witness": [] @@ -221,11 +211,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a204bba687d2198a9a049b75255ea3fbdf5b648437ffb7757c258a95cb1232a5fa6" + "scriptPubkey": "6a20d87aa6b06a714562dc4e9f5a9e24e6dfda5684d880480ba6f54262702c55a7a5" }, { - "value": 99999600, - "scriptPubkey": "00149aeec847f99c80464389ed96e80de8bb147d6227" + "value": 99998800, + "scriptPubkey": "001469ade53185b381ac4428fdd0edbca6368403e9d0" } ], "lockTime": 0 @@ -233,55 +223,56 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "315234829e1fd969c450b5651cd33d9282c081dc7f87cb7f321e34186ed2a476", - "6efee2e679ba3987921bbdb3ff2b5c254d823072fed90a7f661c82e5a9b97363", - "2608cec7dc2d6f14c1e89d3f8aaf81dcc79146c063c1b62b52a3923f1dec0ec9" + "a3a23db672daad69d0717c9740d1ffc937f8c95b479340a97a61c2979262a44d", + "ee360ceb6a0a463c92710b7213bbac8e0f3bfc1fafa7ad09fcc4782dff90ea9e", + "2f48a5c7ffff1fc60b698c18224bb847fd603359ecd61852f9b729e6e5bef414" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b" - ] + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938" }, - "knownTransitions": { - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "8f8ac47ea084bdff5550df2b43427cafc2aa6177f7043a855046a59e3c6f1a16", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 17520881827267755355 + "knownTransitions": [ + { + "opid": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 9119672638623966453 + }, + "state": 539 }, - "state": 666 - } - ] - } - }, - "signature": null + { + "seal": "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90", + "state": 77 + } + ] + } + }, + "signature": null + } } - } + ] } } ], diff --git a/tests/fixtures/attack_genesis_schema_id.json b/tests/fixtures/attack_genesis_schema_id.json index 1d3b9e9..68a059c 100644 --- a/tests/fixtures/attack_genesis_schema_id.json +++ b/tests/fixtures/attack_genesis_schema_id.json @@ -5,7 +5,7 @@ "genesis": { "ffv": 0, "schemaId": "rgb:sch:JgqK5hJX9YBT4osCV7VcW_iLTcA5csUCnLzvaKTTrNY#mars-house-friend", - "timestamp": 1747745161, + "timestamp": 1750883671, "issuer": "ssi:anonymous", "chainNet": "bitcoinRegtest", "sealClosingStrategy": "firstOpretOrTapret", @@ -27,9 +27,9 @@ "items": [ { "seal": { - "txid": "2697bf250bfbfdf0232329e1c4d504df0a3afc7f155372c8344d14aa477978eb", + "txid": "4b8d99de8188a6769987e59faa7cdb70086608a05f38a336549770f047a64701", "vout": 1, - "blinding": 18077556918557531948 + "blinding": 15971490758955256628 }, "state": 666 } @@ -44,7 +44,7 @@ "version": 2, "inputs": [ { - "prevOutput": "5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9:2", + "prevOutput": "4b8d99de8188a6769987e59faa7cdb70086608a05f38a336549770f047a64701:1", "sigScript": "", "sequence": 0, "witness": [] @@ -53,15 +53,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a20f165d1e9ce1ee99e0c26a614b060b8ba964d053de9d2591d27fda3a42c4a06ea" + "scriptPubkey": "6a204266173b9f445e4e0738d460c90ed778eb152822ad9c14366c7fc07b20fcbcc3" }, { "value": 9000, - "scriptPubkey": "0014de56a95f365f2fdfac59c996d911807643318d45" + "scriptPubkey": "0014a38ad5e206733b28151e460e383991ffbdbdbfe9" }, { - "value": 99981200, - "scriptPubkey": "00140721467af22eceb7c10669839340d36b0550fb51" + "value": 99990600, + "scriptPubkey": "00146990e864fee7e996d191cf742d37d80fd47eab2f" } ], "lockTime": 0 @@ -69,63 +69,52 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "8b8e51703db9bdaf371d1f24e825bede7f195f4eddf9d8ee91a732e366f2fa22", - "a175c03717869069a81353f65ac325b9ae8420d68003a26e5c226fc94650b1cb", - "5fca309f0aa9feb868fa5ef4419252f16fe9370ed7ca2fb2b18a4e631eea6b22" + "50d3665113ef6571da5870d08ab7f2fd9a74a8fb8b885d72ba6e27ee443bd1f1", + "28ad1a030ca76f794d62a000e8d68101ed7855fc06ae56e1c10e64814c6dfbeb", + "26fd7ea39c056153b91b556d0a1d2bfd2d99a02d18ffdc5738fc0c565bf5cc56" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4" - ] + "6ed33f3dc88ef3682ac43fbe1ac4648245130d12fa1ab9f755a3c92f00b0178b/4000/0": "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658" }, - "knownTransitions": { - "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 1635815392667104294 - }, - "state": 50 - }, - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 2032282526052071825 - }, - "state": 616 - } - ] - } - }, - "signature": null + "knownTransitions": [ + { + "opid": "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "6ed33f3dc88ef3682ac43fbe1ac4648245130d12fa1ab9f755a3c92f00b0178b/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 5104376770230072053 + }, + "state": 666 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -134,7 +123,7 @@ "version": 2, "inputs": [ { - "prevOutput": "2697bf250bfbfdf0232329e1c4d504df0a3afc7f155372c8344d14aa477978eb:1", + "prevOutput": "143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd:2", "sigScript": "", "sequence": 0, "witness": [] @@ -143,15 +132,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a207d21d8c4829a93e3b28dc2624ce854dec0393025b252c884e15020be1fafa949" + "scriptPubkey": "6a20ec7439f82cb704cdc0e867ec63c6f88ecdb352266915e7b95639b26360ebbb6e" }, { "value": 9000, - "scriptPubkey": "001402bff690f27911f8412cb4047779ebd9eea228db" + "scriptPubkey": "00142842f7eabee95edda63fefc011bce78c69a9cd1d" }, { - "value": 99990600, - "scriptPubkey": "0014b31d8f364e330e328c0ab1baed3adb3873e3d9bb" + "value": 99981200, + "scriptPubkey": "0014f62a638b6981c9396ea76109aed6ef5f5981a303" } ], "lockTime": 0 @@ -159,55 +148,60 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "688ed0d51c1f2d7e3d6a7eb2a2a047d931838c752b6e45e0f426fff55f9d3a84", - "2da91d03506ba70b5db5ff1bb090139a00c5db85793f4b24b1bb428c17718d24", - "3a65fcfd4ef2917c6d514fde2c49a6a226a7ce44d842d70332668f502412a8f3" + "f250b9b3d529f03b634d1b400fcc1c722e3d5da1723e55634d053bf241966f36", + "95b11bf9d3c76e118677fee7ccddb3fb86ccd42c813d254737c3156484b9916f", + "0cc8e38d92681cbfc54e90e42a9ff9e1944b3e2e2caa6fd6b8fa98d865f69811" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26" - ] + "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658/4000/0": "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a" }, - "knownTransitions": { - "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "dcdb65b22f2cb4ee4c0a99c246e77a790b57f2e84134ff1286d37b40d61dac67", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 16601173385335492688 + "knownTransitions": [ + { + "opid": "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 14095570581868621249 + }, + "state": 50 }, - "state": 666 - } - ] - } - }, - "signature": null + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 8503444477660371154 + }, + "state": 616 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -216,7 +210,7 @@ "version": 2, "inputs": [ { - "prevOutput": "5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54:2", + "prevOutput": "84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3:2", "sigScript": "", "sequence": 0, "witness": [] @@ -225,15 +219,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a2004a2379274e2e46d4728b9f77e41fd50fe11c16fb407256f3240b39178c10e43" + "scriptPubkey": "6a20ded4a8d8dba904936aeea30e8bc0ae524b64c3500bc9cfe94895dc77bfde35d9" }, { "value": 9000, - "scriptPubkey": "00147cc7738422dd879427daa2facf25fd9aa052593f" + "scriptPubkey": "0014fe9163be63b335ae4640e5011d610feb791713db" }, { "value": 99971800, - "scriptPubkey": "00140af5321f1a7064480f0cedb1531cea66254329f8" + "scriptPubkey": "0014282993ddc2ba6d84598e751a93429395d460c7f9" } ], "lockTime": 0 @@ -241,63 +235,60 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "5f044994a45a923dc171e42054ad3a716cedfb03d20cac4aabbabb797f58fa0d", - "0af457bc1888e4dbf7788ecb06411ebd352bcca74dee3f2304ef7d53c9fd8ab8", - "2f6dea82c781e92c1142d4a7d1be4bb27e0ffb91fab718918c51bdc812db66a5" + "a5b9eb9691493220613a6207567cc40c00b69c960c417b83c63ffe98dd1582cc", + "c91ec5dbc524954e5ec1321bcab56cb1f06c3a6759b5d9ff8560f159f39a8c49", + "061191e16060e63aaf24c4c0e0d4795a5e8762f201ee7745abae967346812236" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "c8f4df6ae56b0c00a8d5747beea427d38319ab8fe85069a0634cf69a88fa67a0" - ] + "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a/4000/1": "21c09f8ead108258bcdf2e7bbb0de231974b351b9cebe69e283beb6a99590628" }, - "knownTransitions": { - "c8f4df6ae56b0c00a8d5747beea427d38319ab8fe85069a0634cf69a88fa67a0": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4", - "ty": 4000, - "no": 1 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 14130614574817494517 - }, - "state": 77 - }, - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 7391128784690907900 + "knownTransitions": [ + { + "opid": "21c09f8ead108258bcdf2e7bbb0de231974b351b9cebe69e283beb6a99590628", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a/4000/1" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 2964060174665201768 + }, + "state": 77 }, - "state": 539 - } - ] - } - }, - "signature": null + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 17353984293023054398 + }, + "state": 539 + } + ] + } + }, + "signature": null + } } - } + ] } } ], diff --git a/tests/fixtures/attack_genesis_testnet.json b/tests/fixtures/attack_genesis_testnet.json index 82649bd..bd64a4a 100644 --- a/tests/fixtures/attack_genesis_testnet.json +++ b/tests/fixtures/attack_genesis_testnet.json @@ -5,7 +5,7 @@ "genesis": { "ffv": 0, "schemaId": "rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus", - "timestamp": 1747745161, + "timestamp": 1750883671, "issuer": "ssi:anonymous", "chainNet": "bitcoinMainnet", "sealClosingStrategy": "firstOpretOrTapret", @@ -27,9 +27,9 @@ "items": [ { "seal": { - "txid": "2697bf250bfbfdf0232329e1c4d504df0a3afc7f155372c8344d14aa477978eb", + "txid": "4b8d99de8188a6769987e59faa7cdb70086608a05f38a336549770f047a64701", "vout": 1, - "blinding": 18077556918557531948 + "blinding": 15971490758955256628 }, "state": 666 } @@ -44,7 +44,7 @@ "version": 2, "inputs": [ { - "prevOutput": "5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9:2", + "prevOutput": "4b8d99de8188a6769987e59faa7cdb70086608a05f38a336549770f047a64701:1", "sigScript": "", "sequence": 0, "witness": [] @@ -53,15 +53,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a20f165d1e9ce1ee99e0c26a614b060b8ba964d053de9d2591d27fda3a42c4a06ea" + "scriptPubkey": "6a204266173b9f445e4e0738d460c90ed778eb152822ad9c14366c7fc07b20fcbcc3" }, { "value": 9000, - "scriptPubkey": "0014de56a95f365f2fdfac59c996d911807643318d45" + "scriptPubkey": "0014a38ad5e206733b28151e460e383991ffbdbdbfe9" }, { - "value": 99981200, - "scriptPubkey": "00140721467af22eceb7c10669839340d36b0550fb51" + "value": 99990600, + "scriptPubkey": "00146990e864fee7e996d191cf742d37d80fd47eab2f" } ], "lockTime": 0 @@ -69,63 +69,52 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "8b8e51703db9bdaf371d1f24e825bede7f195f4eddf9d8ee91a732e366f2fa22", - "a175c03717869069a81353f65ac325b9ae8420d68003a26e5c226fc94650b1cb", - "5fca309f0aa9feb868fa5ef4419252f16fe9370ed7ca2fb2b18a4e631eea6b22" + "50d3665113ef6571da5870d08ab7f2fd9a74a8fb8b885d72ba6e27ee443bd1f1", + "28ad1a030ca76f794d62a000e8d68101ed7855fc06ae56e1c10e64814c6dfbeb", + "26fd7ea39c056153b91b556d0a1d2bfd2d99a02d18ffdc5738fc0c565bf5cc56" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4" - ] + "6ed33f3dc88ef3682ac43fbe1ac4648245130d12fa1ab9f755a3c92f00b0178b/4000/0": "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658" }, - "knownTransitions": { - "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 1635815392667104294 - }, - "state": 50 - }, - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 2032282526052071825 - }, - "state": 616 - } - ] - } - }, - "signature": null + "knownTransitions": [ + { + "opid": "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "6ed33f3dc88ef3682ac43fbe1ac4648245130d12fa1ab9f755a3c92f00b0178b/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 5104376770230072053 + }, + "state": 666 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -134,7 +123,7 @@ "version": 2, "inputs": [ { - "prevOutput": "2697bf250bfbfdf0232329e1c4d504df0a3afc7f155372c8344d14aa477978eb:1", + "prevOutput": "143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd:2", "sigScript": "", "sequence": 0, "witness": [] @@ -143,15 +132,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a207d21d8c4829a93e3b28dc2624ce854dec0393025b252c884e15020be1fafa949" + "scriptPubkey": "6a20ec7439f82cb704cdc0e867ec63c6f88ecdb352266915e7b95639b26360ebbb6e" }, { "value": 9000, - "scriptPubkey": "001402bff690f27911f8412cb4047779ebd9eea228db" + "scriptPubkey": "00142842f7eabee95edda63fefc011bce78c69a9cd1d" }, { - "value": 99990600, - "scriptPubkey": "0014b31d8f364e330e328c0ab1baed3adb3873e3d9bb" + "value": 99981200, + "scriptPubkey": "0014f62a638b6981c9396ea76109aed6ef5f5981a303" } ], "lockTime": 0 @@ -159,55 +148,60 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "688ed0d51c1f2d7e3d6a7eb2a2a047d931838c752b6e45e0f426fff55f9d3a84", - "2da91d03506ba70b5db5ff1bb090139a00c5db85793f4b24b1bb428c17718d24", - "3a65fcfd4ef2917c6d514fde2c49a6a226a7ce44d842d70332668f502412a8f3" + "f250b9b3d529f03b634d1b400fcc1c722e3d5da1723e55634d053bf241966f36", + "95b11bf9d3c76e118677fee7ccddb3fb86ccd42c813d254737c3156484b9916f", + "0cc8e38d92681cbfc54e90e42a9ff9e1944b3e2e2caa6fd6b8fa98d865f69811" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26" - ] + "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658/4000/0": "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a" }, - "knownTransitions": { - "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "dcdb65b22f2cb4ee4c0a99c246e77a790b57f2e84134ff1286d37b40d61dac67", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 16601173385335492688 + "knownTransitions": [ + { + "opid": "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 14095570581868621249 + }, + "state": 50 }, - "state": 666 - } - ] - } - }, - "signature": null + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 8503444477660371154 + }, + "state": 616 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -216,7 +210,7 @@ "version": 2, "inputs": [ { - "prevOutput": "5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54:2", + "prevOutput": "84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3:2", "sigScript": "", "sequence": 0, "witness": [] @@ -225,15 +219,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a2004a2379274e2e46d4728b9f77e41fd50fe11c16fb407256f3240b39178c10e43" + "scriptPubkey": "6a20ded4a8d8dba904936aeea30e8bc0ae524b64c3500bc9cfe94895dc77bfde35d9" }, { "value": 9000, - "scriptPubkey": "00147cc7738422dd879427daa2facf25fd9aa052593f" + "scriptPubkey": "0014fe9163be63b335ae4640e5011d610feb791713db" }, { "value": 99971800, - "scriptPubkey": "00140af5321f1a7064480f0cedb1531cea66254329f8" + "scriptPubkey": "0014282993ddc2ba6d84598e751a93429395d460c7f9" } ], "lockTime": 0 @@ -241,63 +235,60 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "5f044994a45a923dc171e42054ad3a716cedfb03d20cac4aabbabb797f58fa0d", - "0af457bc1888e4dbf7788ecb06411ebd352bcca74dee3f2304ef7d53c9fd8ab8", - "2f6dea82c781e92c1142d4a7d1be4bb27e0ffb91fab718918c51bdc812db66a5" + "a5b9eb9691493220613a6207567cc40c00b69c960c417b83c63ffe98dd1582cc", + "c91ec5dbc524954e5ec1321bcab56cb1f06c3a6759b5d9ff8560f159f39a8c49", + "061191e16060e63aaf24c4c0e0d4795a5e8762f201ee7745abae967346812236" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "c8f4df6ae56b0c00a8d5747beea427d38319ab8fe85069a0634cf69a88fa67a0" - ] + "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a/4000/1": "21c09f8ead108258bcdf2e7bbb0de231974b351b9cebe69e283beb6a99590628" }, - "knownTransitions": { - "c8f4df6ae56b0c00a8d5747beea427d38319ab8fe85069a0634cf69a88fa67a0": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4", - "ty": 4000, - "no": 1 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 14130614574817494517 - }, - "state": 77 - }, - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 7391128784690907900 + "knownTransitions": [ + { + "opid": "21c09f8ead108258bcdf2e7bbb0de231974b351b9cebe69e283beb6a99590628", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a/4000/1" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 2964060174665201768 + }, + "state": 77 }, - "state": 539 - } - ] - } - }, - "signature": null + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 17353984293023054398 + }, + "state": 539 + } + ] + } + }, + "signature": null + } } - } + ] } } ], diff --git a/tests/fixtures/attack_resolver_error.json b/tests/fixtures/attack_resolver_error.json index da463f4..4b1f151 100644 --- a/tests/fixtures/attack_resolver_error.json +++ b/tests/fixtures/attack_resolver_error.json @@ -2,14 +2,14 @@ "version": "v0", "transfer": true, "terminals": { - "9d4b73f7964529cfd46536f640c40d0ec5ac20bff54e00f7d101b26c16dfae13": [ - "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0" + "f5f7500948a8ae8ad6db4d551c6f317f5c02de23edb07bbff34cea2bfcbe4cb1": [ + "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90" ] }, "genesis": { "ffv": 0, "schemaId": "rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus", - "timestamp": 1747745043, + "timestamp": 1750883619, "issuer": "ssi:anonymous", "chainNet": "bitcoinRegtest", "sealClosingStrategy": "firstOpretOrTapret", @@ -31,9 +31,9 @@ "items": [ { "seal": { - "txid": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13", + "txid": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7", "vout": 1, - "blinding": 13113921856262959977 + "blinding": 15882975521680157652 }, "state": 666 } @@ -48,7 +48,7 @@ "version": 2, "inputs": [ { - "prevOutput": "c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9:1", + "prevOutput": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7:1", "sigScript": "", "sequence": 0, "witness": [] @@ -57,11 +57,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a20f75dffbafa81de29f1b767a81f47e9ace789223e6854b388c8ff72b480e9bc65" + "scriptPubkey": "6a2004b86f6d44449be00a1b75a13d671ad44da9b388367102b2a6ee668389313b5b" }, { - "value": 99998800, - "scriptPubkey": "0014a6558396fcd09a1cb1773b09e9a7033ffe5f7843" + "value": 99999600, + "scriptPubkey": "00148467a4cb9231d8da59df02de1a82ce5761b6d59e" } ], "lockTime": 0 @@ -69,120 +69,110 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "7584c919969fced81f6309b7a6d817e0e2bc6240e5b41759d90719efec4235c3", - "048867a3370db6815e3a90093e0f3e8a16f19c39953e91af5bb426ab2a3aabfd", - "ad31b376af0d04b0f5088abf077b405cad2f9b9760e0c27dddc463cdad289af2" + "871af4b1c4ec5ab8d17b6ee08f50ba823f497b3e3e32e8d4ed6171cf101596c5", + "52e4b4229303ac38fcb7258d8bec1c2cf79344c1e80d55b9b3ce4328e5bef1d5", + "f35512c5b4e2cd46bf866036d0778d87d7c74bf460208fa6d08a7a35655c9d69" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291" - ] + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0" }, - "knownTransitions": { - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 12961427178433477692 - }, - "state": 539 - }, - { - "seal": "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0", - "state": 77 - } - ] - } - }, - "signature": null + "knownTransitions": [ + { + "opid": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 17454843376278179683 + }, + "state": 666 + } + ] + } + }, + "signature": null + } } - } + ] } }, { "pubWitness": { - "txid": "c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9" + "txid": "b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2" }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "e194ceb0f09362d49969e8f4ddfee873ac6760ede382351fdead1dab3c0ab0d0", - "9bfdf671b70582032db385ec98c07f01060ff467918a9a812cf6c00bedb22180", - "e04fcb9eaf2a716f7c0c5e3a538cc3ed4580b3ae2e658fe0d2eef9e46fd952a6" + "ca3be1e1847652a7e803f4599f73f1cf200bf05ab9cceda8e30a372c8216fdfe", + "6471737aeb42e46cdcd5d7f57cd56406806d7630938b764c16ba04b547ef3bf4", + "27915b2641c8ad41aa1dd2198c752aa58a84f8d58849f50fba7c8252318a3ea0" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d" - ] + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941" }, - "knownTransitions": { - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 10003067900325773186 + "knownTransitions": [ + { + "opid": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 7476137096582570779 + }, + "state": 616 }, - "state": 616 - }, - { - "seal": "18a82040f68755c128b28eacdb9af7c8a0bed32b2a52f5dcba6c45b51d83bdf3", - "state": 50 - } - ] - } - }, - "signature": null + { + "seal": "88a6eddc7feb428eb58fbd64728a33bfdc673f375a57d4bd59371ca92369e40f", + "state": 50 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -191,7 +181,7 @@ "version": 2, "inputs": [ { - "prevOutput": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13:1", + "prevOutput": "b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2:1", "sigScript": "", "sequence": 0, "witness": [] @@ -200,11 +190,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a204bba687d2198a9a049b75255ea3fbdf5b648437ffb7757c258a95cb1232a5fa6" + "scriptPubkey": "6a20d87aa6b06a714562dc4e9f5a9e24e6dfda5684d880480ba6f54262702c55a7a5" }, { - "value": 99999600, - "scriptPubkey": "00149aeec847f99c80464389ed96e80de8bb147d6227" + "value": 99998800, + "scriptPubkey": "001469ade53185b381ac4428fdd0edbca6368403e9d0" } ], "lockTime": 0 @@ -212,55 +202,56 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "315234829e1fd969c450b5651cd33d9282c081dc7f87cb7f321e34186ed2a476", - "6efee2e679ba3987921bbdb3ff2b5c254d823072fed90a7f661c82e5a9b97363", - "2608cec7dc2d6f14c1e89d3f8aaf81dcc79146c063c1b62b52a3923f1dec0ec9" + "a3a23db672daad69d0717c9740d1ffc937f8c95b479340a97a61c2979262a44d", + "ee360ceb6a0a463c92710b7213bbac8e0f3bfc1fafa7ad09fcc4782dff90ea9e", + "2f48a5c7ffff1fc60b698c18224bb847fd603359ecd61852f9b729e6e5bef414" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b" - ] + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938" }, - "knownTransitions": { - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "8f8ac47ea084bdff5550df2b43427cafc2aa6177f7043a855046a59e3c6f1a16", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 17520881827267755355 + "knownTransitions": [ + { + "opid": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 9119672638623966453 + }, + "state": 539 }, - "state": 666 - } - ] - } - }, - "signature": null + { + "seal": "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90", + "state": 77 + } + ] + } + }, + "signature": null + } } - } + ] } } ], diff --git a/tests/fixtures/b243f251cd06181c5568e041ed19106512886bf2c8617dfd3bf06c2321c5f8f4.json b/tests/fixtures/b243f251cd06181c5568e041ed19106512886bf2c8617dfd3bf06c2321c5f8f4.json new file mode 100644 index 0000000..47f98aa --- /dev/null +++ b/tests/fixtures/b243f251cd06181c5568e041ed19106512886bf2c8617dfd3bf06c2321c5f8f4.json @@ -0,0 +1,25 @@ +{ + "version": 2, + "inputs": [ + { + "prevOutput": "b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2:1", + "sigScript": "", + "sequence": 0, + "witness": [ + "3044022053e67d7dffae33f5e239f8d5161db4bf1793039ba17c1883224043bef449ba3f022043ce8e0a662fc1883a1bbb07636cef987b0cddfe13313ebba3c4fec9c27222a201", + "0245c8116b53e8d01ba153028ed0230425801f5209465475902abbdeb5079b7937" + ] + } + ], + "outputs": [ + { + "value": 0, + "scriptPubkey": "6a20d87aa6b06a714562dc4e9f5a9e24e6dfda5684d880480ba6f54262702c55a7a5" + }, + { + "value": 99998800, + "scriptPubkey": "001469ade53185b381ac4428fdd0edbca6368403e9d0" + } + ], + "lockTime": 0 +} \ No newline at end of file diff --git a/tests/fixtures/b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2.json b/tests/fixtures/b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2.json new file mode 100644 index 0000000..b4656dd --- /dev/null +++ b/tests/fixtures/b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2.json @@ -0,0 +1,25 @@ +{ + "version": 2, + "inputs": [ + { + "prevOutput": "b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b:1", + "sigScript": "", + "sequence": 0, + "witness": [ + "3045022100f45a2532bb9c03be0f961be8e471f91b5204380a2994d2399aa150051c734614022013b66870fef6ff683e04cf84b08e6c7ed913c3361aa722e988e9006d207b268301", + "02a0169b1fdae78d33891cadfc82549b9f295e555bf2466f71fc82fd1bd3e5ec25" + ] + } + ], + "outputs": [ + { + "value": 0, + "scriptPubkey": "6a20bc53e837e022ea6083e4ad64efcca8371e031710118834615df7098715cf87a6" + }, + { + "value": 99999200, + "scriptPubkey": "00145c3afeb169a9fa6828c917b6e61ae123951806f4" + } + ], + "lockTime": 0 +} \ No newline at end of file diff --git a/tests/fixtures/b7729e80544704769c690e6c5d4f103d0183eba1ef2b81fa4f41158697dd4b2a.json b/tests/fixtures/b7729e80544704769c690e6c5d4f103d0183eba1ef2b81fa4f41158697dd4b2a.json deleted file mode 100644 index 207973a..0000000 --- a/tests/fixtures/b7729e80544704769c690e6c5d4f103d0183eba1ef2b81fa4f41158697dd4b2a.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": 2, - "inputs": [ - { - "prevOutput": "c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9:1", - "sigScript": "", - "sequence": 0, - "witness": [ - "304402201ad61d49194d3929a808a7ba14d241f7c5d639d81dfefe09b4590031579ca9d70220266072217f643745da25d1225efdab6b2ba61972fb01cffa880675ee6836b1a101", - "02ee092d5390cfe8ae0c2113d6a85e6f52d2a7037c43fea99aa436350ca8eefa2a" - ] - } - ], - "outputs": [ - { - "value": 0, - "scriptPubkey": "6a20f75dffbafa81de29f1b767a81f47e9ace789223e6854b388c8ff72b480e9bc65" - }, - { - "value": 99998800, - "scriptPubkey": "0014a6558396fcd09a1cb1773b09e9a7033ffe5f7843" - } - ], - "lockTime": 0 -} \ No newline at end of file diff --git a/tests/fixtures/b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b.json b/tests/fixtures/b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b.json new file mode 100644 index 0000000..a2fee2f --- /dev/null +++ b/tests/fixtures/b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b.json @@ -0,0 +1,25 @@ +{ + "version": 2, + "inputs": [ + { + "prevOutput": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7:1", + "sigScript": "", + "sequence": 0, + "witness": [ + "3045022100cbe68467f587b7988836921e51b054a45b64967fd8bf2f91edb1aef8a6a97b5202202a8806310d4a5a35ca74e0617b2f279bf36feedaa390233f50ea6593445989d501", + "0310a53e3fe344cbd0a2ff08b21a34d4bc05324b97b4173ccf9668a8b774a941ad" + ] + } + ], + "outputs": [ + { + "value": 0, + "scriptPubkey": "6a2004b86f6d44449be00a1b75a13d671ad44da9b388367102b2a6ee668389313b5b" + }, + { + "value": 99999600, + "scriptPubkey": "00148467a4cb9231d8da59df02de1a82ce5761b6d59e" + } + ], + "lockTime": 0 +} \ No newline at end of file diff --git a/tests/fixtures/c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9.json b/tests/fixtures/c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9.json deleted file mode 100644 index e5dadcf..0000000 --- a/tests/fixtures/c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": 2, - "inputs": [ - { - "prevOutput": "e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0:1", - "sigScript": "", - "sequence": 0, - "witness": [ - "304502210082ae1a665793ab4d7553e4e1f556a6cecd685bfce0c4e713cd15b840be74ee4c02202380d1129f7319a3d3a457a46d066f1950d51f39c1017b216804829401a5837b01", - "02b6a3a109661cde313199439e0c316f786cc1406add7224bcee32609373f2323f" - ] - } - ], - "outputs": [ - { - "value": 0, - "scriptPubkey": "6a201f129c99327c5cd54125d7c2091bb8962bf04147254459a38070587e1349d89c" - }, - { - "value": 99999200, - "scriptPubkey": "001438ef9ad1ee0663a43b8b30a7c1d4705f071779db" - } - ], - "lockTime": 0 -} \ No newline at end of file diff --git a/tests/fixtures/consignment_A.json b/tests/fixtures/consignment_A.json index 80dc750..ce2cf3d 100644 --- a/tests/fixtures/consignment_A.json +++ b/tests/fixtures/consignment_A.json @@ -2,14 +2,14 @@ "version": "v0", "transfer": true, "terminals": { - "9d4b73f7964529cfd46536f640c40d0ec5ac20bff54e00f7d101b26c16dfae13": [ - "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0" + "f5f7500948a8ae8ad6db4d551c6f317f5c02de23edb07bbff34cea2bfcbe4cb1": [ + "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90" ] }, "genesis": { "ffv": 0, "schemaId": "rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus", - "timestamp": 1747745043, + "timestamp": 1750883619, "issuer": "ssi:anonymous", "chainNet": "bitcoinRegtest", "sealClosingStrategy": "firstOpretOrTapret", @@ -31,9 +31,9 @@ "items": [ { "seal": { - "txid": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13", + "txid": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7", "vout": 1, - "blinding": 13113921856262959977 + "blinding": 15882975521680157652 }, "state": 666 } @@ -48,7 +48,7 @@ "version": 2, "inputs": [ { - "prevOutput": "c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9:1", + "prevOutput": "4caa17eae3f082765ce50dceaddd4e0ec4cef41d162bd42a3bbbbb076de649a7:1", "sigScript": "", "sequence": 0, "witness": [] @@ -57,11 +57,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a20f75dffbafa81de29f1b767a81f47e9ace789223e6854b388c8ff72b480e9bc65" + "scriptPubkey": "6a2004b86f6d44449be00a1b75a13d671ad44da9b388367102b2a6ee668389313b5b" }, { - "value": 99998800, - "scriptPubkey": "0014a6558396fcd09a1cb1773b09e9a7033ffe5f7843" + "value": 99999600, + "scriptPubkey": "00148467a4cb9231d8da59df02de1a82ce5761b6d59e" } ], "lockTime": 0 @@ -69,59 +69,52 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "7584c919969fced81f6309b7a6d817e0e2bc6240e5b41759d90719efec4235c3", - "048867a3370db6815e3a90093e0f3e8a16f19c39953e91af5bb426ab2a3aabfd", - "ad31b376af0d04b0f5088abf077b405cad2f9b9760e0c27dddc463cdad289af2" + "871af4b1c4ec5ab8d17b6ee08f50ba823f497b3e3e32e8d4ed6171cf101596c5", + "52e4b4229303ac38fcb7258d8bec1c2cf79344c1e80d55b9b3ce4328e5bef1d5", + "f35512c5b4e2cd46bf866036d0778d87d7c74bf460208fa6d08a7a35655c9d69" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291" - ] + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0" }, - "knownTransitions": { - "a6af59b5b69fbbc490683801a2174ceb9d0531de9133da0aac2350d439a78291": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 12961427178433477692 - }, - "state": 539 - }, - { - "seal": "e651af63e80c3584261ab1ce5fde181c730df2baed13569aa3620953ddd140f0", - "state": 77 - } - ] - } - }, - "signature": null + "knownTransitions": [ + { + "opid": "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2e75cd43bb1215c25a059a70231c3d1fc876baedf57b01cad5523ec86becab9c/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 17454843376278179683 + }, + "state": 666 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -130,7 +123,7 @@ "version": 2, "inputs": [ { - "prevOutput": "e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0:1", + "prevOutput": "b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b:1", "sigScript": "", "sequence": 0, "witness": [] @@ -139,11 +132,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a201f129c99327c5cd54125d7c2091bb8962bf04147254459a38070587e1349d89c" + "scriptPubkey": "6a20bc53e837e022ea6083e4ad64efcca8371e031710118834615df7098715cf87a6" }, { "value": 99999200, - "scriptPubkey": "001438ef9ad1ee0663a43b8b30a7c1d4705f071779db" + "scriptPubkey": "00145c3afeb169a9fa6828c917b6e61ae123951806f4" } ], "lockTime": 0 @@ -151,59 +144,56 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "e194ceb0f09362d49969e8f4ddfee873ac6760ede382351fdead1dab3c0ab0d0", - "9bfdf671b70582032db385ec98c07f01060ff467918a9a812cf6c00bedb22180", - "e04fcb9eaf2a716f7c0c5e3a538cc3ed4580b3ae2e658fe0d2eef9e46fd952a6" + "ca3be1e1847652a7e803f4599f73f1cf200bf05ab9cceda8e30a372c8216fdfe", + "6471737aeb42e46cdcd5d7f57cd56406806d7630938b764c16ba04b547ef3bf4", + "27915b2641c8ad41aa1dd2198c752aa58a84f8d58849f50fba7c8252318a3ea0" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d" - ] + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941" }, - "knownTransitions": { - "f80fa0989d0776589f621bbe2bce3b3ef50ccb50a9001b458623a433494f686d": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 10003067900325773186 + "knownTransitions": [ + { + "opid": "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "7eef21683f363a4204ff35d97261b4cde102930337bb716dff19b1c11bb382a0/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 7476137096582570779 + }, + "state": 616 }, - "state": 616 - }, - { - "seal": "18a82040f68755c128b28eacdb9af7c8a0bed32b2a52f5dcba6c45b51d83bdf3", - "state": 50 - } - ] - } - }, - "signature": null + { + "seal": "88a6eddc7feb428eb58fbd64728a33bfdc673f375a57d4bd59371ca92369e40f", + "state": 50 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -212,7 +202,7 @@ "version": 2, "inputs": [ { - "prevOutput": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13:1", + "prevOutput": "b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2:1", "sigScript": "", "sequence": 0, "witness": [] @@ -221,11 +211,11 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a204bba687d2198a9a049b75255ea3fbdf5b648437ffb7757c258a95cb1232a5fa6" + "scriptPubkey": "6a20d87aa6b06a714562dc4e9f5a9e24e6dfda5684d880480ba6f54262702c55a7a5" }, { - "value": 99999600, - "scriptPubkey": "00149aeec847f99c80464389ed96e80de8bb147d6227" + "value": 99998800, + "scriptPubkey": "001469ade53185b381ac4428fdd0edbca6368403e9d0" } ], "lockTime": 0 @@ -233,55 +223,56 @@ }, "anchor": { "mpcProof": { - "pos": 7, + "pos": 6, "cofactor": 0, "path": [ - "315234829e1fd969c450b5651cd33d9282c081dc7f87cb7f321e34186ed2a476", - "6efee2e679ba3987921bbdb3ff2b5c254d823072fed90a7f661c82e5a9b97363", - "2608cec7dc2d6f14c1e89d3f8aaf81dcc79146c063c1b62b52a3923f1dec0ec9" + "a3a23db672daad69d0717c9740d1ffc937f8c95b479340a97a61c2979262a44d", + "ee360ceb6a0a463c92710b7213bbac8e0f3bfc1fafa7ad09fcc4782dff90ea9e", + "2f48a5c7ffff1fc60b698c18224bb847fd603359ecd61852f9b729e6e5bef414" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b" - ] + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938" }, - "knownTransitions": { - "1fed9153734dabd6c81a45116e198bd6bb8002cba7dcd5fdb6e152bb99867f6b": { - "ffv": 0, - "contractId": "rgb:j4rEfqCE-vf9VUN8-rQ0J8r8-KqYXf3B-DqFUEal-njxvGhY", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "8f8ac47ea084bdff5550df2b43427cafc2aa6177f7043a855046a59e3c6f1a16", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 17520881827267755355 + "knownTransitions": [ + { + "opid": "12d445f14163f7b7ffdad877e9f733198b904f42d01dd32a25cc4b52f6aac938", + "transition": { + "ffv": 0, + "contractId": "rgb:LnXNQ7sS-FcJaBZp-wIxw9H8-h2uu31e-wHK1VI_-yGvsq5w", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "2c7cffddfae7bdacb0ef1044a912af88855a443fa9fcd475eab1b90fdb455941/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 9119672638623966453 + }, + "state": 539 }, - "state": 666 - } - ] - } - }, - "signature": null + { + "seal": "2312d1e66065930131fbaf955acd1bbc9d62de82e81b4da8a0b3f7a7fb8d5a90", + "state": 77 + } + ] + } + }, + "signature": null + } } - } + ] } } ], diff --git a/tests/fixtures/consignment_B.json b/tests/fixtures/consignment_B.json index babebab..4c3f54d 100644 --- a/tests/fixtures/consignment_B.json +++ b/tests/fixtures/consignment_B.json @@ -5,7 +5,7 @@ "genesis": { "ffv": 0, "schemaId": "rgb:sch:RWhwUfTMpuP2Zfx1~j4nswCANGeJrYOqDcKelaMV4zU#remote-digital-pegasus", - "timestamp": 1747745161, + "timestamp": 1750883671, "issuer": "ssi:anonymous", "chainNet": "bitcoinRegtest", "sealClosingStrategy": "firstOpretOrTapret", @@ -27,9 +27,9 @@ "items": [ { "seal": { - "txid": "2697bf250bfbfdf0232329e1c4d504df0a3afc7f155372c8344d14aa477978eb", + "txid": "4b8d99de8188a6769987e59faa7cdb70086608a05f38a336549770f047a64701", "vout": 1, - "blinding": 18077556918557531948 + "blinding": 15971490758955256628 }, "state": 666 } @@ -44,7 +44,7 @@ "version": 2, "inputs": [ { - "prevOutput": "5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9:2", + "prevOutput": "4b8d99de8188a6769987e59faa7cdb70086608a05f38a336549770f047a64701:1", "sigScript": "", "sequence": 0, "witness": [] @@ -53,15 +53,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a20f165d1e9ce1ee99e0c26a614b060b8ba964d053de9d2591d27fda3a42c4a06ea" + "scriptPubkey": "6a204266173b9f445e4e0738d460c90ed778eb152822ad9c14366c7fc07b20fcbcc3" }, { "value": 9000, - "scriptPubkey": "0014de56a95f365f2fdfac59c996d911807643318d45" + "scriptPubkey": "0014a38ad5e206733b28151e460e383991ffbdbdbfe9" }, { - "value": 99981200, - "scriptPubkey": "00140721467af22eceb7c10669839340d36b0550fb51" + "value": 99990600, + "scriptPubkey": "00146990e864fee7e996d191cf742d37d80fd47eab2f" } ], "lockTime": 0 @@ -69,63 +69,52 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "8b8e51703db9bdaf371d1f24e825bede7f195f4eddf9d8ee91a732e366f2fa22", - "a175c03717869069a81353f65ac325b9ae8420d68003a26e5c226fc94650b1cb", - "5fca309f0aa9feb868fa5ef4419252f16fe9370ed7ca2fb2b18a4e631eea6b22" + "50d3665113ef6571da5870d08ab7f2fd9a74a8fb8b885d72ba6e27ee443bd1f1", + "28ad1a030ca76f794d62a000e8d68101ed7855fc06ae56e1c10e64814c6dfbeb", + "26fd7ea39c056153b91b556d0a1d2bfd2d99a02d18ffdc5738fc0c565bf5cc56" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4" - ] + "6ed33f3dc88ef3682ac43fbe1ac4648245130d12fa1ab9f755a3c92f00b0178b/4000/0": "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658" }, - "knownTransitions": { - "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 1635815392667104294 - }, - "state": 50 - }, - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 2032282526052071825 - }, - "state": 616 - } - ] - } - }, - "signature": null + "knownTransitions": [ + { + "opid": "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "6ed33f3dc88ef3682ac43fbe1ac4648245130d12fa1ab9f755a3c92f00b0178b/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 5104376770230072053 + }, + "state": 666 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -134,7 +123,7 @@ "version": 2, "inputs": [ { - "prevOutput": "2697bf250bfbfdf0232329e1c4d504df0a3afc7f155372c8344d14aa477978eb:1", + "prevOutput": "143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd:2", "sigScript": "", "sequence": 0, "witness": [] @@ -143,15 +132,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a207d21d8c4829a93e3b28dc2624ce854dec0393025b252c884e15020be1fafa949" + "scriptPubkey": "6a20ec7439f82cb704cdc0e867ec63c6f88ecdb352266915e7b95639b26360ebbb6e" }, { "value": 9000, - "scriptPubkey": "001402bff690f27911f8412cb4047779ebd9eea228db" + "scriptPubkey": "00142842f7eabee95edda63fefc011bce78c69a9cd1d" }, { - "value": 99990600, - "scriptPubkey": "0014b31d8f364e330e328c0ab1baed3adb3873e3d9bb" + "value": 99981200, + "scriptPubkey": "0014f62a638b6981c9396ea76109aed6ef5f5981a303" } ], "lockTime": 0 @@ -159,55 +148,60 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "688ed0d51c1f2d7e3d6a7eb2a2a047d931838c752b6e45e0f426fff55f9d3a84", - "2da91d03506ba70b5db5ff1bb090139a00c5db85793f4b24b1bb428c17718d24", - "3a65fcfd4ef2917c6d514fde2c49a6a226a7ce44d842d70332668f502412a8f3" + "f250b9b3d529f03b634d1b400fcc1c722e3d5da1723e55634d053bf241966f36", + "95b11bf9d3c76e118677fee7ccddb3fb86ccd42c813d254737c3156484b9916f", + "0cc8e38d92681cbfc54e90e42a9ff9e1944b3e2e2caa6fd6b8fa98d865f69811" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26" - ] + "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658/4000/0": "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a" }, - "knownTransitions": { - "e70b34e8fa9f851fa4061e8c75b2364b5f45c20fa3d4b5acdc572e8fd7413c26": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "dcdb65b22f2cb4ee4c0a99c246e77a790b57f2e84134ff1286d37b40d61dac67", - "ty": 4000, - "no": 0 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 16601173385335492688 + "knownTransitions": [ + { + "opid": "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "31f87d18b87fc70e808bb8043e4cebddc2aa2896b4c4cf407865a38db0257658/4000/0" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 14095570581868621249 + }, + "state": 50 }, - "state": 666 - } - ] - } - }, - "signature": null + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 8503444477660371154 + }, + "state": 616 + } + ] + } + }, + "signature": null + } } - } + ] } }, { @@ -216,7 +210,7 @@ "version": 2, "inputs": [ { - "prevOutput": "5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54:2", + "prevOutput": "84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3:2", "sigScript": "", "sequence": 0, "witness": [] @@ -225,15 +219,15 @@ "outputs": [ { "value": 0, - "scriptPubkey": "6a2004a2379274e2e46d4728b9f77e41fd50fe11c16fb407256f3240b39178c10e43" + "scriptPubkey": "6a20ded4a8d8dba904936aeea30e8bc0ae524b64c3500bc9cfe94895dc77bfde35d9" }, { "value": 9000, - "scriptPubkey": "00147cc7738422dd879427daa2facf25fd9aa052593f" + "scriptPubkey": "0014fe9163be63b335ae4640e5011d610feb791713db" }, { "value": 99971800, - "scriptPubkey": "00140af5321f1a7064480f0cedb1531cea66254329f8" + "scriptPubkey": "0014282993ddc2ba6d84598e751a93429395d460c7f9" } ], "lockTime": 0 @@ -241,63 +235,60 @@ }, "anchor": { "mpcProof": { - "pos": 4, + "pos": 6, "cofactor": 0, "path": [ - "5f044994a45a923dc171e42054ad3a716cedfb03d20cac4aabbabb797f58fa0d", - "0af457bc1888e4dbf7788ecb06411ebd352bcca74dee3f2304ef7d53c9fd8ab8", - "2f6dea82c781e92c1142d4a7d1be4bb27e0ffb91fab718918c51bdc812db66a5" + "a5b9eb9691493220613a6207567cc40c00b69c960c417b83c63ffe98dd1582cc", + "c91ec5dbc524954e5ec1321bcab56cb1f06c3a6759b5d9ff8560f159f39a8c49", + "061191e16060e63aaf24c4c0e0d4795a5e8762f201ee7745abae967346812236" ] }, "dbcProof": null }, "bundle": { "inputMap": { - "0": [ - "c8f4df6ae56b0c00a8d5747beea427d38319ab8fe85069a0634cf69a88fa67a0" - ] + "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a/4000/1": "21c09f8ead108258bcdf2e7bbb0de231974b351b9cebe69e283beb6a99590628" }, - "knownTransitions": { - "c8f4df6ae56b0c00a8d5747beea427d38319ab8fe85069a0634cf69a88fa67a0": { - "ffv": 0, - "contractId": "rgb:3Ntlsi8s-tO5MCpn-CRud6eQ-tX8uhBN-P8ShtN7-QNYdrGc", - "nonce": 18446744073709551615, - "transitionType": 10000, - "metadata": {}, - "globals": {}, - "inputs": [ - { - "op": "84743251f680efd86179366bba1a12b3bef3a0325dd35845e59337a7cc7b63b4", - "ty": 4000, - "no": 1 - } - ], - "assignments": { - "4000": { - "type": "fungible", - "items": [ - { - "seal": { - "txid": null, - "vout": 1, - "blinding": 14130614574817494517 - }, - "state": 77 - }, - { - "seal": { - "txid": null, - "vout": 2, - "blinding": 7391128784690907900 + "knownTransitions": [ + { + "opid": "21c09f8ead108258bcdf2e7bbb0de231974b351b9cebe69e283beb6a99590628", + "transition": { + "ffv": 0, + "contractId": "rgb:btM~PciO-82gqxD_-_GsRkgk-UTDRL6G-rn3VaPJ-LwCwF4s", + "nonce": 18446744073709551615, + "transitionType": 10000, + "metadata": {}, + "globals": {}, + "inputs": [ + "348ec8956f9dbf0cc5fb8de31adfb146b6567c1d5ec2abdaff8b203ca0045e1a/4000/1" + ], + "assignments": { + "4000": { + "type": "fungible", + "items": [ + { + "seal": { + "txid": null, + "vout": 1, + "blinding": 2964060174665201768 + }, + "state": 77 }, - "state": 539 - } - ] - } - }, - "signature": null + { + "seal": { + "txid": null, + "vout": 2, + "blinding": 17353984293023054398 + }, + "state": 539 + } + ] + } + }, + "signature": null + } } - } + ] } } ], diff --git a/tests/fixtures/e031ca3d4cf33f8d003d9362b8c91692ee2eba943bb3ec3b86588d816fe965b9.json b/tests/fixtures/e031ca3d4cf33f8d003d9362b8c91692ee2eba943bb3ec3b86588d816fe965b9.json deleted file mode 100644 index 94c8f21..0000000 --- a/tests/fixtures/e031ca3d4cf33f8d003d9362b8c91692ee2eba943bb3ec3b86588d816fe965b9.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "version": 2, - "inputs": [ - { - "prevOutput": "5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54:2", - "sigScript": "", - "sequence": 0, - "witness": [ - "304402200bf023a07037030f059d10f6425f5daa176930cd4becc559cdeaf7da176d347802203b669dc79158d4f3a97c6d14df1742f3d1e2ca43e28174dc63dbed4f63860c8d01", - "0290689a4033869f8eac1f56131889f944eabba29fc710bd655700bf2b6e06b93c" - ] - } - ], - "outputs": [ - { - "value": 0, - "scriptPubkey": "6a2004a2379274e2e46d4728b9f77e41fd50fe11c16fb407256f3240b39178c10e43" - }, - { - "value": 9000, - "scriptPubkey": "00147cc7738422dd879427daa2facf25fd9aa052593f" - }, - { - "value": 99971800, - "scriptPubkey": "00140af5321f1a7064480f0cedb1531cea66254329f8" - } - ], - "lockTime": 0 -} \ No newline at end of file diff --git a/tests/fixtures/e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0.json b/tests/fixtures/e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0.json deleted file mode 100644 index 054b2cd..0000000 --- a/tests/fixtures/e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "version": 2, - "inputs": [ - { - "prevOutput": "aedcde1133e96fdb1a130b5f3899d2a5932ff3d05378c0455f9c858fe7c5ec13:1", - "sigScript": "", - "sequence": 0, - "witness": [ - "30440220096cf460aa52b2e4b5b6c00d9b1d95036aebb6d270d5fa95eaa75bd0fa8768f20220668cc982690d7e72700d41ff0d3309210724399050c9db4d81168feadadaddce01", - "02c33b7a4b43895fbaea5234147bd96a00a2d7be5c84b67239221ea254a5b2fcbe" - ] - } - ], - "outputs": [ - { - "value": 0, - "scriptPubkey": "6a204bba687d2198a9a049b75255ea3fbdf5b648437ffb7757c258a95cb1232a5fa6" - }, - { - "value": 99999600, - "scriptPubkey": "00149aeec847f99c80464389ed96e80de8bb147d6227" - } - ], - "lockTime": 0 -} \ No newline at end of file diff --git a/tests/issuance.rs b/tests/issuance.rs index 9b0146e..ea3bb3c 100644 --- a/tests/issuance.rs +++ b/tests/issuance.rs @@ -480,7 +480,7 @@ fn deterministic_contract_id(#[case] asset_schema: AssetSchema) { } AssetSchema::Ifa => ( AssetInfo::default_ifa(vec![999], vec![], vec![]), - "rgb:0BE~U89N-BCpNAvM-qLVH764-GyTkV4x-78PP7Y7-xNMcZng", + "rgb:0XcqlfD6-ccXYzWp-iTGCnA_-nBh9yKq-O~oMQRA-Nq54JBI", ), }; diff --git a/tests/stress.rs b/tests/stress.rs index c46d473..5555c68 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -91,5 +91,5 @@ fn back_and_forth( report.end_line(); } let elapsed = now.elapsed(); - println!("elapsed: {:.2?}", elapsed); + println!("elapsed: {elapsed:.2?}"); } diff --git a/tests/transfers.rs b/tests/transfers.rs index 1015e4d..4aa7b2d 100644 --- a/tests/transfers.rs +++ b/tests/transfers.rs @@ -1592,6 +1592,110 @@ fn ifa_inflation() { assert_eq!(inflatable, 0); } +#[cfg(not(feature = "altered"))] +#[test] +fn ifa_move_inflation_right() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issued_supply = 999; + let inflation_supply = 555; + let inflation_outpoint = wlt_1.get_utxo(None); + let contract_id = wlt_1.issue_ifa( + issued_supply, + None, + vec![], + vec![(inflation_outpoint, inflation_supply)], + ); + let schema_id = wlt_1.schema_id(contract_id); + + // partially move inflation right from wlt_1 to wlt_2 + let inflation_moved = 55; + let inflation_moved_utxo = wlt_2.get_utxo(None); + let mut invoice = wlt_2.invoice( + contract_id, + schema_id, + inflation_moved, + InvoiceType::Blinded(Some(inflation_moved_utxo)), + ); + invoice.assignment_name = Some(FieldName::from_str("inflationAllowance").unwrap()); + wlt_1.send_ifa_to_invoice(&mut wlt_2, invoice); + let contract = wlt_2.contract_wrapper::(contract_id); + let inflation_allocations = contract + .inflation_allocations(AllocationFilter::Wallet.filter_for(&wlt_2)) + .collect::>(); + let inflation_outpoints = inflation_allocations + .iter() + .map(|oa| oa.seal.outpoint().unwrap()) + .collect::>(); + assert_eq!(inflation_outpoints.len(), 1); + assert_eq!(inflation_outpoints[0], inflation_moved_utxo); + assert_eq!( + inflation_allocations + .iter() + .map(|oa| oa.state.value()) + .sum::(), + inflation_moved + ); + + // inflate asset with wlt_2 + wlt_2.inflate_ifa( + contract_id, + vec![inflation_moved_utxo], + vec![inflation_moved], + ); + let contract = wlt_2.contract_wrapper::(contract_id); + assert_eq!( + contract.total_issued_supply().value(), + issued_supply + inflation_moved + ); + + // inflate asset with wlt_1 + let contract = wlt_1.contract_wrapper::(contract_id); + let inflation_change_utxo = contract + .inflation_allocations(AllocationFilter::Wallet.filter_for(&wlt_1)) + .map(|oa| oa.seal.outpoint().unwrap()) + .collect::>()[0]; + let inflation_change = inflation_supply - inflation_moved; + wlt_1.inflate_ifa( + contract_id, + vec![inflation_change_utxo], + vec![inflation_change], + ); + let contract = wlt_1.contract_wrapper::(contract_id); + let wlt_1_amt = issued_supply + inflation_change; + assert_eq!(contract.total_issued_supply().value(), wlt_1_amt); + + // wlt_1 sends all to wlt_2 + wlt_1.send_ifa(&mut wlt_2, TransferType::Blinded, contract_id, wlt_1_amt); + wlt_1.check_allocations(contract_id, AssetSchema::Ifa, vec![], false); + wlt_2.check_allocations( + contract_id, + AssetSchema::Ifa, + vec![wlt_1_amt, inflation_moved], + false, + ); + + // check max supply has been reached, no more inflation allowed + let contract = wlt_2.contract_wrapper::(contract_id); + let max_supply = contract.max_supply().value(); + let total_issued_supply = contract.total_issued_supply().value(); + assert_eq!(max_supply, total_issued_supply); + assert_eq!(max_supply, wlt_1_amt + inflation_moved); + let inflation_allocations = contract + .inflation_allocations(AllocationFilter::Wallet.filter_for(&wlt_2)) + .collect::>(); + assert_eq!( + inflation_allocations + .iter() + .map(|oa| oa.state.value()) + .sum::(), + 0 + ); +} + #[cfg(not(feature = "altered"))] #[test] fn ifa_burn() { @@ -1696,6 +1800,680 @@ fn ifa_replace() { assert_eq!(replace_rights.len(), 1); } +#[cfg(not(feature = "altered"))] +#[should_panic(expected = "ExtraKnownTransition")] +#[test] +fn extra_known_transition() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issued_amt = 900; + let contract_id = wlt_1.issue_nia(issued_amt, None); + let asset_schema = wlt_1.asset_schema(contract_id); + let schema_id = wlt_1.schema_id(contract_id); + let contract = wlt_1.stock().contract_data(contract_id).unwrap(); + let assignment_type = contract + .schema + .assignment_types_for_state(asset_schema.default_state_type())[0]; + let transition_type = contract + .schema + .default_transition_for_assignment(assignment_type); + + let utxo_1 = wlt_1.get_utxo(Some(8000)); + let amt_0 = 500; + let invoice = wlt_1.invoice( + contract_id, + schema_id, + amt_0, + InvoiceType::Blinded(Some(utxo_1)), + ); + let (consignment, tx, _, _) = wlt_1.pay_full(invoice, None, None, true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_1.accept_transfer(consignment, None); + wlt_1.sync(); + + let (base_consignment, tx) = wlt_1.send( + &mut wlt_2, + InvoiceType::Blinded(None), + contract_id, + amt_0, + 1000, + None, + ); + let base_txid = tx.txid(); + + // allocate additional assets on spent utxo_1 + let amt_1 = 400; + let invoice = wlt_1.invoice( + contract_id, + schema_id, + amt_1, + InvoiceType::Blinded(Some(utxo_1)), + ); + let (consignment, tx, _, _) = wlt_1.pay_full(invoice, None, None, true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_1.accept_transfer(consignment, None); + wlt_1.sync(); + + let (opout, _) = wlt_1 + .stock() + .contract_assignments_for(contract_id, vec![utxo_1]) + .unwrap() + .into_values() + .flat_map(|s| s.into_iter()) + .find(|(_, s)| match s { + AllocatedState::Amount(a) => a.as_u64() == amt_1, + _ => { + panic!("unexpected allocatedState"); + } + }) + .unwrap(); + + let mut new_consignment = base_consignment.clone(); + let mut bundles = base_consignment.bundles.release().clone(); + + let mut transition_builder = wlt_1 + .stock() + .transition_builder_raw(contract_id, transition_type) + .unwrap(); + let state = asset_schema.allocated_state(amt_1); + transition_builder = transition_builder.add_input(opout, state.clone()).unwrap(); + let secret_seal = wlt_2.get_secret_seal(None, None); + transition_builder = transition_builder + .add_owned_state_raw(*assignment_type, BuilderSeal::Concealed(secret_seal), state) + .unwrap(); + let new_transition = transition_builder.complete_transition().unwrap(); + let new_opid = new_transition.id(); + + let new_bundle = bundles + .iter_mut() + .find(|b| b.pub_witness.txid() == base_txid) + .unwrap(); + let bundle_id = new_bundle.bundle.bundle_id(); + new_bundle + .bundle + .known_transitions + .push(KnownTransition::new(new_opid, new_transition)) + .unwrap(); + assert_eq!(bundle_id, new_bundle.bundle.bundle_id()); + assert!(new_bundle.bundle.known_transitions_contain_opid(&new_opid)); + new_consignment.bundles = LargeVec::from_checked(bundles); + + wlt_2.accept_transfer(new_consignment, None); +} + +#[cfg(not(feature = "altered"))] +#[should_panic(expected = "MissingInputMapTransition")] +#[test] +fn uncommitted_input_opout() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issued_amt = 900; + let contract_id = wlt_1.issue_nia(issued_amt, None); + let schema_id = wlt_1.schema_id(contract_id); + + // split issued amount into 2 opouts + let amt_0 = 500; + let invoice = wlt_1.invoice(contract_id, schema_id, amt_0, InvoiceType::Witness); + let (consignment, tx, _, _) = wlt_1.pay_full(invoice, None, None, true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_1.accept_transfer(consignment, None); + wlt_1.sync(); + + // merge the 2 allocation to send to wlt_2 + let invoice = wlt_2.invoice(contract_id, schema_id, issued_amt, InvoiceType::Witness); + let (mut psbt, _, mut consignment) = wlt_1.pay(invoice, None, None); + let prev_txids = consignment + .bundles + .iter() + .map(|wb| wb.witness_id()) + .collect::>(); + + // remove commitment to one of the spent opouts + consignment.modify_bundle(psbt.txid(), |witness_bundle| { + let mut input_map = witness_bundle.bundle.input_map.clone().release(); + input_map.pop_last(); + witness_bundle.bundle.input_map = NonEmptyOrdMap::from_checked(input_map); + let mut witness_psbt = Psbt::from_tx(witness_bundle.pub_witness.tx().unwrap().clone()); + let idx = witness_psbt + .outputs() + .find(|o| o.script.is_op_return()) + .unwrap() + .index(); + let contract_id = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .contract_id; + let protocol_id = mpc::ProtocolId::from(contract_id); + let message = mpc::Message::from(witness_bundle.bundle.bundle_id()); + witness_psbt.output_mut(idx).unwrap().script = ScriptPubkey::op_return(&[]); + witness_psbt + .output_mut(idx) + .unwrap() + .set_opret_host() + .unwrap(); + witness_psbt + .output_mut(idx) + .unwrap() + .set_mpc_message(protocol_id, message) + .unwrap(); + let (commitment, proof) = witness_psbt.output_mut(idx).unwrap().mpc_commit().unwrap(); + witness_psbt + .output_mut(idx) + .unwrap() + .opret_commit(commitment) + .unwrap(); + let witness: Tx = witness_psbt.to_unsigned_tx().into(); + witness_bundle.anchor.mpc_proof = proof.to_merkle_proof(protocol_id).unwrap(); + witness_bundle.pub_witness = PubWitness::Tx(witness.clone()); + }); + let tx = consignment + .bundles + .iter() + .find(|wb| !prev_txids.contains(&wb.witness_id())) + .unwrap() + .pub_witness + .tx() + .unwrap(); + let opret_script = tx + .outputs() + .find(|o| o.script_pubkey.is_op_return()) + .unwrap() + .script_pubkey + .clone(); + psbt.outputs_mut() + .find(|o| o.script.is_op_return()) + .unwrap() + .script = opret_script; + assert_eq!(tx.txid(), psbt.txid()); + let new_tx = wlt_1.sign_finalize_extract(&mut psbt); + wlt_1.broadcast_tx(&new_tx); + wlt_2.accept_transfer(consignment, None); +} + +#[cfg(not(feature = "altered"))] +#[test] +fn concealed_known_transition() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let issued_amt = 700; + let contract_id = wlt_1.issue_nia(issued_amt, None); + let asset_schema = wlt_1.asset_schema(contract_id); + let schema_id = wlt_1.schema_id(contract_id); + let contract = wlt_1.stock().contract_data(contract_id).unwrap(); + let assignment_type = contract + .schema + .assignment_types_for_state(asset_schema.default_state_type())[0]; + let transition_type = contract + .schema + .default_transition_for_assignment(assignment_type); + + // prepare 2 allocations on utxo + let utxo = wlt_1.get_utxo(None); + + let amt_1 = 300; + let invoice = wlt_1.invoice( + contract_id, + schema_id, + amt_1, + InvoiceType::Blinded(Some(utxo)), + ); + let (consignment, tx, _, _) = wlt_1.pay_full(invoice, None, None, true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_1.accept_transfer(consignment, None); + wlt_1.sync(); + + let amt_2 = 400; + let invoice = wlt_1.invoice( + contract_id, + schema_id, + amt_2, + InvoiceType::Blinded(Some(utxo)), + ); + let (consignment, tx, _, _) = wlt_1.pay_full(invoice, None, None, true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_1.accept_transfer(consignment, None); + wlt_1.sync(); + + // retrieve the two opouts on utxo + let allocations = wlt_1 + .stock() + .contract_assignments_for(contract_id, vec![utxo]) + .unwrap() + .into_values() + .flat_map(|v| v.into_iter()) + .collect::>(); + assert_eq!(allocations.len(), 2); + let (opout_1, amt_1) = if let (opout, AllocatedState::Amount(state)) = allocations[0] { + (opout, state.as_u64()) + } else { + panic!("unexpected state type"); + }; + let (opout_2, amt_2) = if let (opout, AllocatedState::Amount(state)) = allocations[1] { + (opout, state.as_u64()) + } else { + panic!("unexpected state type"); + }; + + // construct transaction committing to bundle with missing transition + let btc_change = wlt_1.get_address(); + let (mut psbt, _) = wlt_1.construct_psbt(vec![utxo], vec![(btc_change, None)], None); + psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO); + psbt.output_mut(1).unwrap().set_opret_host().unwrap(); + psbt.set_rgb_close_method(CloseMethod::OpretFirst); + + // 1st transition + let mut transition_builder = wlt_1 + .stock() + .transition_builder_raw(contract_id, transition_type) + .unwrap(); + let state = asset_schema.allocated_state(amt_1); + transition_builder = transition_builder + .add_input(opout_1, state.clone()) + .unwrap(); + let secret_seal_1 = wlt_2.get_secret_seal(None, None); + let seal_1 = BuilderSeal::Concealed(secret_seal_1); + transition_builder = transition_builder + .add_owned_state_raw(*assignment_type, seal_1, state) + .unwrap(); + let transition = transition_builder.complete_transition().unwrap(); + for opout in transition.inputs() { + // this is not necessary since it's done by push_rgb_transition, + // but it shows that it's idempotent + psbt.set_rgb_contract_consumer(contract_id, opout, transition.id()) + .unwrap(); + } + psbt.push_rgb_transition(transition).unwrap(); + + // 2nd transition + let mut transition_builder = wlt_1 + .stock() + .transition_builder_raw(contract_id, transition_type) + .unwrap(); + let state = asset_schema.allocated_state(amt_2); + transition_builder = transition_builder + .add_input(opout_2, state.clone()) + .unwrap(); + let secret_seal_2 = wlt_2.get_secret_seal(None, None); + let seal_2 = BuilderSeal::Concealed(secret_seal_2); + transition_builder = transition_builder + .add_owned_state_raw(*assignment_type, seal_2, state) + .unwrap(); + let transition = transition_builder.complete_transition().unwrap(); + let opid_2 = transition.id(); + for opout in transition.inputs() { + psbt.set_rgb_contract_consumer(contract_id, opout, opid_2) + .unwrap(); + } + // we don't push this transition to keep it concealed + + psbt.complete_construction(); + let fascia = psbt.rgb_commit().unwrap(); + let witness_id = psbt.txid(); + wlt_1.consume_fascia(fascia, witness_id); + let tx = wlt_1.sign_finalize_extract(&mut psbt); + wlt_1.broadcast_tx(&tx); + wlt_2.sync(); + + let mut beneficiaries = AssetBeneficiariesMap::new(); + beneficiaries.insert(contract_id, vec![seal_1]); + let consignment = wlt_1.create_consignments(beneficiaries, witness_id)[0].clone(); + + // ensure the consignment contains the bundle with missing transition + let bundle = consignment + .bundles + .iter() + .find(|wb| wb.bundle.input_map_opids().contains(&opid_2)) + .unwrap(); + assert!(!bundle.bundle.known_transitions_contain_opid(&opid_2)); + + wlt_2.accept_transfer(consignment, None); +} + +#[cfg(not(feature = "altered"))] +#[test] +fn accept_bundle_missing_transitions() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_3 = get_wallet(&DescriptorType::Wpkh); + + let issued_amt = 700; + let contract_id = wlt_1.issue_nia(issued_amt, None); + let asset_schema = wlt_1.asset_schema(contract_id); + let schema_id = wlt_1.schema_id(contract_id); + let contract = wlt_1.stock().contract_data(contract_id).unwrap(); + let assignment_type = contract + .schema + .assignment_types_for_state(asset_schema.default_state_type())[0]; + let transition_type = contract + .schema + .default_transition_for_assignment(assignment_type); + + // split into 2 allocations + let utxo_1 = wlt_1.get_utxo(None); + let invoice = wlt_1.invoice( + contract_id, + schema_id, + 300, + InvoiceType::Blinded(Some(utxo_1)), + ); + let (consignment, tx, _, _) = wlt_1.pay_full(invoice, None, None, true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_1.accept_transfer(consignment.clone(), None); + wlt_1.sync(); + + // construct bundle that will be omitted in first validation + let utxo_2 = wlt_1.get_utxo(None); + let invoice = wlt_1.invoice( + contract_id, + schema_id, + 400, + InvoiceType::Blinded(Some(utxo_2)), + ); + let (consignment, tx, _, _) = wlt_1.pay_full(invoice, None, None, true, None); + wlt_1.mine_tx(&tx.txid(), false); + wlt_1.accept_transfer(consignment.clone(), None); + wlt_1.sync(); + let omit_wid = tx.txid(); + let omit_bid = consignment + .bundles + .iter() + .find(|wb| wb.witness_id() == omit_wid) + .unwrap() + .bundle + .bundle_id(); + + // retrieve the two opouts on utxo + let allocations = wlt_1 + .stock() + .contract_assignments_for(contract_id, vec![utxo_1]) + .unwrap() + .into_values() + .flat_map(|v| v.into_iter()) + .collect::>(); + assert_eq!(allocations.len(), 1); + let (opout_1, amt_1) = if let (opout, AllocatedState::Amount(state)) = allocations[0] { + (opout, state.as_u64()) + } else { + panic!("unexpected state type"); + }; + let allocations = wlt_1 + .stock() + .contract_assignments_for(contract_id, vec![utxo_2]) + .unwrap() + .into_values() + .flat_map(|v| v.into_iter()) + .collect::>(); + assert_eq!(allocations.len(), 1); + let (opout_2, amt_2) = if let (opout, AllocatedState::Amount(state)) = allocations[0] { + (opout, state.as_u64()) + } else { + panic!("unexpected state type"); + }; + + // construct bundle that will be accepted twice, first with missing transition + let btc_change = wlt_1.get_address(); + let (mut psbt, _) = wlt_1.construct_psbt(vec![utxo_1, utxo_2], vec![(btc_change, None)], None); + psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO); + psbt.output_mut(1).unwrap().set_opret_host().unwrap(); + psbt.set_rgb_close_method(CloseMethod::OpretFirst); + + // 1st transition (revealed) + let mut transition_builder = wlt_1 + .stock() + .transition_builder_raw(contract_id, transition_type) + .unwrap(); + let state = asset_schema.allocated_state(amt_1); + transition_builder = transition_builder + .add_input(opout_1, state.clone()) + .unwrap(); + let secret_seal_1 = wlt_2.get_secret_seal(None, None); + let seal_1 = BuilderSeal::Concealed(secret_seal_1); + transition_builder = transition_builder + .add_owned_state_raw(*assignment_type, seal_1, state) + .unwrap(); + let transition = transition_builder.complete_transition().unwrap(); + let opid_1 = transition.id(); + psbt.push_rgb_transition(transition).unwrap(); + + // 2nd transition (concealed at first, revealed later) + let mut transition_builder = wlt_1 + .stock() + .transition_builder_raw(contract_id, transition_type) + .unwrap(); + let state = asset_schema.allocated_state(amt_2); + transition_builder = transition_builder + .add_input(opout_2, state.clone()) + .unwrap(); + let secret_seal_2 = wlt_3.get_secret_seal(None, None); + let seal_2 = BuilderSeal::Concealed(secret_seal_2); + transition_builder = transition_builder + .add_owned_state_raw(*assignment_type, seal_2, state) + .unwrap(); + let transition = transition_builder.complete_transition().unwrap(); + let opid_2 = transition.id(); + psbt.push_rgb_transition(transition).unwrap(); + + psbt.complete_construction(); + let fascia = psbt.rgb_commit().unwrap(); + let witness_id = psbt.txid(); + wlt_1.consume_fascia(fascia, witness_id); + let tx = wlt_1.sign_finalize_extract(&mut psbt); + wlt_1.broadcast_tx(&tx); + wlt_2.sync(); + + let mut beneficiaries = AssetBeneficiariesMap::new(); + beneficiaries.insert(contract_id, vec![seal_1, seal_2]); + let consignment = wlt_1.create_consignments(beneficiaries, witness_id)[0].clone(); + + // wlt_2 accepts consignment with transition to wlt_3 concealed + let mut consignment_1 = consignment.clone(); + let mut new_bundle = consignment_1 + .bundles + .iter() + .find(|b| b.bundle.known_transitions.len() == 2) + .unwrap() + .clone(); + let bundle_id = new_bundle.bundle.bundle_id(); + new_bundle.bundle.known_transitions = Confined::from_checked( + new_bundle + .bundle + .known_transitions + .to_unconfined() + .into_iter() + .filter(|kt| kt.opid != opid_2) + .collect(), + ); + consignment_1.bundles = LargeVec::from_iter_checked( + consignment + .bundled_witnesses() + .filter(|wb| wb.witness_id() != omit_wid) + .cloned() + .map(|wb| { + if wb.witness_id() == witness_id { + new_bundle.clone() + } else { + wb + } + }), + ); + consignment_1.terminals.remove(&bundle_id).unwrap(); + consignment_1.terminals.remove(&omit_bid).unwrap(); + consignment_1 + .terminals + .insert(bundle_id, NonEmptyOrdSet::with(secret_seal_1).into()) + .unwrap(); + // wlt_2 accepts bundle with opid_1 revealed and opid_2 concealed + wlt_2.accept_transfer(consignment_1, None); + + let mut consignment_2 = consignment.clone(); + let mut new_bundle = consignment_2 + .bundles + .iter() + .find(|b| b.bundle.known_transitions.len() == 2) + .unwrap() + .clone(); + let bundle_id = new_bundle.bundle.bundle_id(); + new_bundle.bundle.known_transitions = Confined::from_checked( + new_bundle + .bundle + .known_transitions + .to_unconfined() + .into_iter() + .filter(|kt| kt.opid != opid_1) + .collect(), + ); + consignment_2.bundles = LargeVec::from_iter_checked( + consignment + .bundled_witnesses() + .filter(|wb| wb.witness_id() != omit_wid) + .cloned() + .map(|wb| { + if wb.witness_id() == witness_id { + new_bundle.clone() + } else { + wb + } + }), + ); + consignment_2.terminals.remove(&bundle_id).unwrap(); + consignment_2.terminals.remove(&omit_bid).unwrap(); + consignment_2 + .terminals + .insert(bundle_id, NonEmptyOrdSet::with(secret_seal_2).into()) + .unwrap(); + wlt_3.accept_transfer(consignment, None); + + // wlt_2 accepts the same bundle with opid_1 concealed and opid_2 revealed + let (consignment, _) = wlt_3.send( + &mut wlt_2, + InvoiceType::Blinded(None), + contract_id, + amt_2, + 0, + None, + ); + println!("{consignment:?}"); + + // wlt_2 can spend allocation from both opid_1 and opid_2 + wlt_2.check_allocations(contract_id, asset_schema, vec![amt_1, amt_2], false); + wlt_2.send( + &mut wlt_1, + InvoiceType::Blinded(None), + contract_id, + amt_1 + amt_2, + 0, + None, + ); +} + +#[cfg(not(feature = "altered"))] +#[test] +fn unordered_transitions_within_bundle() { + initialize(); + + let mut wlt_1 = get_wallet(&DescriptorType::Wpkh); + let mut wlt_2 = get_wallet(&DescriptorType::Wpkh); + + let utxo_0 = wlt_1.get_utxo(Some(8000)); + let issued_amt = 666; + let contract_id = wlt_1.issue_nia(issued_amt, Some(&utxo_0)); + let asset_schema = wlt_1.asset_schema(contract_id); + let contract = wlt_1.wallet.stock().contract_data(contract_id).unwrap(); + let assignment_type = contract + .schema + .assignment_types_for_state(asset_schema.default_state_type())[0]; + let transition_type = contract + .schema + .default_transition_for_assignment(assignment_type); + + let utxo_1 = wlt_1.get_utxo(Some(7000)); + + let utxo_2 = wlt_2.get_utxo(None); + let btc_change = wlt_1.get_address(); + let (mut psbt, _) = wlt_1.construct_psbt(vec![utxo_0, utxo_1], vec![(btc_change, None)], None); + psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO); + psbt.output_mut(1).unwrap().set_opret_host().unwrap(); + psbt.set_rgb_close_method(CloseMethod::OpretFirst); + + let mut beneficiaries = AssetBeneficiariesMap::new(); + let mut transition_builder = wlt_1 + .wallet + .stock() + .transition_builder_raw(contract_id, transition_type) + .unwrap(); + let opout = Opout::new( + OpId::copy_from_slice(contract_id.as_slice()).unwrap(), + *assignment_type, + 0, + ); + let state = asset_schema.allocated_state(issued_amt); + transition_builder = transition_builder.add_input(opout, state.clone()).unwrap(); + let seal = BuilderSeal::Revealed(GraphSeal::rand_from(utxo_1)); + transition_builder = transition_builder + .add_owned_state_raw(*assignment_type, seal, state) + .unwrap(); + beneficiaries.push((contract_id, vec![seal])); + let transition_1 = transition_builder.complete_transition().unwrap(); + let opid_1 = transition_1.id(); + psbt.push_rgb_transition(transition_1).unwrap(); + + let mut transition_builder = wlt_1 + .wallet + .stock() + .transition_builder_raw(contract_id, transition_type) + .unwrap(); + let opout = Opout::new(opid_1, *assignment_type, 0); + let state = asset_schema.allocated_state(issued_amt); + transition_builder = transition_builder.add_input(opout, state.clone()).unwrap(); + let seal = BuilderSeal::Concealed(wlt_2.get_secret_seal(Some(utxo_2), None)); + transition_builder = transition_builder + .add_owned_state_raw(*assignment_type, seal, state) + .unwrap(); + beneficiaries.push((contract_id, vec![seal])); + let mut transition_2 = transition_builder.clone().complete_transition().unwrap(); + // mine transition_2 until its opid is lower than transition_1 + while opid_1 < transition_2.id() { + transition_2.nonce -= 1; + } + psbt.push_rgb_transition(transition_2).unwrap(); + psbt.complete_construction(); + let fascia = psbt.rgb_commit().unwrap(); + let witness_id = psbt.txid(); + wlt_1.consume_fascia(fascia, witness_id); + + let tx = wlt_1.sign_finalize_extract(&mut psbt); + wlt_1.broadcast_tx(&tx); + wlt_2.sync(); + + let consignments = wlt_1.create_consignments(beneficiaries, witness_id); + for consignment in consignments { + wlt_2.accept_transfer(consignment, None); + } + + wlt_2.send( + &mut wlt_1, + InvoiceType::Witness, + contract_id, + issued_amt, + 1000, + None, + ); +} + #[cfg(not(feature = "altered"))] #[rstest] #[case(HistoryType::Linear, ReorgType::ChangeOrder)] diff --git a/tests/utils/chain.rs b/tests/utils/chain.rs index 7a214a6..24a29b7 100644 --- a/tests/utils/chain.rs +++ b/tests/utils/chain.rs @@ -13,7 +13,7 @@ pub enum Indexer { impl fmt::Display for Indexer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", format!("{:?}", self).to_lowercase()) + write!(f, "{}", format!("{self:?}").to_lowercase()) } } diff --git a/tests/utils/helpers.rs b/tests/utils/helpers.rs index 2c9f5f0..129d1f4 100644 --- a/tests/utils/helpers.rs +++ b/tests/utils/helpers.rs @@ -1,7 +1,7 @@ use super::*; pub struct TestWallet { - wallet: RgbWallet>, + pub wallet: RgbWallet>, signer: Option, wallet_dir: PathBuf, instance: u8, @@ -79,7 +79,7 @@ pub enum DescriptorType { impl fmt::Display for DescriptorType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", format!("{:?}", self).to_lowercase()) + write!(f, "{}", format!("{self:?}").to_lowercase()) } } @@ -104,7 +104,7 @@ pub enum TransferType { impl fmt::Display for TransferType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", format!("{:?}", self).to_lowercase()) + write!(f, "{}", format!("{self:?}").to_lowercase()) } } @@ -159,7 +159,7 @@ pub enum AssetSchema { impl fmt::Display for AssetSchema { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", format!("{:?}", self).to_lowercase()) + write!(f, "{}", format!("{self:?}").to_lowercase()) } } @@ -202,14 +202,14 @@ impl AssetSchema { kit.validate().unwrap() } - fn default_state_type(&self) -> StateType { + pub fn default_state_type(&self) -> StateType { match self { Self::Cfa | Self::Nia | Self::Pfa | Self::Ifa => StateType::Fungible, Self::Uda => StateType::Structured, } } - fn allocated_state(&self, value: u64) -> AllocatedState { + pub fn allocated_state(&self, value: u64) -> AllocatedState { match self { Self::Cfa | Self::Nia | Self::Pfa | Self::Ifa => AllocatedState::Amount(value.into()), Self::Uda => AllocatedState::Data( @@ -1061,6 +1061,10 @@ impl TestWallet { self.schema_id(contract_id).into() } + pub fn stock(&self) -> &Stock { + self.wallet.stock() + } + pub fn import_contract(&mut self, contract: &ValidContract, resolver: impl ResolveWitness) { self.wallet .stock_mut() @@ -1570,8 +1574,10 @@ impl TestWallet { secret_key: SecretKey, ) { let transition_signer = |witness_bundle: &mut WitnessBundle| { - for transition in witness_bundle.bundle_mut().known_transitions.values_mut() { - let transition_id: [u8; 32] = transition.id().as_ref().into_inner(); + for KnownTransition { opid, transition } in + witness_bundle.bundle_mut().known_transitions.iter_mut() + { + let transition_id: [u8; 32] = opid.as_ref().into_inner(); let msg = Message::from_digest(transition_id); let signature = secret_key.sign_ecdsa(msg); transition.signature = @@ -1703,11 +1709,6 @@ impl TestWallet { .add_metadata("allowedInflation", Amount::from(inflation_change)) .unwrap(); let transition = asset_transition_builder.complete_transition().unwrap(); - for input in psbt.inputs_mut() { - input - .set_rgb_consumer(contract_id, transition.id()) - .unwrap(); - } psbt.push_rgb_transition(transition).unwrap(); psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO) .set_opret_host() @@ -1726,7 +1727,7 @@ impl TestWallet { let all_opids = consignment .bundles .iter() - .flat_map(|b| b.bundle().known_transitions.keys().copied()) + .flat_map(|b| b.bundle().known_transitions_opids()) .collect::>(); let validated_consignment = consignment .clone() @@ -1787,11 +1788,6 @@ impl TestWallet { .add_rights("replaceRight", seal) .unwrap(); // add replace right let transition = asset_transition_builder.complete_transition().unwrap(); - for input in psbt.inputs_mut() { - input - .set_rgb_consumer(contract_id, transition.id()) - .unwrap(); - } psbt.push_rgb_transition(transition).unwrap(); psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO) .set_opret_host() @@ -1854,11 +1850,6 @@ impl TestWallet { } } let transition = asset_transition_builder.complete_transition().unwrap(); - for input in psbt.inputs_mut() { - input - .set_rgb_consumer(contract_id, transition.id()) - .unwrap(); - } psbt.push_rgb_transition(transition).unwrap(); psbt.construct_output_expect(ScriptPubkey::op_return(&[]), Sats::ZERO) .set_opret_host() @@ -2089,7 +2080,7 @@ impl TestWallet { .map(|txin| txin.prev_output) .collect::>(); - let mut all_transitions: HashMap = HashMap::new(); + let mut all_transitions: HashSet = HashSet::new(); let mut asset_beneficiaries: AssetBeneficiariesMap = bmap![]; for (contract_id, asset_coloring_info) in coloring_info.asset_info_map.clone() { @@ -2170,7 +2161,7 @@ impl TestWallet { } let transition = asset_transition_builder.complete_transition().unwrap(); - all_transitions.insert(contract_id, transition); + all_transitions.insert(transition); asset_beneficiaries.insert(contract_id, beneficiaries); } @@ -2191,24 +2182,7 @@ impl TestWallet { opreturn_output.set_mpc_entropy(blinding).unwrap(); } - let tx_inputs = psbt.clone().to_unsigned_tx().inputs; - for (contract_id, transition) in all_transitions { - for (input, txin) in psbt.inputs_mut().zip(&tx_inputs) { - let prevout = txin.prev_output; - let outpoint = Outpoint::new(prevout.txid.to_byte_array().into(), prevout.vout); - if coloring_info - .asset_info_map - .clone() - .get(&contract_id) - .unwrap() - .input_outpoints - .contains(&outpoint) - { - input - .set_rgb_consumer(contract_id, transition.id()) - .unwrap(); - } - } + for transition in all_transitions { psbt.push_rgb_transition(transition).unwrap(); } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index ce9b987..21b34eb 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -45,8 +45,13 @@ pub use std::{ pub use amplify::{ bmap, bset, - confinement::{Confined, U16}, - map, s, ByteArray, Bytes64, Wrapper, + confinement::{ + Collection, Confined, LargeVec, NonEmptyOrdMap, NonEmptyOrdSet, NonEmptyVec, SmallOrdMap, + TinyOrdMap, TinyOrdSet, U16, + }, + map, + num::u24, + s, ByteArray, Bytes64, Wrapper, }; use bitcoin_hashes::{sha256, Hash}; pub use bp::{ @@ -64,6 +69,7 @@ pub use bpwallet::{ Wallet, WalletUtxo, }; pub use chrono::Utc; +pub use commit_verify::mpc; pub use descriptors::Wpkh; pub use electrum::{Client as ElectrumClient, ElectrumApi, Param}; pub use file_format::FileFormat; @@ -73,35 +79,45 @@ pub use psbt::{ Utxo, }; #[cfg(not(feature = "altered"))] -pub use psrgbt::{RgbExt, RgbInExt, RgbPsbt, TxParams}; +pub use psrgbt::{RgbExt, RgbPsbt, TxParams}; #[cfg(feature = "altered")] -pub use psrgbt_altered::{RgbExt, RgbInExt, RgbPsbt, TxParams}; +pub use psrgbt_altered::{RgbExt, RgbPsbt, TxParams}; pub use rand::RngCore; #[cfg(not(feature = "altered"))] pub use rgb::{ + assignments::AssignVec, containers::{PubWitness, ValidContract, WitnessBundle}, contract::{AllocatedState, AssignmentsFilter, ContractOp, FilterIncludeAll, OpDirection}, info::ContractInfo, invoice::Pay2Vout, persistence::{MemContract, MemContractState, Stock}, stl::{ContractTerms, OpidRejectUrl}, + validation::Validator, validation::{Failure, ResolveWitness, Scripts, Validity, Warning, WitnessResolverError}, vm::{WitnessOrd, WitnessPos}, - AssignmentType, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, - RgbWallet, StateType, TapretKey, TransferParams, Transition, WalletProvider, + Assign, AssignmentDetails, AssignmentType, BundleId, DescriptorRgb, FungibleState, GenesisSeal, + GlobalDetails, GlobalStateSchema, GraphSeal, Identity, KnownTransition, MetaDetails, MetaType, + MetaValue, Occurrences, OccurrencesMismatch, OpId, Opout, OwnedStateSchema, RevealedData, + RevealedValue, RgbDescr, RgbKeychain, RgbWallet, StateType, TapretKey, TransferParams, + Transition, TransitionBundle, TransitionType, TypedAssigns, VoidState, WalletProvider, }; #[cfg(feature = "altered")] pub use rgb_altered::{ + assignments::AssignVec, containers::{PubWitness, ValidContract, WitnessBundle}, contract::{AllocatedState, AssignmentsFilter, ContractOp, FilterIncludeAll, OpDirection}, info::ContractInfo, invoice::Pay2Vout, persistence::{MemContract, MemContractState, Stock}, stl::{ContractTerms, OpidRejectUrl}, + validation::Validator, validation::{Failure, ResolveWitness, Scripts, Validity, Warning, WitnessResolverError}, vm::{WitnessOrd, WitnessPos}, - AssignmentType, DescriptorRgb, GenesisSeal, GraphSeal, Identity, OpId, RgbDescr, RgbKeychain, - RgbWallet, StateType, TapretKey, TransferParams, Transition, WalletProvider, + Assign, AssignmentDetails, AssignmentType, BundleId, DescriptorRgb, FungibleState, GenesisSeal, + GlobalDetails, GlobalStateSchema, GraphSeal, Identity, KnownTransition, MetaDetails, MetaType, + MetaValue, Occurrences, OccurrencesMismatch, OpId, Opout, OwnedStateSchema, RevealedData, + RevealedValue, RgbDescr, RgbKeychain, RgbWallet, StateType, TapretKey, TransferParams, + Transition, TransitionBundle, TransitionType, TypedAssigns, VoidState, WalletProvider, }; pub use rgbstd::{ containers::{ @@ -128,11 +144,11 @@ pub use rstest::rstest; pub use schemata::{ CollectibleFungibleAsset, InflatableFungibleAsset, NonInflatableAsset, PermissionedFungibleAsset, UniqueDigitalAsset, CFA_SCHEMA_ID, IFA_SCHEMA_ID, NIA_SCHEMA_ID, - PFA_SCHEMA_ID, UDA_SCHEMA_ID, + OS_ASSET, PFA_SCHEMA_ID, UDA_SCHEMA_ID, }; pub use serial_test::serial; pub use strict_encoding::{fname, tn, FieldName, StrictSerialize, TypeName}; -pub use strict_types::{StrictVal, TypeSystem}; +pub use strict_types::{SemId, StrictDumb, StrictVal, TypeSystem}; pub use strum::IntoEnumIterator; pub use strum_macros::EnumIter; pub use time::OffsetDateTime; diff --git a/tests/validation.rs b/tests/validation.rs index b3c5df6..c6233bc 100644 --- a/tests/validation.rs +++ b/tests/validation.rs @@ -2,16 +2,19 @@ pub mod utils; use utils::*; +#[derive(Clone)] enum MockResolvePubWitness { Success(Tx), Error(WitnessResolverError), } +#[derive(Clone)] enum MockResolvePubWitnessOrd { Success(WitnessOrd), Error(WitnessResolverError), } +#[derive(Clone)] struct MockResolver { pub_witnesses: HashMap, pub_witness_ords: HashMap, @@ -47,6 +50,20 @@ impl ResolveWitness for MockResolver { Ok(()) } } +impl MockResolver { + pub fn with_new_transaction(&self, witness: Tx) -> Self { + let mut resolver = self.clone(); + let witness_id = witness.txid(); + resolver + .pub_witnesses + .insert(witness_id, MockResolvePubWitness::Success(witness)); + resolver.pub_witness_ords.insert( + witness_id, + MockResolvePubWitnessOrd::Success(WitnessOrd::Tentative), + ); + resolver + } +} #[derive(Debug, EnumIter, Copy, Clone, PartialEq)] enum Scenario { @@ -56,7 +73,7 @@ enum Scenario { impl fmt::Display for Scenario { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) + write!(f, "{self:?}") } } @@ -65,11 +82,11 @@ impl Scenario { match self { Self::A => { let (tx_1, witness_id_1) = - get_tx("e68c51aede5479db97384efe8f3d0d4aadbc4dca96923ab821c837713140f1d0"); + get_tx("b8880c28cf9163673b7e39f2af6b6fec952425354c17c74b0d5e69d3c467142b"); let (tx_2, witness_id_2) = - get_tx("c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9"); + get_tx("b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2"); let (tx_3, witness_id_3) = - get_tx("b7729e80544704769c690e6c5d4f103d0183eba1ef2b81fa4f41158697dd4b2a"); + get_tx("b243f251cd06181c5568e041ed19106512886bf2c8617dfd3bf06c2321c5f8f4"); MockResolver { pub_witnesses: map![ witness_id_1 => MockResolvePubWitness::Success(tx_1), @@ -85,11 +102,11 @@ impl Scenario { } Self::B => { let (tx_1, witness_id_1) = - get_tx("5f61c1f5db43f98b2274e90babd90e085f9089aa48b7aa685f78ad930142d5a9"); + get_tx("143b34678a7e3e0d2dbbfbd14c6a163aed89d96e4992374154d3c1b5973a93cd"); let (tx_2, witness_id_2) = - get_tx("5259f55018e26bf50bfa1813e1e174710b368ac6e196f15a280388b429a31a54"); + get_tx("84e3ac658455e8969e03ac02dc487c9ccd2fcb10314f9d19b0b223cfb85e7ed3"); let (tx_3, witness_id_3) = - get_tx("e031ca3d4cf33f8d003d9362b8c91692ee2eba943bb3ec3b86588d816fe965b9"); + get_tx("333b0aea5cbf230791c57814de6dd86340e2626c1c1e8ac462f4f73c2645682c"); MockResolver { pub_witnesses: map![ witness_id_1 => MockResolvePubWitness::Success(tx_1), @@ -107,6 +124,85 @@ impl Scenario { } } +fn replace_transition_in_bundle( + witness_bundle: &mut WitnessBundle, + old_opid: OpId, + transition: Transition, +) { + let mut known_transitions = witness_bundle + .bundle + .known_transitions + .clone() + .into_iter() + .filter(|kt| kt.opid != old_opid) + .collect::>(); + let transition_id = transition.id(); + known_transitions.push(KnownTransition::new(transition_id, transition.clone())); + let input_map = witness_bundle + .bundle + .input_map + .clone() + .into_iter() + .map(|(opout, opid)| { + let new_opid = if opid == old_opid { + transition_id + } else { + opid + }; + (opout, new_opid) + }) + .collect(); + let bundle = TransitionBundle { + input_map: NonEmptyOrdMap::from_checked(input_map), + known_transitions: NonEmptyVec::from_checked(known_transitions), + }; + witness_bundle.bundle = bundle; + update_witness_and_anchor(witness_bundle, None) +} + +fn update_witness_and_anchor(witness_bundle: &mut WitnessBundle, contract_id: Option) { + let mut witness_psbt = Psbt::from_tx(witness_bundle.pub_witness.tx().unwrap().clone()); + let idx = witness_psbt + .outputs() + .find(|o| o.script.is_op_return()) + .unwrap() + .index(); + let contract_id = contract_id.unwrap_or( + witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .contract_id, + ); + let protocol_id = mpc::ProtocolId::from(contract_id); + let message = mpc::Message::from(witness_bundle.bundle.bundle_id()); + witness_psbt.output_mut(idx).unwrap().script = ScriptPubkey::op_return(&[]); + witness_psbt + .output_mut(idx) + .unwrap() + .set_opret_host() + .unwrap(); + witness_psbt + .output_mut(idx) + .unwrap() + .set_mpc_message(protocol_id, message) + .unwrap(); + let (commitment, proof) = witness_psbt.output_mut(idx).unwrap().mpc_commit().unwrap(); + witness_psbt + .output_mut(idx) + .unwrap() + .opret_commit(commitment) + .unwrap(); + let witness: Tx = witness_psbt.to_unsigned_tx().into(); + + let mut anchor = witness_bundle.anchor.clone(); + anchor.mpc_proof = proof.to_merkle_proof(protocol_id).unwrap(); + witness_bundle.pub_witness = PubWitness::Tx(witness.clone()); + witness_bundle.anchor = anchor; +} + fn get_consignment(scenario: Scenario) -> (Transfer, Vec) { initialize(); @@ -228,8 +324,12 @@ fn validate_consignment_chain_fail() { dbg!(&validation_status); assert!(validation_status.warnings.is_empty()); assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); + assert_eq!(validation_status.failures.len(), 1); + assert!(matches!( + validation_status.failures[0], + Failure::ContractChainNetMismatch(ChainNet::BitcoinRegtest) + )); + assert_eq!(validation_status.validity(), Validity::Invalid); } #[cfg(not(feature = "altered"))] @@ -246,7 +346,7 @@ fn validate_consignment_genesis_fail() { Err(status) => status, }; dbg!(&validation_status); - assert_eq!(validation_status.failures.len(), 5); + assert_eq!(validation_status.failures.len(), 4); assert!(matches!( validation_status.failures[0], Failure::OperationAbsent(_) @@ -255,18 +355,10 @@ fn validate_consignment_genesis_fail() { validation_status.failures[1], Failure::MpcInvalid(_, _, _) )); - assert!(matches!( - validation_status.failures[2], - Failure::BundleExtraTransition(_, _) - )); assert!(matches!( validation_status.failures[3], Failure::MpcInvalid(_, _, _) )); - assert!(matches!( - validation_status.failures[4], - Failure::MpcInvalid(_, _, _) - )); assert!(validation_status.warnings.is_empty()); assert!(validation_status.info.is_empty()); let validity = validation_status.validity(); @@ -317,7 +409,7 @@ fn validate_consignment_bundles_fail() { )); assert!(matches!( validation_status.failures[2], - Failure::BundleInvalidCommitment(_, _, _, _) + Failure::WitnessMissingInput(_, _, _) )); assert!(validation_status.warnings.is_empty()); assert!(validation_status.info.is_empty()); @@ -329,9 +421,16 @@ fn validate_consignment_bundles_fail() { #[test] fn validate_consignment_resolver_error() { let scenario = Scenario::A; - let mut resolver = scenario.resolver(); + let base_resolver = scenario.resolver(); + let consignment = get_consignment_from_json("attack_resolver_error"); let txid = - Txid::from_str("c0098d330a9c091340f9ff11c415f8584cd6451aecd16af1c7ab870937e6a4b9").unwrap(); + Txid::from_str("b411d8dd37353d243a527739fdc39cca22dbfe4fe92517ce16a33563803c5ad2").unwrap(); + let wbundle = consignment + .bundles + .iter() + .find(|wb| wb.witness_id() == txid) + .unwrap(); + let bundle_id = wbundle.bundle.bundle_id(); struct ConsignmentResolver<'a, 'cons, const TRANSFER: bool> { consignment: &'cons IndexedConsignment<'cons, TRANSFER>, @@ -354,9 +453,10 @@ fn validate_consignment_resolver_error() { } // resolve_pub_witness error + let mut resolver = base_resolver.clone(); + let resolver_error = WitnessResolverError::Other(txid, s!("unexpected error")); *resolver.pub_witnesses.get_mut(&txid).unwrap() = - MockResolvePubWitness::Error(WitnessResolverError::Other(txid, s!("unexpected error"))); - let consignment = get_consignment_from_json("attack_resolver_error"); + MockResolvePubWitness::Error(resolver_error.clone()); let consignment_resolver = ConsignmentResolver { consignment: &IndexedConsignment::new(&consignment), fallback: &resolver, @@ -371,26 +471,29 @@ fn validate_consignment_resolver_error() { }; dbg!(&validation_status); assert_eq!(validation_status.failures.len(), 1); - assert!(matches!( + assert_eq!( validation_status.failures[0], - Failure::SealNoPubWitness(_, _, _) - )); + Failure::SealNoPubWitness(bundle_id, txid, resolver_error) + ); assert!(validation_status.warnings.is_empty()); assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); + assert_eq!(validation_status.validity(), Validity::Invalid); + assert_eq!( + validation_status, + consignment + .clone() + .validate(&resolver, ChainNet::BitcoinRegtest, None) + .unwrap_err() + ); // resolve_pub_witness_ord error + let mut resolver = base_resolver.clone(); + let resolver_error = WitnessResolverError::Other(txid, s!("another unexpected error")); *resolver.pub_witness_ords.get_mut(&txid).unwrap() = - MockResolvePubWitnessOrd::Error(WitnessResolverError::Other(txid, s!("unexpected error"))); - let consignment = get_consignment_from_json("attack_resolver_error"); - let consignment_resolver = ConsignmentResolver { - consignment: &IndexedConsignment::new(&consignment), - fallback: &resolver, - }; + MockResolvePubWitnessOrd::Error(resolver_error.clone()); let res = consignment .clone() - .validate(&consignment_resolver, ChainNet::BitcoinRegtest, None); + .validate(&resolver, ChainNet::BitcoinRegtest, None); assert!(res.is_err()); let validation_status = match res { Ok(validated_consignment) => validated_consignment.validation_status().clone(), @@ -398,12 +501,781 @@ fn validate_consignment_resolver_error() { }; dbg!(&validation_status); assert_eq!(validation_status.failures.len(), 1); - assert!(matches!( + assert_eq!( validation_status.failures[0], - Failure::SealNoPubWitness(_, _, _) - )); + Failure::WitnessUnresolved(bundle_id, txid, resolver_error) + ); assert!(validation_status.warnings.is_empty()); assert!(validation_status.info.is_empty()); - let validity = validation_status.validity(); - assert_eq!(validity, Validity::Invalid); + assert_eq!(validation_status.validity(), Validity::Invalid); +} + +#[cfg(not(feature = "altered"))] +#[test] +fn validate_consignment_schema_fail() { + let scenario = Scenario::B; + let resolver = scenario.resolver(); + + let base_consignment = get_consignment_from_json(&format!("consignment_{scenario}")); + let transition_type = base_consignment.schema.transitions.keys().last().unwrap(); + + // SchemaOpMetaTypeUnknown: schema transition has unknown metatype + let mut consignment = base_consignment.clone(); + consignment + .schema + .transitions + .get_mut(transition_type) + .unwrap() + .transition_schema + .metadata = TinyOrdSet::from_checked(bset![MetaType::with(42)]); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + assert!(matches!( + failures[0], + Failure::SchemaOpMetaTypeUnknown(_, _) + )); + + // SchemaOpEmptyInputs: schema transition has no inputs + let mut consignment = base_consignment.clone(); + consignment + .schema + .transitions + .get_mut(transition_type) + .unwrap() + .transition_schema + .inputs = TinyOrdMap::new(); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + assert!(matches!(failures[0], Failure::SchemaOpEmptyInputs(_))); + + // SchemaOpGlobalTypeUnknown: schema transition has unknown global type + let mut consignment = base_consignment.clone(); + consignment + .schema + .transitions + .get_mut(transition_type) + .unwrap() + .transition_schema + .globals = TinyOrdMap::from_checked(bmap! { + GlobalStateType::with(42) => Occurrences::Once + }); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + assert!(matches!( + failures[0], + Failure::SchemaOpGlobalTypeUnknown(_, _) + )); + + // SchemaOpAssignmentTypeUnknown: schema transition has unknown assignment type + let mut consignment = base_consignment.clone(); + consignment + .schema + .transitions + .get_mut(transition_type) + .unwrap() + .transition_schema + .assignments = TinyOrdMap::from_checked(bmap! { + AssignmentType::with(42) => Occurrences::Once + }); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + assert!(matches!( + failures[0], + Failure::SchemaOpAssignmentTypeUnknown(_, _) + )); + + // SchemaMetaSemIdUnknown: schema meta type has unknown sem id + let mut consignment = base_consignment.clone(); + consignment.schema.meta_types = + TinyOrdMap::from_checked(bmap! {MetaType::with(42) => MetaDetails { + sem_id: SemId::from([42u8; 32]), + name: fname!("foo") + }}); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + assert!(matches!(failures[0], Failure::SchemaMetaSemIdUnknown(_, _))); + + // SchemaGlobalSemIdUnknown: schema global type has unknown sem id + let mut consignment = base_consignment.clone(); + let mut global_types = consignment.schema.global_types.release(); + global_types.insert( + GlobalStateType::with(42), + GlobalDetails { + global_state_schema: GlobalStateSchema { + sem_id: SemId::from([42u8; 32]), + max_items: u24::from_le_bytes([42u8; 3]), + }, + name: fname!("foo"), + }, + ); + consignment.schema.global_types = TinyOrdMap::from_checked(global_types); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + assert!(matches!( + failures[0], + Failure::SchemaGlobalSemIdUnknown(_, _) + )); + + // SchemaOwnedSemIdUnknown: schema owned type has unknown sem id + let mut consignment = base_consignment.clone(); + let mut owned_types = consignment.schema.owned_types.release(); + owned_types.insert( + AssignmentType::with(56), + AssignmentDetails { + owned_state_schema: OwnedStateSchema::Structured(SemId::from([42u8; 32])), + default_transition: TransitionType::with(42), + name: fname!("foo"), + }, + ); + consignment.schema.owned_types = TinyOrdMap::from_checked(owned_types); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + dbg!(&failures); + assert!(matches!( + failures[0], + Failure::SchemaOwnedSemIdUnknown(_, _) + )); +} + +#[cfg(not(feature = "altered"))] +#[test] +fn validate_consignment_commitments_fail() { + let scenario = Scenario::B; + let resolver = scenario.resolver(); + + let base_consignment = get_consignment_from_json(&format!("consignment_{scenario}")); + + // CyclicGraph: it's enough to make the same opid appear twice, changing InputMap and + // PubWitness to avoid automated removal of duplicates + let mut consignment = base_consignment.clone(); + let bundle = consignment.bundles.iter().last().unwrap(); + let mut new_bundle = bundle.clone(); + new_bundle.pub_witness = PubWitness::new( + Txid::from_str("a6e7e4775ea6e8b7155f6cfcc8d193df326c468dce99e9c4ee0a26511659feb3").unwrap(), + ); + new_bundle + .bundle + .input_map + .insert(Opout::strict_dumb(), OpId::strict_dumb()) + .unwrap(); + + consignment.bundles = LargeVec::from_checked(vec![bundle.clone(), new_bundle]); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert!(failures + .iter() + .any(|f| matches!(f, Failure::CyclicGraph(_)))); + + // DoubleSpend: add different transition that spends the same opouts + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let new_bundle = bundles.last_mut().unwrap(); + let mut transition = new_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + transition.nonce -= 1; + + new_bundle + .bundle + .known_transitions + .push(KnownTransition::new(transition.id(), transition)) + .unwrap(); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 2); + assert!(matches!(failures[0], Failure::ExtraKnownTransition(_))); + assert!(matches!(failures[1], Failure::DoubleSpend(_))); + + // OperationAbsent: remove a bundle that contains spent assignments + let mut consignment = base_consignment.clone(); + let spent_transitions = consignment + .bundles + .iter() + .flat_map(|b| b.bundle.known_transitions.as_unconfined()) + .flat_map(|kt| kt.transition.inputs.iter()) + .map(|ti| ti.op) + .collect::>(); + let bundle_id_to_remove = consignment + .bundles + .iter() + .map(|wb| wb.clone().bundle) + .find(|b| { + spent_transitions + .iter() + .any(|st| b.known_transitions_contain_opid(st)) + }) + .unwrap() + .bundle_id(); + consignment.bundles = LargeVec::from_checked( + consignment + .bundles + .into_iter() + .filter(|b| b.bundle.bundle_id() != bundle_id_to_remove) + .collect::>(), + ); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert!(failures + .iter() + .any(|f| matches!(f, Failure::OperationAbsent(_)))); + + // NoPrevState: add input with missing assignment type to a transition + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let new_bundle = bundles.last_mut().unwrap(); + let mut transition = new_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let fst_input = *transition.inputs.as_unconfined().first().unwrap(); + transition + .inputs + .push(Opout { + ty: AssignmentType::with(42), + ..fst_input + }) + .unwrap(); + new_bundle + .bundle + .known_transitions + .push(KnownTransition::new(transition.id(), transition)) + .unwrap(); + + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert!(failures.iter().any(|f| matches!( + f, + Failure::NoPrevState { + opid: _, + prev_id: _, + state_type: _ + } + ))); + + // NoPrevOut: add input with missing assignment number to a transition + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let new_bundle = bundles.last_mut().unwrap(); + let mut transition = new_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let fst_input = *transition.inputs.as_unconfined().first().unwrap(); + transition + .inputs + .push(Opout { + no: 42, + ..fst_input + }) + .unwrap(); + new_bundle + .bundle + .known_transitions + .push(KnownTransition::new(transition.id(), transition)) + .unwrap(); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert!(failures + .iter() + .any(|f| matches!(f, Failure::NoPrevOut(_, _)))); + + // ConfidentialSeal: one of the transitions includes blinded assignments + let mut consignment = base_consignment.clone(); + let spent_transitions = consignment + .bundles + .iter() + .flat_map(|b| b.bundle.known_transitions.as_unconfined()) + .flat_map(|kt| kt.transition.inputs.iter()) + .map(|ti| ti.op) + .collect::>(); + let mut bundles = consignment.bundles.release().clone(); + let new_bundle = bundles + .iter_mut() + .find(|wb| { + spent_transitions + .iter() + .any(|st| wb.bundle.known_transitions_contain_opid(st)) + }) + .unwrap(); + let mut transitions = new_bundle.clone().bundle.known_transitions; + let transition = transitions + .iter_mut() + .find(|kt| spent_transitions.contains(&kt.opid)) + .map(|kt| &mut kt.transition) + .unwrap(); + let assignments = transition + .assignments + .remove(&AssignmentType::ASSET) + .unwrap() + .unwrap() + .as_fungible() + .iter() + .map(|a| { + let (seal, state) = a.to_revealed().unwrap(); + rgb::Assign::ConfidentialSeal { + seal: seal.to_secret_seal(), + state, + } + }) + .collect::>(); + let assignments = + TypedAssigns::Fungible(AssignVec::with(NonEmptyVec::from_checked(assignments))); + transition + .assignments + .insert(AssignmentType::ASSET, assignments) + .unwrap(); + new_bundle.bundle.known_transitions = transitions; + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert!(failures + .iter() + .any(|f| matches!(f, Failure::ConfidentialSeal(_)))); + + // ExtraKnownTransition: replace known_transition referenced in input map + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let new_bundle = bundles.last_mut().unwrap(); + let mut transition = new_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + transition.nonce -= 1; + new_bundle.bundle.known_transitions = + NonEmptyVec::from_checked(vec![KnownTransition::new(transition.id(), transition)]); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert!(matches!(failures[0], Failure::ExtraKnownTransition(_))); +} + +#[cfg(not(feature = "altered"))] +#[test] +fn validate_consignment_logic_fail() { + let scenario = Scenario::B; + let resolver = scenario.resolver(); + + let base_consignment = get_consignment_from_json(&format!("consignment_{scenario}")); + + // SchemaMismatch: replace consignment.schema with a compatible schema with different id + let mut consignment = base_consignment.clone(); + let schema_id = consignment.schema_id(); + let mut alt_schema = NonInflatableAsset::schema(); + alt_schema.name = tn!("NonInflatableAsset2"); + let alt_schema_id = alt_schema.schema_id(); + consignment.schema = alt_schema; + let res = consignment.validate(&resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert_eq!( + failures[0], + Failure::SchemaMismatch { + expected: schema_id, + actual: alt_schema_id, + } + ); + + // SchemaUnknownTransitionType: replace transition with unsupported transition type + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + transition.transition_type = TransitionType::with(42); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert_eq!( + failures[0], + Failure::SchemaUnknownTransitionType(transition_id, TransitionType::with(42)) + ); + + // SchemaUnknownMetaType: replace transition with unsupported meta type + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + transition + .metadata + .add_value(MetaType::with(42), MetaValue::strict_dumb()) + .unwrap(); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert_eq!( + failures[0], + Failure::SchemaUnknownMetaType(transition_id, MetaType::with(42)) + ); + + // SchemaUnknownGlobalStateType: replace transition with unsupported global state type + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + transition + .globals + .add_state(GlobalStateType::with(42), RevealedData::strict_dumb()) + .unwrap(); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert_eq!( + failures[0], + Failure::SchemaUnknownGlobalStateType(transition_id, GlobalStateType::with(42)) + ); + + // SchemaUnknownAssignmentType: add unsupported assignment type to transition + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + transition + .assignments + .insert(AssignmentType::with(42), TypedAssigns::strict_dumb()) + .unwrap(); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert_eq!( + failures[0], + Failure::SchemaUnknownAssignmentType(transition_id, AssignmentType::with(42)) + ); + + // SchemaAssignmentOccurrences: add transition with no assignments + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + transition.assignments = SmallOrdMap::new().into(); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!( + failures[0], + Failure::SchemaAssignmentOccurrences( + transition_id, + AssignmentType::with(4000), + OccurrencesMismatch { + min: 1, + max: 65535, + found: 0 + } + ) + ); + + // StateTypeMismatch + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + let assignment_type = AssignmentType::with(4000); + transition + .assignments + .insert( + assignment_type, + TypedAssigns::Declarative( + NonEmptyVec::with(Assign::ConfidentialSeal { + seal: SecretSeal::strict_dumb(), + state: VoidState::strict_dumb(), + }) + .into(), + ), + ) + .unwrap(); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!( + failures[0], + Failure::StateTypeMismatch { + opid: transition_id, + state_type: assignment_type, + expected: StateType::Fungible, + found: StateType::Void + } + ); + + // ScriptFailure: e.g. one can't do simple inflation + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + let assignment_type = AssignmentType::with(4000); + let output_sum = transition + .assignments + .get(&assignment_type) + .unwrap() + .as_fungible() + .iter() + .map(|a| a.as_revealed_state().as_u64()) + .sum::(); + transition + .assignments + .insert( + assignment_type, + TypedAssigns::Fungible( + NonEmptyVec::with(Assign::ConfidentialSeal { + seal: SecretSeal::strict_dumb(), + state: RevealedValue::new(output_sum + 1), + }) + .into(), + ), + ) + .unwrap(); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert_eq!( + failures[0], + Failure::ScriptFailure(transition_id, Some(0), None) + ); + + // ContractMismatch: operations should commit to the correct contract + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + let old_contract_id = transition.contract_id; + transition.contract_id = ContractId::strict_dumb(); + let transition_id = transition.id(); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + // update again with the correct contract_id, otherwise we get SealsInvalid + update_witness_and_anchor(witness_bundle, Some(old_contract_id)); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + dbg!(&failures); + assert_eq!(failures.len(), 1); + assert_eq!( + failures[0], + Failure::ContractMismatch(transition_id, ContractId::strict_dumb()) + ); + + // Error: zero-amount allocations are not allowed + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let mut transition = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .clone(); + let old_opid = transition.id(); + if let TypedAssigns::Fungible(assign) = transition.assignments.get_mut(&OS_ASSET).unwrap() { + assign + .push(Assign::ConfidentialSeal { + seal: SecretSeal::strict_dumb(), + state: RevealedValue::new(Amount::ZERO), + }) + .unwrap(); + } else { + panic!("unexpected asssignment type") + }; + let opid = transition.id(); + assert_ne!(opid, old_opid); + replace_transition_in_bundle(witness_bundle, old_opid, transition); + let alt_resolver = + resolver.with_new_transaction(witness_bundle.pub_witness.tx().unwrap().clone()); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 1); + assert_eq!(failures[0], Failure::ScriptFailure(opid, Some(0), None)); +} + +#[cfg(not(feature = "altered"))] +#[test] +fn validate_consignment_unmatching_transition_id() { + let scenario = Scenario::B; + let resolver = scenario.resolver(); + + let base_consignment = get_consignment_from_json(&format!("consignment_{scenario}")); + + let mut consignment = base_consignment.clone(); + let mut bundles = consignment.bundles.release(); + let witness_bundle = bundles.last_mut().unwrap(); + let contract_id = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .transition + .contract_id; + + let mut other_wbundle = witness_bundle.clone(); + let KnownTransition { opid, transition } = witness_bundle + .bundle + .known_transitions + .last() + .unwrap() + .clone(); + // modified transition lies in witness_bundle, but is committed to in other_bundle + let mut transition = transition.clone(); + transition.nonce -= 1; + if let Some(existing) = witness_bundle + .bundle + .known_transitions + .iter_mut() + .find(|kt| kt.opid == opid) + { + existing.transition = transition.clone(); + } + + let dumb_transition = Transition::strict_dumb(); + let dumb_id = dumb_transition.id(); + // known_transitions can't be empty, so we need to add something + // we have no free allocations for a meaningful transition so it is a dumb one + // which causes OperationAbsent(OpId(0000000000000000000000000000000000000000000000000000000000000000)) + other_wbundle.bundle.known_transitions = + NonEmptyVec::with(KnownTransition::new(dumb_id, dumb_transition)); + other_wbundle + .bundle + .input_map + .insert(Opout::strict_dumb(), dumb_id) + .unwrap(); + update_witness_and_anchor(&mut other_wbundle, Some(contract_id)); + + let alt_resolver = + resolver.with_new_transaction(other_wbundle.pub_witness.tx().unwrap().clone()); + bundles.push(other_wbundle); + consignment.bundles = LargeVec::from_checked(bundles); + let res = consignment.validate(&alt_resolver, ChainNet::BitcoinRegtest, None); + let failures = res.unwrap_err().failures; + assert_eq!(failures.len(), 2); + assert_eq!( + failures[0], + Failure::TransitionIdMismatch(opid, transition.id()) + ); + assert_eq!(failures[1], Failure::OperationAbsent(OpId::strict_dumb())); }