mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 01:40:55 +01:00
TapscriptTree
, TapBranch
, TapLeaf
(#5520)
* Add taproot wallet test vectors * Get parsing logic working * Get first test case passing * Add TapLeaf * Get test cases working with two TapLeaf * Add TapscriptTree as the top level type for a recursive data structure for TapscriptPath's * Remove control block parsing for now until we actually test control blocks * scalafmt
This commit is contained in:
parent
376872eb3e
commit
2536fd3138
452
core-test/.jvm/src/test/resources/wallet-test-vectors.json
Normal file
452
core-test/.jvm/src/test/resources/wallet-test-vectors.json
Normal file
@ -0,0 +1,452 @@
|
||||
{
|
||||
"version": 1,
|
||||
"scriptPubKey": [
|
||||
{
|
||||
"given": {
|
||||
"internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d",
|
||||
"scriptTree": null
|
||||
},
|
||||
"intermediary": {
|
||||
"merkleRoot": null,
|
||||
"tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70",
|
||||
"tweakedPubkey": "53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343"
|
||||
},
|
||||
"expected": {
|
||||
"scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
|
||||
"bip350Address": "bc1p2wsldez5mud2yam29q22wgfh9439spgduvct83k3pm50fcxa5dps59h4z5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27",
|
||||
"scriptTree": {
|
||||
"id": 0,
|
||||
"script": "20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac",
|
||||
"leafVersion": 192
|
||||
}
|
||||
},
|
||||
"intermediary": {
|
||||
"leafHashes": [
|
||||
"5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21"
|
||||
],
|
||||
"merkleRoot": "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"
|
||||
],
|
||||
"merkleRoot": "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": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
"intermediary": {
|
||||
"leafHashes": [
|
||||
"8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7",
|
||||
"f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a"
|
||||
],
|
||||
"merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef",
|
||||
"tweak": "9e0517edc8259bb3359255400b23ca9507f2a91cd1e4250ba068b4eafceba4a9",
|
||||
"tweakedPubkey": "712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5"
|
||||
},
|
||||
"expected": {
|
||||
"scriptPubKey": "5120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5",
|
||||
"bip350Address": "bc1pwyjywgrd0ffr3tx8laflh6228dj98xkjj8rum0zfpd6h0e930h6saqxrrm",
|
||||
"scriptPathControlBlocks": [
|
||||
"c0ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a",
|
||||
"faee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf37865928ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8",
|
||||
"scriptTree": [
|
||||
{
|
||||
"id": 0,
|
||||
"script": "2044b178d64c32c4a05cc4f4d1407268f764c940d20ce97abfd44db5c3592b72fdac",
|
||||
"leafVersion": 192
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"script": "07546170726f6f74",
|
||||
"leafVersion": 192
|
||||
}
|
||||
]
|
||||
},
|
||||
"intermediary": {
|
||||
"leafHashes": [
|
||||
"64512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89",
|
||||
"2cb2b90daa543b544161530c925f285b06196940d6085ca9474d41dc3822c5cb"
|
||||
],
|
||||
"merkleRoot": "ab179431c28d3b68fb798957faf5497d69c883c6fb1e1cd9f81483d87bac90cc",
|
||||
"tweak": "639f0281b7ac49e742cd25b7f188657626da1ad169209078e2761cefd91fd65e",
|
||||
"tweakedPubkey": "77e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220"
|
||||
},
|
||||
"expected": {
|
||||
"scriptPubKey": "512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220",
|
||||
"bip350Address": "bc1pwl3s54fzmk0cjnpl3w9af39je7pv5ldg504x5guk2hpecpg2kgsqaqstjq",
|
||||
"scriptPathControlBlocks": [
|
||||
"c1f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd82cb2b90daa543b544161530c925f285b06196940d6085ca9474d41dc3822c5cb",
|
||||
"c1f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd864512fecdb5afa04f98839b50e6f0cb7b1e539bf6f205f67934083cdcc3c8d89"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"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"
|
||||
],
|
||||
"merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2",
|
||||
"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"
|
||||
],
|
||||
"merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def",
|
||||
"tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9",
|
||||
"tweakedPubkey": "75169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831"
|
||||
},
|
||||
"expected": {
|
||||
"scriptPubKey": "512075169f4001aa68f15bbed28b218df1d0a62cbbcf1188c6665110c293c907b831",
|
||||
"bip350Address": "bc1pw5tf7sqp4f50zka7629jrr036znzew70zxyvvej3zrpf8jg8hqcssyuewe",
|
||||
"scriptPathControlBlocks": [
|
||||
"c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d3cd369a528b326bc9d2133cbd2ac21451acb31681a410434672c8e34fe757e91",
|
||||
"c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312dd7485025fceb78b9ed667db36ed8b8dc7b1f0b307ac167fa516fe4352b9f4ef7f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d",
|
||||
"c155adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d737ed1fe30bc42b8022d717b44f0d93516617af64a64753b7a06bf16b26cd711f154e8e8e17c31d3462d7132589ed29353c6fafdb884c5a6e04ea938834f0d9d"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"keyPathSpending": [
|
||||
{
|
||||
"given": {
|
||||
"rawUnsignedTx": "02000000097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a418420000000000fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0065cd1d",
|
||||
"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": "5120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5",
|
||||
"amountSats": 546000000
|
||||
},
|
||||
{
|
||||
"scriptPubKey": "512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220",
|
||||
"amountSats": 588000000
|
||||
}
|
||||
]
|
||||
},
|
||||
"intermediary": {
|
||||
"hashAmounts": "58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde6",
|
||||
"hashOutputs": "a2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc5",
|
||||
"hashPrevouts": "e3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f",
|
||||
"hashScriptPubkeys": "23ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e21",
|
||||
"hashSequences": "18959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e"
|
||||
},
|
||||
"inputSpending": [
|
||||
{
|
||||
"given": {
|
||||
"txinIndex": 0,
|
||||
"internalPrivkey": "6b973d88838f27366ed61c9ad6367663045cb456e28335c109e30717ae0c6baa",
|
||||
"merkleRoot": null,
|
||||
"hashType": 3
|
||||
},
|
||||
"intermediary": {
|
||||
"internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d",
|
||||
"tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70",
|
||||
"tweakedPrivkey": "2405b971772ad26915c8dcdf10f238753a9b837e5f8e6a86fd7c0cce5b7296d9",
|
||||
"sigMsg": "0003020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0000000000d0418f0e9a36245b9a50ec87f8bf5be5bcae434337b87139c3a5b1f56e33cba0",
|
||||
"precomputedUsed": [
|
||||
"hashAmounts",
|
||||
"hashPrevouts",
|
||||
"hashScriptPubkeys",
|
||||
"hashSequences"
|
||||
],
|
||||
"sigHash": "2514a6272f85cfa0f45eb907fcb0d121b808ed37c6ea160a5a9046ed5526d555"
|
||||
},
|
||||
"expected": {
|
||||
"witness": [
|
||||
"ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c03"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"txinIndex": 1,
|
||||
"internalPrivkey": "1e4da49f6aaf4e5cd175fe08a32bb5cb4863d963921255f33d3bc31e1343907f",
|
||||
"merkleRoot": "5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21",
|
||||
"hashType": 131
|
||||
},
|
||||
"intermediary": {
|
||||
"internalPubkey": "187791b6f712a8ea41c8ecdd0ee77fab3e85263b37e1ec18a3651926b3a6cf27",
|
||||
"tweak": "cbd8679ba636c1110ea247542cfbd964131a6be84f873f7f3b62a777528ed001",
|
||||
"tweakedPrivkey": "ea260c3b10e60f6de018455cd0278f2f5b7e454be1999572789e6a9565d26080",
|
||||
"sigMsg": "0083020000000065cd1d00d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd9900000000808f891b00000000225120147c9c57132f6e7ecddba9800bb0c4449251c92a1e60371ee77557b6620f3ea3ffffffffffcef8fb4ca7efc5433f591ecfc57391811ce1e186a3793024def5c884cba51d",
|
||||
"precomputedUsed": [],
|
||||
"sigHash": "325a644af47e8a5a2591cda0ab0723978537318f10e6a63d4eed783b96a71a4d"
|
||||
},
|
||||
"expected": {
|
||||
"witness": [
|
||||
"052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"txinIndex": 3,
|
||||
"internalPrivkey": "d3c7af07da2d54f7a7735d3d0fc4f0a73164db638b2f2f7c43f711f6d4aa7e64",
|
||||
"merkleRoot": "c525714a7f49c28aedbbba78c005931a81c234b2f6c99a73e4d06082adc8bf2b",
|
||||
"hashType": 1
|
||||
},
|
||||
"intermediary": {
|
||||
"internalPubkey": "93478e9488f956df2396be2ce6c5cced75f900dfa18e7dabd2428aae78451820",
|
||||
"tweak": "6af9e28dbf9d6aaf027696e2598a5b3d056f5fd2355a7fd5a37a0e5008132d30",
|
||||
"tweakedPrivkey": "97323385e57015b75b0339a549c56a948eb961555973f0951f555ae6039ef00d",
|
||||
"sigMsg": "0001020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50003000000",
|
||||
"precomputedUsed": [
|
||||
"hashAmounts",
|
||||
"hashOutputs",
|
||||
"hashPrevouts",
|
||||
"hashScriptPubkeys",
|
||||
"hashSequences"
|
||||
],
|
||||
"sigHash": "bf013ea93474aa67815b1b6cc441d23b64fa310911d991e713cd34c7f5d46669"
|
||||
},
|
||||
"expected": {
|
||||
"witness": [
|
||||
"ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a01"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"txinIndex": 4,
|
||||
"internalPrivkey": "f36bb07a11e469ce941d16b63b11b9b9120a84d9d87cff2c84a8d4affb438f4e",
|
||||
"merkleRoot": "ccbd66c6f7e8fdab47b3a486f59d28262be857f30d4773f2d5ea47f7761ce0e2",
|
||||
"hashType": 0
|
||||
},
|
||||
"intermediary": {
|
||||
"internalPubkey": "e0dfe2300b0dd746a3f8674dfd4525623639042569d829c7f0eed9602d263e6f",
|
||||
"tweak": "b57bfa183d28eeb6ad688ddaabb265b4a41fbf68e5fed2c72c74de70d5a786f4",
|
||||
"tweakedPrivkey": "a8e7aa924f0d58854185a490e6c41f6efb7b675c0f3331b7f14b549400b4d501",
|
||||
"sigMsg": "0000020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957ea2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc50004000000",
|
||||
"precomputedUsed": [
|
||||
"hashAmounts",
|
||||
"hashOutputs",
|
||||
"hashPrevouts",
|
||||
"hashScriptPubkeys",
|
||||
"hashSequences"
|
||||
],
|
||||
"sigHash": "4f900a0bae3f1446fd48490c2958b5a023228f01661cda3496a11da502a7f7ef"
|
||||
},
|
||||
"expected": {
|
||||
"witness": [
|
||||
"b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"txinIndex": 6,
|
||||
"internalPrivkey": "415cfe9c15d9cea27d8104d5517c06e9de48e2f986b695e4f5ffebf230e725d8",
|
||||
"merkleRoot": "2f6b2c5397b6d68ca18e09a3f05161668ffe93a988582d55c6f07bd5b3329def",
|
||||
"hashType": 2
|
||||
},
|
||||
"intermediary": {
|
||||
"internalPubkey": "55adf4e8967fbd2e29f20ac896e60c3b0f1d5b0efa9d34941b5958c7b0a0312d",
|
||||
"tweak": "6579138e7976dc13b6a92f7bfd5a2fc7684f5ea42419d43368301470f3b74ed9",
|
||||
"tweakedPrivkey": "241c14f2639d0d7139282aa6abde28dd8a067baa9d633e4e7230287ec2d02901",
|
||||
"sigMsg": "0002020000000065cd1de3b33bb4ef3a52ad1fffb555c0d82828eb22737036eaeb02a235d82b909c4c3f58a6964a4f5f8f0b642ded0a8a553be7622a719da71d1f5befcefcdee8e0fde623ad0f61ad2bca5ba6a7693f50fce988e17c3780bf2b1e720cfbb38fbdd52e2118959c7221ab5ce9e26c3cd67b22c24f8baa54bac281d8e6b05e400e6c3a957e0006000000",
|
||||
"precomputedUsed": [
|
||||
"hashAmounts",
|
||||
"hashPrevouts",
|
||||
"hashScriptPubkeys",
|
||||
"hashSequences"
|
||||
],
|
||||
"sigHash": "15f25c298eb5cdc7eb1d638dd2d45c97c4c59dcaec6679cfc16ad84f30876b85"
|
||||
},
|
||||
"expected": {
|
||||
"witness": [
|
||||
"a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee002"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"txinIndex": 7,
|
||||
"internalPrivkey": "c7b0e81f0a9a0b0499e112279d718cca98e79a12e2f137c72ae5b213aad0d103",
|
||||
"merkleRoot": "6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef",
|
||||
"hashType": 130
|
||||
},
|
||||
"intermediary": {
|
||||
"internalPubkey": "ee4fe085983462a184015d1f782d6a5f8b9c2b60130aff050ce221ecf3786592",
|
||||
"tweak": "9e0517edc8259bb3359255400b23ca9507f2a91cd1e4250ba068b4eafceba4a9",
|
||||
"tweakedPrivkey": "65b6000cd2bfa6b7cf736767a8955760e62b6649058cbc970b7c0871d786346b",
|
||||
"sigMsg": "0082020000000065cd1d00e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf00000000804c8b2000000000225120712447206d7a5238acc7ff53fbe94a3b64539ad291c7cdbc490b7577e4b17df5ffffffff",
|
||||
"precomputedUsed": [],
|
||||
"sigHash": "cd292de50313804dabe4685e83f923d2969577191a3e1d2882220dca88cbeb10"
|
||||
},
|
||||
"expected": {
|
||||
"witness": [
|
||||
"ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c482"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"given": {
|
||||
"txinIndex": 8,
|
||||
"internalPrivkey": "77863416be0d0665e517e1c375fd6f75839544eca553675ef7fdf4949518ebaa",
|
||||
"merkleRoot": "ab179431c28d3b68fb798957faf5497d69c883c6fb1e1cd9f81483d87bac90cc",
|
||||
"hashType": 129
|
||||
},
|
||||
"intermediary": {
|
||||
"internalPubkey": "f9f400803e683727b14f463836e1e78e1c64417638aa066919291a225f0e8dd8",
|
||||
"tweak": "639f0281b7ac49e742cd25b7f188657626da1ad169209078e2761cefd91fd65e",
|
||||
"tweakedPrivkey": "ec18ce6af99f43815db543f47b8af5ff5df3b2cb7315c955aa4a86e8143d2bf5",
|
||||
"sigMsg": "0081020000000065cd1da2e6dab7c1f0dcd297c8d61647fd17d821541ea69c3cc37dcbad7f90d4eb4bc500a778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af101000000002b0c230000000022512077e30a5522dd9f894c3f8b8bd4c4b2cf82ca7da8a3ea6a239655c39c050ab220ffffffff",
|
||||
"precomputedUsed": [
|
||||
"hashOutputs"
|
||||
],
|
||||
"sigHash": "cccb739eca6c13a8a89e6e5cd317ffe55669bbda23f2fd37b0f18755e008edd2"
|
||||
},
|
||||
"expected": {
|
||||
"witness": [
|
||||
"bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd981"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"auxiliary": {
|
||||
"fullySignedTx": "020000000001097de20cbff686da83a54981d2b9bab3586f4ca7e48f57f5b55963115f3b334e9c010000000000000000d7b7cab57b1393ace2d064f4d4a2cb8af6def61273e127517d44759b6dafdd990000000000fffffffff8e1f583384333689228c5d28eac13366be082dc57441760d957275419a41842000000006b4830450221008f3b8f8f0537c420654d2283673a761b7ee2ea3c130753103e08ce79201cf32a022079e7ab904a1980ef1c5890b648c8783f4d10103dd62f740d13daa79e298d50c201210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798fffffffff0689180aa63b30cb162a73c6d2a38b7eeda2a83ece74310fda0843ad604853b0100000000feffffffaa5202bdf6d8ccd2ee0f0202afbbb7461d9264a25e5bfd3c5a52ee1239e0ba6c0000000000feffffff956149bdc66faa968eb2be2d2faa29718acbfe3941215893a2a3446d32acd050000000000000000000e664b9773b88c09c32cb70a2a3e4da0ced63b7ba3b22f848531bbb1d5d5f4c94010000000000000000e9aa6b8e6c9de67619e6a3924ae25696bb7b694bb677a632a74ef7eadfd4eabf0000000000ffffffffa778eb6a263dc090464cd125c466b5a99667720b1c110468831d058aa1b82af10100000000ffffffff0200ca9a3b000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac807840cb0000000020ac9a87f5594be208f8532db38cff670c450ed2fea8fcdefcc9a663f78bab962b0141ed7c1647cb97379e76892be0cacff57ec4a7102aa24296ca39af7541246d8ff14d38958d4cc1e2e478e4d4a764bbfd835b16d4e314b72937b29833060b87276c030141052aedffc554b41f52b521071793a6b88d6dbca9dba94cf34c83696de0c1ec35ca9c5ed4ab28059bd606a4f3a657eec0bb96661d42921b5f50a95ad33675b54f83000141ff45f742a876139946a149ab4d9185574b98dc919d2eb6754f8abaa59d18b025637a3aa043b91817739554f4ed2026cf8022dbd83e351ce1fabc272841d2510a010140b4010dd48a617db09926f729e79c33ae0b4e94b79f04a1ae93ede6315eb3669de185a17d2b0ac9ee09fd4c64b678a0b61a0a86fa888a273c8511be83bfd6810f0247304402202b795e4de72646d76eab3f0ab27dfa30b810e856ff3a46c9a702df53bb0d8cc302203ccc4d822edab5f35caddb10af1be93583526ccfbade4b4ead350781e2f8adcd012102f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f90141a3785919a2ce3c4ce26f298c3d51619bc474ae24014bcdd31328cd8cfbab2eff3395fa0a16fe5f486d12f22a9cedded5ae74feb4bbe5351346508c5405bcfee0020141ea0c6ba90763c2d3a296ad82ba45881abb4f426b3f87af162dd24d5109edc1cdd11915095ba47c3a9963dc1e6c432939872bc49212fe34c632cd3ab9fed429c4820141bbc9584a11074e83bc8c6759ec55401f0ae7b03ef290c3139814f545b58a9f8127258000874f44bc46db7646322107d4d86aec8e73b8719a61fff761d75b5dd9810065cd1d"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package org.bitcoins.core.protocol.transaction
|
||||
|
||||
import org.bitcoins.core.protocol.Bech32mAddress
|
||||
import org.bitcoins.core.protocol.script._
|
||||
import org.bitcoins.crypto.{Sha256Digest, XOnlyPubKey}
|
||||
import upickle.default._
|
||||
|
||||
case class Given(internalPubkey: XOnlyPubKey, treeOpt: Option[TapscriptTree]) {
|
||||
|
||||
val leafHashes: Vector[Sha256Digest] = {
|
||||
treeOpt match {
|
||||
case None => Vector.empty
|
||||
case Some(t) =>
|
||||
t.leafs.map(_.sha256)
|
||||
}
|
||||
}
|
||||
|
||||
def merkleRootOpt: Option[Sha256Digest] = {
|
||||
treeOpt.map(s => TaprootScriptPath.computeFullTreeMerkleRoot(s))
|
||||
}
|
||||
}
|
||||
|
||||
case class Intermediary(
|
||||
leafHashes: Option[Vector[Sha256Digest]],
|
||||
merkleRootOpt: Option[Sha256Digest],
|
||||
tweak: Sha256Digest,
|
||||
tweakedPubkey: XOnlyPubKey)
|
||||
|
||||
case class Expected(
|
||||
scriptPubKey: TaprootScriptPubKey,
|
||||
bip350Address: Bech32mAddress)
|
||||
|
||||
case class TaprootWalletTestCase(
|
||||
`given`: Given,
|
||||
intermediary: Intermediary,
|
||||
expected: Expected)
|
||||
|
||||
case class TaprootWalletTestCases(tests: Vector[TaprootWalletTestCase])
|
||||
|
||||
object TaprootWalletTestCase {
|
||||
|
||||
implicit val walletTestVectorReader: Reader[TaprootWalletTestCases] = {
|
||||
reader[ujson.Obj].map { obj =>
|
||||
val testCases = obj("scriptPubKey").arr.map { testCase =>
|
||||
val givenObj = testCase("given").obj
|
||||
val internalPubkey = XOnlyPubKey.fromHex(givenObj("internalPubkey").str)
|
||||
val scriptTree = parseScriptTree(givenObj("scriptTree"))
|
||||
|
||||
val `given` = Given(internalPubkey, scriptTree)
|
||||
|
||||
val intermediaryObj = testCase("intermediary").obj
|
||||
|
||||
val intermediary = parseIntermediary(intermediaryObj)
|
||||
|
||||
val expectedObj = testCase("expected").obj
|
||||
val spk =
|
||||
TaprootScriptPubKey.fromAsmHex(expectedObj("scriptPubKey").str)
|
||||
val bip350Address =
|
||||
Bech32mAddress.fromString(expectedObj("bip350Address").str)
|
||||
val expected = Expected(spk, bip350Address)
|
||||
|
||||
TaprootWalletTestCase(`given`, intermediary, expected)
|
||||
|
||||
}
|
||||
TaprootWalletTestCases(testCases.toVector)
|
||||
}
|
||||
}
|
||||
|
||||
private def parseScriptTree(`given`: ujson.Value): Option[TapscriptTree] = {
|
||||
if (`given`.isNull) None
|
||||
else if (`given`.objOpt.isDefined) {
|
||||
val givenObj = `given`.obj
|
||||
val script = ScriptPubKey.fromAsmHex(givenObj("script").str)
|
||||
val leafVersion = givenObj("leafVersion").num.toInt
|
||||
val leaf = TapLeaf(leafVersion, script)
|
||||
Some(leaf)
|
||||
} else {
|
||||
val arr = `given`.arr
|
||||
require(arr.length == 2,
|
||||
s"tapscript is a binary tre, not ${arr.length} tree")
|
||||
val result: Vector[Option[TapscriptTree]] =
|
||||
arr.map(parseScriptTree).toVector
|
||||
val branch = TapBranch(result(0).get, result(1).get)
|
||||
Some(branch)
|
||||
}
|
||||
}
|
||||
|
||||
private def parseIntermediary(intermediaryObj: ujson.Obj): Intermediary = {
|
||||
val merkleRootOpt = {
|
||||
if (intermediaryObj("merkleRoot").isNull) None
|
||||
else Some(Sha256Digest.fromHex(intermediaryObj("merkleRoot").str))
|
||||
}
|
||||
val tweak = Sha256Digest.fromHex(intermediaryObj("tweak").str)
|
||||
val tweakedPubkey =
|
||||
XOnlyPubKey.fromHex(intermediaryObj("tweakedPubkey").str)
|
||||
|
||||
val leafHashesOpt =
|
||||
if (intermediaryObj.value.exists(_._1 == "leafHashes")) {
|
||||
val leaves = intermediaryObj("leafHashes").arr.map(l =>
|
||||
Sha256Digest.fromHex(l.str))
|
||||
Some(leaves.toVector)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
Intermediary(leafHashesOpt, merkleRootOpt, tweak, tweakedPubkey)
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package org.bitcoins.core.protocol.transaction
|
||||
|
||||
import org.bitcoins.core.config.MainNet
|
||||
import org.bitcoins.core.protocol.Bech32mAddress
|
||||
import org.bitcoins.core.protocol.script.TaprootScriptPubKey
|
||||
import org.bitcoins.testkitcore.util.BitcoinSUnitTest
|
||||
import org.scalatest.Assertion
|
||||
|
||||
class TaprootWalletTestVectors extends BitcoinSUnitTest {
|
||||
behavior of "TaprootWalletTestVectors"
|
||||
|
||||
//from: https://github.com/bitcoin/bips/blob/master/bip-0341/wallet-test-vectors.json
|
||||
lazy val url = getClass.getResource("/wallet-test-vectors.json")
|
||||
|
||||
lazy val lines = {
|
||||
scala.io.Source.fromURL(url).getLines().mkString
|
||||
}
|
||||
|
||||
lazy val testCase: TaprootWalletTestCases = {
|
||||
upickle.default.read[TaprootWalletTestCases](lines)(
|
||||
TaprootWalletTestCase.walletTestVectorReader)
|
||||
}
|
||||
|
||||
lazy val tests: Vector[TaprootWalletTestCase] = testCase.tests
|
||||
|
||||
it must "build correct taproot spks" in {
|
||||
tests.foreach { test =>
|
||||
val `given` = test.`given`
|
||||
val intermediary = test.intermediary
|
||||
if (`given`.treeOpt.isEmpty) {
|
||||
checkOutput(test)
|
||||
} else {
|
||||
val leafHashes = `given`.leafHashes
|
||||
assert(leafHashes == intermediary.leafHashes.get)
|
||||
assert(`given`.merkleRootOpt == intermediary.merkleRootOpt,
|
||||
s"test=${test.expected.bip350Address}")
|
||||
checkOutput(test)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def checkOutput(test: TaprootWalletTestCase): Assertion = {
|
||||
val `given` = test.`given`
|
||||
val intermediary = test.intermediary
|
||||
val expected = test.expected
|
||||
val internal = `given`.internalPubkey
|
||||
val tweakHash =
|
||||
internal.computeTapTweakHash(intermediary.merkleRootOpt)
|
||||
assert(tweakHash == test.intermediary.tweak)
|
||||
val (_, tweakedKey) =
|
||||
internal.createTapTweak(intermediary.merkleRootOpt)
|
||||
assert(tweakedKey == intermediary.tweakedPubkey)
|
||||
val spk = TaprootScriptPubKey.fromPubKey(tweakedKey)
|
||||
val addr = Bech32mAddress.fromScriptPubKey(spk, MainNet)
|
||||
assert(spk == expected.scriptPubKey)
|
||||
assert(addr == expected.bip350Address)
|
||||
}
|
||||
}
|
@ -47,7 +47,8 @@ class TaprootWitnessTest extends BitcoinSUnitTest {
|
||||
"7520c7b5db9562078049719228db2ac80cb9643ec96c8055aa3b29c2c03d4d99edb0ac"
|
||||
val spk = ScriptPubKey.fromAsmHex(asmHex)
|
||||
assert(asmHex == spk.asmHex)
|
||||
val hash = TaprootScriptPath.computeTapleafHash(0xc0.toByte, spk)
|
||||
val leaf = TapLeaf(0xc0.toByte, spk)
|
||||
val hash = TaprootScriptPath.computeTapleafHash(leaf)
|
||||
assert(hash.hex == expected)
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,13 @@ object TapscriptControlBlock extends Factory[TapscriptControlBlock] {
|
||||
override def fromBytes(bytes: ByteVector): TapscriptControlBlock = {
|
||||
new TapscriptControlBlock(bytes)
|
||||
}
|
||||
|
||||
def apply(
|
||||
internalKey: XOnlyPubKey,
|
||||
leafHashes: Vector[TapLeaf]): ControlBlock = {
|
||||
val bytes = internalKey.bytes ++ ByteVector.concat(leafHashes.map(_.bytes))
|
||||
ControlBlock(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
object UnknownControlBlock extends Factory[UnknownControlBlock] {
|
||||
|
@ -499,10 +499,10 @@ object TaprootScriptPath extends Factory[TaprootScriptPath] {
|
||||
* @see https://github.com/bitcoin/bitcoin/blob/37633d2f61697fc719390767aae740ece978b074/src/script/interpreter.cpp#L1828
|
||||
* @return
|
||||
*/
|
||||
def computeTapleafHash(leafVersion: Byte, spk: ScriptPubKey): Sha256Digest = {
|
||||
def computeTapleafHash(leaf: TapLeaf): Sha256Digest = {
|
||||
val bytes =
|
||||
ByteVector.fromByte(leafVersion) ++ spk.bytes
|
||||
CryptoUtil.taggedSha256(bytes, "TapLeaf")
|
||||
ByteVector.fromInt(i = leaf.leafVersion, size = 1) ++ leaf.spk.bytes
|
||||
CryptoUtil.tapLeafHash(bytes)
|
||||
}
|
||||
|
||||
/** Computes the merkle root of a tapscript tree
|
||||
@ -533,6 +533,22 @@ object TaprootScriptPath extends Factory[TaprootScriptPath] {
|
||||
k
|
||||
}
|
||||
|
||||
def computeFullTreeMerkleRoot(tree: TapscriptTree): Sha256Digest = {
|
||||
tree match {
|
||||
case branch: TapBranch =>
|
||||
val left = computeFullTreeMerkleRoot(branch.tree1)
|
||||
val right = computeFullTreeMerkleRoot(branch.tree2)
|
||||
val sorted = if (left.bytes.compare(right.bytes) <= 0) {
|
||||
left.bytes ++ right.bytes
|
||||
} else {
|
||||
right.bytes ++ left.bytes
|
||||
}
|
||||
CryptoUtil.tapBranchHash(sorted)
|
||||
case l: TapLeaf => l.sha256
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Checks the witness stack has an annex in it */
|
||||
def hasAnnex(stack: Vector[ByteVector]): Boolean = {
|
||||
stack.length > 1 && stack.headOption
|
||||
|
@ -0,0 +1,28 @@
|
||||
package org.bitcoins.core.protocol.script
|
||||
|
||||
import org.bitcoins.crypto.{CryptoUtil, NetworkElement, Sha256Digest}
|
||||
import scodec.bits.ByteVector
|
||||
|
||||
sealed abstract class TapscriptTree extends NetworkElement {
|
||||
def leafs: Vector[TapLeaf]
|
||||
}
|
||||
|
||||
case class TapBranch(tree1: TapscriptTree, tree2: TapscriptTree)
|
||||
extends TapscriptTree {
|
||||
|
||||
override val bytes: ByteVector = {
|
||||
tree1.bytes ++ tree2.bytes
|
||||
}
|
||||
|
||||
override def leafs: Vector[TapLeaf] = {
|
||||
tree1.leafs ++ tree2.leafs
|
||||
}
|
||||
}
|
||||
|
||||
case class TapLeaf(leafVersion: Int, spk: ScriptPubKey) extends TapscriptTree {
|
||||
|
||||
override val bytes: ByteVector =
|
||||
ByteVector.fromInt(leafVersion, 1) ++ spk.bytes
|
||||
val sha256: Sha256Digest = CryptoUtil.tapLeafHash(bytes)
|
||||
override val leafs: Vector[TapLeaf] = Vector(this)
|
||||
}
|
@ -3,6 +3,7 @@ package org.bitcoins.core.script
|
||||
import org.bitcoins.core.crypto._
|
||||
import org.bitcoins.core.number.UInt32
|
||||
import org.bitcoins.core.protocol.script.{
|
||||
TapLeaf,
|
||||
TaprootKeyPath,
|
||||
TaprootScriptPath,
|
||||
TaprootUnknownPath,
|
||||
@ -84,9 +85,8 @@ sealed trait ScriptProgram {
|
||||
/** Calculates the leaf hash if we have a tapscript, else returns None if we don't have a tapscript */
|
||||
def tapLeafHashOpt: Option[Sha256Digest] = {
|
||||
getTapscriptOpt.map { sp =>
|
||||
val hash = TaprootScriptPath.computeTapleafHash(
|
||||
TaprootScriptPath.TAPROOT_LEAF_TAPSCRIPT,
|
||||
sp.script)
|
||||
val leaf = TapLeaf(TaprootScriptPath.TAPROOT_LEAF_TAPSCRIPT, sp.script)
|
||||
val hash = TaprootScriptPath.computeTapleafHash(leaf)
|
||||
hash
|
||||
}
|
||||
}
|
||||
|
@ -653,9 +653,8 @@ sealed abstract class ScriptInterpreter {
|
||||
val controlBlock = taprootScriptPath.controlBlock
|
||||
val script = taprootScriptPath.script
|
||||
//execdata.m_tapleaf_hash = ComputeTapleafHash(control[0] & TAPROOT_LEAF_MASK, exec_script);
|
||||
val tapLeafHash = TaprootScriptPath.computeTapleafHash(
|
||||
controlBlock.leafVersion,
|
||||
script)
|
||||
val leaf = TapLeaf(controlBlock.leafVersion, script)
|
||||
val tapLeafHash = TaprootScriptPath.computeTapleafHash(leaf)
|
||||
val isValidTaprootCommitment =
|
||||
TaprootScriptPath.verifyTaprootCommitment(
|
||||
controlBlock = controlBlock,
|
||||
|
@ -42,6 +42,18 @@ trait CryptoRuntime {
|
||||
sha256(tagBytes ++ bytes)
|
||||
}
|
||||
|
||||
def tapTweakHash(bytes: ByteVector): Sha256Digest = {
|
||||
CryptoUtil.taggedSha256(bytes, "TapTweak")
|
||||
}
|
||||
|
||||
def tapBranchHash(bytes: ByteVector): Sha256Digest = {
|
||||
CryptoUtil.taggedSha256(bytes, "TapBranch")
|
||||
}
|
||||
|
||||
def tapLeafHash(bytes: ByteVector): Sha256Digest = {
|
||||
CryptoUtil.taggedSha256(bytes, "TapLeaf")
|
||||
}
|
||||
|
||||
/** Performs sha256(sha256(bytes)). */
|
||||
def doubleSHA256(bytes: ByteVector): DoubleSha256Digest = {
|
||||
val hash: ByteVector = sha256(sha256(bytes).bytes).bytes
|
||||
|
@ -6,7 +6,7 @@ import java.math.BigInteger
|
||||
import scala.util.Try
|
||||
|
||||
/** Represents the raw bytes which are meant to represent an ECKey without deserializing. */
|
||||
sealed trait ECKeyBytes extends NetworkElement
|
||||
sealed abstract class ECKeyBytes extends NetworkElement
|
||||
|
||||
/** Represents a serialization sensitive ECPrivateKey (such as is used in WIF). */
|
||||
case class ECPrivateKeyBytes(bytes: ByteVector, isCompressed: Boolean = true)
|
||||
|
@ -62,8 +62,21 @@ case class XOnlyPubKey(bytes: ByteVector) extends PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
/** @see https://github.com/bitcoin/bitcoin/blob/bdb33ec51986570ea17406c83bad2c955ae23186/src/pubkey.cpp#L249
|
||||
* @param merkleRootOpt if the merkle root is empty we have no scripts.
|
||||
* @return
|
||||
*/
|
||||
def createTapTweak(
|
||||
merkleRootOpt: Option[Sha256Digest]): (KeyParity, XOnlyPubKey) = {
|
||||
val taggedHash = computeTapTweakHash(merkleRootOpt)
|
||||
val result = CryptoParams.getG
|
||||
.multiply(FieldElement(taggedHash.bytes))
|
||||
.add(this.publicKey)
|
||||
(result.parity, result.toXOnly)
|
||||
}
|
||||
|
||||
private def tapTweakHash(bytes: ByteVector): Sha256Digest = {
|
||||
CryptoUtil.taggedSha256(bytes, "TapTweak")
|
||||
CryptoUtil.tapTweakHash(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user