Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP341 test vectors #1225

Merged
merged 1 commit into from
Nov 13, 2021
Merged

BIP341 test vectors #1225

merged 1 commit into from
Nov 13, 2021

Conversation

sipa
Copy link
Member

@sipa sipa commented Oct 30, 2021

This adds a set of wallet-focused BIP341 test vectors covering:

  • scriptPubKey computation (from internal key & script tree)
  • control block construction (for script path spending)
  • key path spending (sighash computation / deterministic signing)

It is primarily aimed at constructions that are useful right now, and excludes for example signing with annex for that reason. BIP342 semantics are not covered directly, as the scope of that is extremely wide, but control block computation is, plus most of sighash computation is shared with BIP341 key path spending.

These test vectors are generated through a scenario in bitcoin/bitcoin#23394, where an actual (regtest) chain is constructed and validated containing the relevant transactions, and also implemented there directly as a unit test.

@sipa
Copy link
Member Author

sipa commented Oct 30, 2021

Inspired by @giacomocaironi's #1191.

Copy link
Contributor

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really nice. Seems to be sufficiently exhaustive for common constructions.

Since this increases the size (in lines) of the BIP by ~70% with random data, it would make sense to put the test vectors could into a dedicated file.

I suppose the intention is to wait until the PR gets merged into Core?

@sipa
Copy link
Member Author

sipa commented Nov 1, 2021

@jonasnick Moved to a separate file. I considered trying to turn it into a CSV based format, but the scriptPubKey construction test cases (with variable script hierarchy) make that kind of difficult.

@junderw
Copy link
Contributor

junderw commented Nov 2, 2021

Eventually I'm going to convert this to a JSON file, so I can do that later today and post it here if you'd like.

@sipa
Copy link
Member Author

sipa commented Nov 2, 2021

@junderw JSON isn't a bad idea, as it can actually represent the hierarchical nature of script trees, as opposed to CSV. If we go that way, it may be better to adapt the code in bitcoin/bitcoin#23394 to output JSON directly.

@junderw
Copy link
Contributor

junderw commented Nov 2, 2021

I will post the JSON later today (it's about 2pm where I am right now) and then I'll maybe take a look at the generator code (though it might be faster for someone familiar with it to look at my schema and implement it)

@junderw
Copy link
Contributor

junderw commented Nov 2, 2021

@sipa What are the private keys for inputs 2 and 5? (P2PKH and P2WPKH respectively)

@junderw
Copy link
Contributor

junderw commented Nov 2, 2021

I have finished one of the scriptPubkey vectors. Looking for feedback.

I think it's pretty straightforward, the controlblock array and leaf hash array are in the order of leaf indices.

Leaf indices are in the order they first appear in the scriptTreeLeaves array.

The flat array scriptTreeLeaves represents the binary tree from root downward, anything that isn't a leaf is null. So the first null means root is not a leaf so first layer is [null], then second layer is [leaf0, null], then third layer is [null, null, leaf1, leaf2] with 2 nulls due to the left branch already terminating with leaf0. This gives [null, leaf0, null, null, null, leaf1, leaf2].

For each leaf script I added the PUSHDATA 32 OP (0x20) at the beginning and converted the CHECKSIG to 0xac

{
  "scriptPubkey": [
    {
      "given": {
        "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d",
        "scriptTreeLeaves": [
          null,
          {
            "script": "2071981521ad9fc9036687364118fb6ccd2035b96a423c59c5430e98310a11abe2ac",
            "version": 192
          },
          null,
          null,
          null,
          {
            "script": "20d5094d2dbe9b76e2c245a2b89b6006888952e2faa6a149ae318d69e520617748ac",
            "version": 192
          },
          {
            "script": "20c440b462ad48c7a77f94cd4532d8f2119dcebbd7c9764557e62726419b08ad4cac",
            "version": 192
          }
        ]
      },
      "intermediary": {
        "leafHashes": [
          "f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d",
          "737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711",
          "d7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7"
        ],
        "merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def",
        "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9",
        "tweakedPublicKey": "75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831"
      },
      "expected": {
        "scriptPubkey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831",
        "bip350Address": "bc1pw5tf7sqp4f50zka7629jrr036znzew70zxyvvej3zrpf8jg8hqcssyuewe",
        "scriptPathControlBlocks": [
          "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d3cd369a528b326bc9d2133cbd2ac21451acb31681a410434672c8e34fe757e91",
          "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312dd7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d",
          "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d"
        ]
      }
    }
  ]
}

@junderw
Copy link
Contributor

junderw commented Nov 2, 2021

I will work on the tx vector tomorrow after I get the private keys for the P2PKH and P2WPKH

@sipa
Copy link
Member Author

sipa commented Nov 2, 2021

@junderw What do you think about this?

{
    "scriptPubKey": [
        {
            "given": {
                "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d",
                "scriptTree": null
            },
            "intermediary": {
                "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70",
                "tweakedPubkey": "53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343"
            },
            "expected": {
                "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
                "bip350Address": "bc1p2wsldez5mud2yam29q22wgfh9439spgduvct83k3pm50fcxa5dps59h4z5"
            }
        },
        {
            "given": {
                "internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27",
                "scriptTree": {
                    "id": 0,
                    "script": "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac",
                    "leafVersion": 192
                }
            },
            "intermediary": {
                "leafHashes": [
                    "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21"
                ],
                "tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001",
                "tweakedPubkey": "147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3"
            },
            "expected": {
                "scriptPubKey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3",
                "bip350Address": "bc1pz37fc4cn9ah8anwm4xqqhvxygjf9rjf2resrw8h8w4tmvcs0863sa2e586",
                "scriptPathControlBlocks": [
                    "c1187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27"
                ]
            }
        },
        {
            "given": {
                "internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820",
                "scriptTree": {
                    "id": 0,
                    "script": "20b617298552a72ade070667e86ca63b8f5789a9fe8731ef91202a91c9f3459007ac",
                    "leafVersion": 192
                }
            },
            "intermediary": {
                "leafHashes": [
                    "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b"
                ],
                "tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30",
                "tweakedPubkey": "e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e"
            },
            "expected": {
                "scriptPubKey": "5120e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e",
                "bip350Address": "bc1punvppl2stp38f7kwv2u2spltjuvuaayuqsthe34hd2dyy5w4g58qqfuag5",
                "scriptPathControlBlocks": [
                    "c093478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820"
                ]
            }
        },
        {
            "given": {
                "internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592",
                "scriptTree": [
                    {
                        "id": 0,
                        "script": "20387671353e273264c495656e27e39ba899ea8fee3bb69fb2a680e22093447d48ac",
                        "leafVersion": 192
                    },
                    {
                        "id": 1,
                        "script": "06424950333431",
                        "leafVersion": 152
                    }
                ]
            },
            "intermediary": {
                "leafHashes": [
                    "8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7",
                    "7b2c2af8aa3e8b7bfe2f62a155f91427489c5c3b32be47e0b3fac755fc780e0e"
                ],
                "tweak": "d0713eea2b474b9d1fd177194a47bd3ab51194b17834b251d8d4ad8401fe4fe1",
                "tweakedPubkey": "0f63ca2c7639b9bb4be0465cc0aa3ee78a0761ba5f5f7d6ff8eab340f09da561"
            },
            "expected": {
                "scriptPubKey": "51200f63ca2c7639b9bb4be0465cc0aa3ee78a0761ba5f5f7d6ff8eab340f09da561",
                "bip350Address": "bc1ppa3u5trk8xumkjlqgewvp237u79qwcd6ta0h6mlca2e5puya54ssw9zq0y",
                "scriptPathControlBlocks": [
                    "c0ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf37865927b2c2af8aa3e8b7bfe2f62a155f91427489c5c3b32be47e0b3fac755fc780e0e",
                    "98ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf37865928ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7"
                ]
            }
        },
        {
            "given": {
                "internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8",
                "scriptTree": [
                    {
                        "id": 0,
                        "script": "2044b178d64c32c4a05cc4f4d1407268f764c940d20ce97abfd44db5c3592b72fdac",
                        "leafVersion": 192
                    },
                    {
                        "id": 1,
                        "script": "07546170726f6f74",
                        "leafVersion": 82
                    }
                ]
            },
            "intermediary": {
                "leafHashes": [
                    "64512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89",
                    "e44d5f8fa5892c8b6d4d09a08d36edd0b08636e30311302e2448ad8172fb3433"
                ],
                "tweak": "05dd8f8b751a5da0ea6d6a46ea37e24895a98ebab8a4b1574ace334348caac4d",
                "tweakedPubkey": "053690babeabbb7850c32eead0acf8df990ced79f7a31e358fabf2658b4bc587"
            },
            "expected": {
                "scriptPubKey": "5120053690babeabbb7850c32eead0acf8df990ced79f7a31e358fabf2658b4bc587",
                "bip350Address": "bc1pq5mfpw474wahs5xr9m4dpt8cm7vsemte7733udv040extz6tckrs29g04c",
                "scriptPathControlBlocks": [
                    "c1f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8e44d5f8fa5892c8b6d4d09a08d36edd0b08636e30311302e2448ad8172fb3433",
                    "53f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd864512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89"
                ]
            }
        },
        {
            "given": {
                "internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f",
                "scriptTree": [
                    {
                        "id": 0,
                        "script": "2072ea6adcf1d371dea8fba1035a09f3d24ed5a059799bae114084130ee5898e69ac",
                        "leafVersion": 192
                    },
                    [
                        {
                            "id": 1,
                            "script": "202352d137f2f3ab38d1eaa976758873377fa5ebb817372c71e2c542313d4abda8ac",
                            "leafVersion": 192
                        },
                        {
                            "id": 2,
                            "script": "207337c0dd4253cb86f2c43a2351aadd82cccb12a172cd120452b9bb8324f2186aac",
                            "leafVersion": 192
                        }
                    ]
                ]
            },
            "intermediary": {
                "leafHashes": [
                    "2645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817",
                    "ba982a91d4fc552163cb1c0da03676102d5b7a014304c01f0c77b2b8e888de1c",
                    "9e31407bffa15fefbf5090b149d53959ecdf3f62b1246780238c24501d5ceaf6"
                ],
                "tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4",
                "tweakedPubkey": "91b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605"
            },
            "expected": {
                "scriptPubKey": "512091b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605",
                "bip350Address": "bc1pjxmy65eywgafs5tsunw95ruycpqcqnev6ynxp7jaasylcgtcxczs6n332e",
                "scriptPathControlBlocks": [
                    "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6fffe578e9ea769027e4f5a3de40732f75a88a6353a09d767ddeb66accef85e553",
                    "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f9e31407bffa15fefbf5090b149d53959ecdf3f62b1246780238c24501d5ceaf62645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817",
                    "c0e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6fba982a91d4fc552163cb1c0da03676102d5b7a014304c01f0c77b2b8e888de1c2645a02e0aac1fe69d69755733a9b7621b694bb5b5cde2bbfc94066ed62b9817"
                ]
            }
        },
        {
            "given": {
                "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d",
                "scriptTree": [
                    {
                        "id": 0,
                        "script": "2071981521ad9fc9036687364118fb6ccd2035b96a423c59c5430e98310a11abe2ac",
                        "leafVersion": 192
                    },
                    [
                        {
                            "id": 1,
                            "script": "20d5094d2dbe9b76e2c245a2b89b6006888952e2faa6a149ae318d69e520617748ac",
                            "leafVersion": 192
                        },
                        {
                            "id": 2,
                            "script": "20c440b462ad48c7a77f94cd4532d8f2119dcebbd7c9764557e62726419b08ad4cac",
                            "leafVersion": 192
                        }
                    ]
                ]
            },
            "intermediary": {
                "leafHashes": [
                    "f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d",
                    "737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711",
                    "d7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7"
                ],
                "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9",
                "tweakedPubkey": "75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831"
            },
            "expected": {
                "scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831",
                "bip350Address": "bc1pw5tf7sqp4f50zka7629jrr036znzew70zxyvvej3zrpf8jg8hqcssyuewe",
                "scriptPathControlBlocks": [
                    "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d3cd369a528b326bc9d2133cbd2ac21451acb31681a410434672c8e34fe757e91",
                    "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312dd7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d",
                    "c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d"
                ]
            }
        }
    ],
    "keyPathSpending": [
        {
            "given": {
                "rawUnsignedTx": "02000000097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a418420000000000fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffff0c638ca38362001f5e128a01ae2b379288eb22cfaf903652b2ec1c88588f487a0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd05000000000000000000081efa267f1f0e46e054ecec01773de7c844721e010c2db5d5864a6a6b53e013a010000000000000000a690669c3c4a62507d93609810c6de3f99d1a6e311fe39dd23683d695c07bdee0000000000ffffffff727ab5f877438496f8613ca84002ff38e8292f7bd11f0a9b9b83ebd16779669e0100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0065cd1d",
                "utxosSpent": [
                    {
                        "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
                        "amountSats": 420000000
                    },
                    {
                        "scriptPubKey": "5120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3",
                        "amountSats": 462000000
                    },
                    {
                        "scriptPubKey": "76a914751e76e8199196d454941c45d1b3a323f1433bd688ac",
                        "amountSats": 294000000
                    },
                    {
                        "scriptPubKey": "5120e4d810fd50586274face62b8a807eb9719cef49c04177cc6b76a9a4251d5450e",
                        "amountSats": 504000000
                    },
                    {
                        "scriptPubKey": "512091b64d5324723a985170e4dc5a0f84c041804f2cd12660fa5dec09fc21783605",
                        "amountSats": 630000000
                    },
                    {
                        "scriptPubKey": "00147dd65592d0ab2fe0d0257d571abf032cd9db93dc",
                        "amountSats": 378000000
                    },
                    {
                        "scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831",
                        "amountSats": 672000000
                    },
                    {
                        "scriptPubKey": "51200f63ca2c7639b9bb4be0465cc0aa3ee78a0761ba5f5f7d6ff8eab340f09da561",
                        "amountSats": 546000000
                    },
                    {
                        "scriptPubKey": "5120053690babeabbb7850c32eead0acf8df990ced79f7a31e358fabf2658b4bc587",
                        "amountSats": 588000000
                    }
                ]
            },
            "intermediary": {
                "hashAmounts": "58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde6",
                "hashOutputs": "a2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc5",
                "hashPrevouts": "2bd4d5a417902673919b2c209d14f8efaa285ede022a88d6a45edf4bdd43db11",
                "hashScriptPubkeys": "26003c31f2f1786d22fcb3e1f690ddcdff53627a59f9219d5a2c77985a8930c0",
                "hashSequences": "18959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e"
            },
            "inputSpending": [
                {
                    "given": {
                        "txinIndex": 0,
                        "internalPrivkey": "6b973d88838f27366ed61c9ad6367663045cb456e28335c109e30717ae0c6baa",
                        "merkleRoot": null,
                        "hashType": 3
                    },
                    "intermediary": {
                        "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d",
                        "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70",
                        "tweakedPrivkey": "2405b971772ad26915c8dcdf10f238753a9b837e5f8e6a86fd7c0cce5b7296d9",
                        "sigMsg": "0003020000000065cd1d2bd4d5a417902673919b2c209d14f8efaa285ede022a88d6a45edf4bdd43db1158a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde626003c31f2f1786d22fcb3e1f690ddcdff53627a59f9219d5a2c77985a8930c018959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0000000000d0418f0e9a36245b9a50ec87f8bf5be5bcae434337b87139c3a5b1f56e33cba0",
                        "precomputedUsed": [
                            "hashAmounts",
                            "hashPrevouts",
                            "hashScriptPubkeys",
                            "hashSequences"
                        ],
                        "sigHash": "7e584883b084ace0469c6962a9a7d2a9060e1f3c218ab40d32c77651482122bc"
                    },
                    "expected": {
                        "signature": "aab8fce3c4d7f359577a338676c9580d6946d7d8f899a48a4e1dcc63611e8f654eab7192d43e6d6b9c7c95322338edbc5af21e88b43df36a989ba559d473f32a03"
                    }
                },
                {
                    "given": {
                        "txinIndex": 1,
                        "internalPrivkey": "1e4da49f6aaf4e5cd175fe08a32bb5cb4863d963921255f33d3bc31e1343907f",
                        "merkleRoot": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21",
                        "hashType": 131
                    },
                    "intermediary": {
                        "internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27",
                        "tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001",
                        "tweakedPrivkey": "ea260c3b10e60f6de018455cd0278f2f5b7e454be1999572789e6a9565d26080",
                        "sigMsg": "0083020000000065cd1d00d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd9900000000808f891b00000000225120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3ffffffffffcef8fb4ca7efc5433f591ecfc57391811ce1e186a3793024def5c884cba51d",
                        "precomputedUsed": [],
                        "sigHash": "325a644af47e8a5a2591cda0ab0723978537318f10e6a63d4eed783b96a71a4d"
                    },
                    "expected": {
                        "signature": "052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83"
                    }
                },
                {
                    "given": {
                        "txinIndex": 3,
                        "internalPrivkey": "d3c7af07da2d54f7a7735d3d0fc4f0a73164db638b2f2f7c43f711f6d4aa7e64",
                        "merkleRoot": "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b",
                        "hashType": 1
                    },
                    "intermediary": {
                        "internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820",
                        "tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30",
                        "tweakedPrivkey": "97323385e57015b75b0339a549c56a948eb961555973f0951f555ae6039ef00d",
                        "sigMsg": "0001020000000065cd1d2bd4d5a417902673919b2c209d14f8efaa285ede022a88d6a45edf4bdd43db1158a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde626003c31f2f1786d22fcb3e1f690ddcdff53627a59f9219d5a2c77985a8930c018959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50003000000",
                        "precomputedUsed": [
                            "hashAmounts",
                            "hashOutputs",
                            "hashPrevouts",
                            "hashScriptPubkeys",
                            "hashSequences"
                        ],
                        "sigHash": "6ffd256e108685b41831385f57eebf2fca041bc6b5e607ea11b3e03d4cf9d9ba"
                    },
                    "expected": {
                        "signature": "f78cf3fe8410326ba95b7119cac657b2d86a461dc0767d7b68cb516f3d8bac64ed027fb710b5962d01c42dadaf4dec5731371c6c7850854cc68054eb8f4de80b01"
                    }
                },
                {
                    "given": {
                        "txinIndex": 4,
                        "internalPrivkey": "f36bb07a11e469ce941d16b63b11b9b9120a84d9d87cff2c84a8d4affb438f4e",
                        "merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2",
                        "hashType": 0
                    },
                    "intermediary": {
                        "internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f",
                        "tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4",
                        "tweakedPrivkey": "a8e7aa924f0d58854185a490e6c41f6efb7b675c0f3331b7f14b549400b4d501",
                        "sigMsg": "0000020000000065cd1d2bd4d5a417902673919b2c209d14f8efaa285ede022a88d6a45edf4bdd43db1158a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde626003c31f2f1786d22fcb3e1f690ddcdff53627a59f9219d5a2c77985a8930c018959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50004000000",
                        "precomputedUsed": [
                            "hashAmounts",
                            "hashOutputs",
                            "hashPrevouts",
                            "hashScriptPubkeys",
                            "hashSequences"
                        ],
                        "sigHash": "9f90136737540ccc18707e1fd398ad222a1a7e4dd65cbfd22dbe4660191efa58"
                    },
                    "expected": {
                        "signature": "69599256a182e89be95c098b03200b958220ee400c42779cd05cdbf9fa2d5c8060a48c1463c9fadf6aea0395b70ebf937fbae0dd2d83185c1d9f675dac8d06f5"
                    }
                },
                {
                    "given": {
                        "txinIndex": 6,
                        "internalPrivkey": "415cfe9c15d9cea27d8104d5517c06e9de48e2f986b695e4f5ffebf230e725d8",
                        "merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def",
                        "hashType": 2
                    },
                    "intermediary": {
                        "internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d",
                        "tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9",
                        "tweakedPrivkey": "241c14f2639d0d7139282aa6abde28dd8a067baa9d633e4e7230287ec2d02901",
                        "sigMsg": "0002020000000065cd1d2bd4d5a417902673919b2c209d14f8efaa285ede022a88d6a45edf4bdd43db1158a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde626003c31f2f1786d22fcb3e1f690ddcdff53627a59f9219d5a2c77985a8930c018959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0006000000",
                        "precomputedUsed": [
                            "hashAmounts",
                            "hashPrevouts",
                            "hashScriptPubkeys",
                            "hashSequences"
                        ],
                        "sigHash": "835c9ab6084ed9a8ae9b7cda21e0aa797aca3b76a54bd1e3c7db093f6c57e23f"
                    },
                    "expected": {
                        "signature": "882a50af428ea47ee84462fcb481033db9c8b1ea6f2b77c9a8e4d8135a1c0771ee8dbcd24ea671576ab441bdb2ab3f85f20675ca4c59889bab719b062abfd06402"
                    }
                },
                {
                    "given": {
                        "txinIndex": 7,
                        "internalPrivkey": "c7b0e81f0a9a0b0499e112279d718cca98e79a12e2f137c72ae5b213aad0d103",
                        "merkleRoot": "f3004d6c183e038105d436db1424f321613366cbb7b05939bf05d763a9ebb962",
                        "hashType": 130
                    },
                    "intermediary": {
                        "internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592",
                        "tweak": "d0713eea2b474b9d1fd177194a47bd3ab51194b17834b251d8d4ad8401fe4fe1",
                        "tweakedPrivkey": "9822270935e156a1b9b28940e7b94a06934a51ddabdd49dd43e8010adc98dfa3",
                        "sigMsg": "0082020000000065cd1d00a690669c3c4a62507d93609810c6de3f99d1a6e311fe39dd23683d695c07bdee00000000804c8b20000000002251200f63ca2c7639b9bb4be0465cc0aa3ee78a0761ba5f5f7d6ff8eab340f09da561ffffffff",
                        "precomputedUsed": [],
                        "sigHash": "df1cca638283c667084b8ffe6bf6e116cc5a53cf7ae1202c5fee45a9085f1ba5"
                    },
                    "expected": {
                        "signature": "1ec324f9ccc982286a10017daa22ead5087d9f2eff58dd6173d7d608eb959be6be2f3df0a25a7890c99a9259c9eab33d71a6c163cabb442aa3a5e5d61361142082"
                    }
                },
                {
                    "given": {
                        "txinIndex": 8,
                        "internalPrivkey": "77863416be0d0665e517e1c375fd6f75839544eca553675ef7fdf4949518ebaa",
                        "merkleRoot": "d9c2c32808b41c0301d876d49c0af72e1d98e84b99ca9b4bb67fea1a7424b755",
                        "hashType": 129
                    },
                    "intermediary": {
                        "internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8",
                        "tweak": "05dd8f8b751a5da0ea6d6a46ea37e24895a98ebab8a4b1574ace334348caac4d",
                        "tweakedPrivkey": "8e575b74b70d573b05558883743a72d1ccc326b4c299ea3412a29d3b83e801e4",
                        "sigMsg": "0081020000000065cd1da2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc500727ab5f877438496f8613ca84002ff38e8292f7bd11f0a9b9b83ebd16779669e01000000002b0c2300000000225120053690babeabbb7850c32eead0acf8df990ced79f7a31e358fabf2658b4bc587ffffffff",
                        "precomputedUsed": [
                            "hashOutputs"
                        ],
                        "sigHash": "30319859ca79ea1b7a9782e9daebc46e4ca4ca2bc04c9c53b2ec87fa83a526bd"
                    },
                    "expected": {
                        "signature": "7e6c212ebe04e8241bee0151b0d3230aa22dec9dbdd8197ebd3ff616b9e4b47dccee08a32a52a77d60587a77e7d7b5d1d113235d38921740ffdbe795459637ff81"
                    }
                }
            ],
            "auxiliary": {
                "fulledSignedTx": "020000000001097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a41842000000006b483045022100f0e6c698ad4607d87a86d168a7385e7c986604fe94a76fdb6ffee5840bc9f47502205d76a584eb97ef99b31cfa3206616369b7ea10c07e5c4a9a82f20681c921a21001210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffff0c638ca38362001f5e128a01ae2b379288eb22cfaf903652b2ec1c88588f487a0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd05000000000000000000081efa267f1f0e46e054ecec01773de7c844721e010c2db5d5864a6a6b53e013a010000000000000000a690669c3c4a62507d93609810c6de3f99d1a6e311fe39dd23683d695c07bdee0000000000ffffffff727ab5f877438496f8613ca84002ff38e8292f7bd11f0a9b9b83ebd16779669e0100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0141aab8fce3c4d7f359577a338676c9580d6946d7d8f899a48a4e1dcc63611e8f654eab7192d43e6d6b9c7c95322338edbc5af21e88b43df36a989ba559d473f32a030141052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83000141f78cf3fe8410326ba95b7119cac657b2d86a461dc0767d7b68cb516f3d8bac64ed027fb710b5962d01c42dadaf4dec5731371c6c7850854cc68054eb8f4de80b01014069599256a182e89be95c098b03200b958220ee400c42779cd05cdbf9fa2d5c8060a48c1463c9fadf6aea0395b70ebf937fbae0dd2d83185c1d9f675dac8d06f50247304402201a084cec54089e142f480fc7479a6c1d82ef7a920045a3c39e327a3dcd633a8b022072d5ab18e2e04c04a3e9d53d4e2b0625265671553f203542fb5a3bfc1d240fc5012102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f90141882a50af428ea47ee84462fcb481033db9c8b1ea6f2b77c9a8e4d8135a1c0771ee8dbcd24ea671576ab441bdb2ab3f85f20675ca4c59889bab719b062abfd0640201411ec324f9ccc982286a10017daa22ead5087d9f2eff58dd6173d7d608eb959be6be2f3df0a25a7890c99a9259c9eab33d71a6c163cabb442aa3a5e5d6136114208201417e6c212ebe04e8241bee0151b0d3230aa22dec9dbdd8197ebd3ff616b9e4b47dccee08a32a52a77d60587a77e7d7b5d1d113235d38921740ffdbe795459637ff810065cd1d"
            }
        }
    ]
}

@sipa
Copy link
Member Author

sipa commented Nov 2, 2021

Instead of using a fixed index->treeposition mapping, I represent the script tree as a hierarchical structure, with Objects as leaves, and 2-element Arrays to represent internal nodes. It's more flexible in case we'd want to extend it with more complex trees etc.

@sipa
Copy link
Member Author

sipa commented Nov 2, 2021

@junderw The private keys for the non-tr inputs are 0x0000...01 and 0x0000...03 respectively (0x0000...02 is used in one of the outputs).

@junderw
Copy link
Contributor

junderw commented Nov 3, 2021

Perhaps a single leaf should be an array with one object. And every tree with multiple layers should have an extra array encapsulating it.

Tests could definitely implement logic to check if the tree is null OR object OR array... but I would rather just have it be null OR array.

Or maybe even have an empty array replace null and make the tree always be an array.

Thoughts?


Also, eventually it would be nice to have a few more keyPathSpending vectors that ONLY have a certain type of input. ie. so if a wallet only cares about non-script-path spending. (ie. a wallet that only wants to offer single sig p2tr and no custom scripts are needed) When the vector includes all types in the tx you need to be able to sign all types to check if the final tx matches.

That said, this would not be a blocker for this PR and could be done later.


Thanks!

@sipa
Copy link
Member Author

sipa commented Nov 3, 2021

Tests could definitely implement logic to check if the tree is null OR object OR array... but I would rather just have it be null OR array.

I don't really understand this; an implementation needs 3 cases anyway: (a) tweaking with no tree (b) computing a leaf hash (c) computing an inner node from a left and right subtree. In my current approach, those correspond exactly to (a) null (b) an object (c) an array with 2 elements. Using a 1-element array for single-script trees means introducing a special case where a leaf at the root is [{...}], while leaves elsewhere are just {...}.

No strong opinion on [] vs. none for lack of scripts.

When the vector includes all types in the tx you need to be able to sign all types to check if the final tx matches.

I realize that, but it's why the test cases are individual inputs, not the final transaction. That's just provided as a demonstration of how the witnesses are formed etc., so I don't think it adds much. If you can construct signatures correctly, you're good.

I'm not opposed to adding extra cases to cover more things, if you have specific ideas.

@junderw
Copy link
Contributor

junderw commented Nov 3, 2021

I don't really understand this; an implementation needs 3 cases anyway: (a) tweaking with no tree (b) computing a leaf hash (c) computing an inner node from a left and right subtree. In my current approach, those correspond exactly to (a) null (b) an object (c) an array with 2 elements. Using a 1-element array for single-script trees means introducing a special case where a leaf at the root is [{...}], while leaves elsewhere are just {...}.

No strong opinion on [] vs. none for lack of scripts.

Good points. On second thought, it's not that big of a deal. As-is is fine.

I realize that, but it's why the test cases are individual inputs, not the final transaction. That's just provided as a demonstration of how the witnesses are formed etc., so I don't think it adds much. If you can construct signatures correctly, you're good.

I'm not opposed to adding extra cases to cover more things, if you have specific ideas.

I understand and appreciate the test case being split into inputs, but I think that having the final transaction would also be a good test for the serialization of a signed completed transaction.

The one vector given is great for apps which implement all forms of taproot spending, but for any wallet that only implements a subset, they will only be able to test if they can generate valid signatures and not test if they can form a valid serialized transaction.

Perhaps serialization tests should be separate. But since the test generation framework already exists it might be easier to just create a few more keyspend vectors with one input each where the only input is one type (ie. p2tr keyspend, p2tr single leaf, p2tr multi-layer leaf structure, etc. similar to the inputs you included, except in separate transactions)

@sipa
Copy link
Member Author

sipa commented Nov 3, 2021

The one vector given is great for apps which implement all forms of taproot spending, but for any wallet that only implements a subset, they will only be able to test if they can generate valid signatures and not test if they can form a valid serialized transaction.

I can see that argument, but really what you want is "can they construct a valid witness". If they can do that for every input, you by definition have a valid transaction. And it turns out that constructing a P2TR keypath witness, once you have valid signatures, is rather trivial.

(again, not objecting to adding more simpler cases later; just pointing out that it doesn't really add much)

@junderw
Copy link
Contributor

junderw commented Nov 3, 2021

Maybe it might be more straightforward for the expected to be an array representation of the witness stack for that input including the signature.

@luke-jr
Copy link
Member

luke-jr commented Nov 4, 2021

It's not clear to me: Is this ready to merge?

@sipa
Copy link
Member Author

sipa commented Nov 5, 2021

@junderw Good idea.

I've updated this to add the test vectors in JSON format, plus a short explanation in the BIP itself linking to it.

bip-0341.mediawiki Outdated Show resolved Hide resolved
Copy link
Contributor

@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 965025b. Looking forward to implementing these in rust-bitcoin after this is merged.

Copy link
Contributor

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's not impossible that in the future the test vectors will be updated in some way, how about adding a version field to the json object that allows users to see at a glance if they're using the latest one? It could just be an integer.

@sipa
Copy link
Member Author

sipa commented Nov 7, 2021

@jonasnick Good idea; done.

Copy link
Contributor

@jonasnick jonasnick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 965025b

@sipa
Copy link
Member Author

sipa commented Nov 7, 2021

@luke-jr @kallewoof Ready for merge, I think.

@kallewoof kallewoof merged commit 93adfba into bitcoin:master Nov 13, 2021
laanwj added a commit to bitcoin-core/gui that referenced this pull request Nov 15, 2021
…tests)

f1c33ee tests: implement BIP341 test vectors (Pieter Wuille)
ac3037d tests: BIP341 test vector generation (Pieter Wuille)
ca83ffc tests: add deterministic signing mode to ECDSA (Pieter Wuille)
c98c53f tests: abstract out precomputed BIP341 signature hash elements (Pieter Wuille)
a5bde01 tests: give feature_taproot access to sighash preimages (Pieter Wuille)
5140825 tests: add more fields to TaprootInfo (Pieter Wuille)
2478c67 Make signing follow BIP340 exactly w.r.t. aux randomness (Pieter Wuille)

Pull request description:

  This PR adds code to `test/functional/feature_taproot.py` which runs through a (deterministic) scenario covering several aspects of the wallet side of BIP341 (scriptPubKey computation from keys/scripts, control block computation, key path spending), with the ability to output test vectors in mediawiki format based on this scenario. The generated tests are then also included directly in `src/test/script_tests.cpp` and `src/test/script_standard_tests.cpp`.

  I intend to add these test vectors to BIP341 itself: bitcoin/bips#1225

ACKs for top commit:
  laanwj:
    Code review ACK f1c33ee

Tree-SHA512: fcf7109539cb214d3190516b205cd32d2b1b452f14aa66f4107acfaa8bfc7d368f626857f1935665a4342eabc0b9ee8aba608a7c0a2494bec0b498e723439c9d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants