diff --git a/bip352-testsuite/bech32m.py b/bip352-testsuite/bech32m.py new file mode 100644 index 0000000000..795e153863 --- /dev/null +++ b/bip352-testsuite/bech32m.py @@ -0,0 +1,135 @@ +# Copyright (c) 2017, 2020 Pieter Wuille +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +"""Reference implementation for Bech32/Bech32m and segwit addresses.""" + + +from enum import Enum + +class Encoding(Enum): + """Enumeration type to list the various supported encodings.""" + BECH32 = 1 + BECH32M = 2 + +CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" +BECH32M_CONST = 0x2bc830a3 + +def bech32_polymod(values): + """Internal function that computes the Bech32 checksum.""" + generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3] + chk = 1 + for value in values: + top = chk >> 25 + chk = (chk & 0x1ffffff) << 5 ^ value + for i in range(5): + chk ^= generator[i] if ((top >> i) & 1) else 0 + return chk + + +def bech32_hrp_expand(hrp): + """Expand the HRP into values for checksum computation.""" + return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp] + + +def bech32_verify_checksum(hrp, data): + """Verify a checksum given HRP and converted data characters.""" + const = bech32_polymod(bech32_hrp_expand(hrp) + data) + if const == 1: + return Encoding.BECH32 + if const == BECH32M_CONST: + return Encoding.BECH32M + return None + +def bech32_create_checksum(hrp, data, spec): + """Compute the checksum values given HRP and data.""" + values = bech32_hrp_expand(hrp) + data + const = BECH32M_CONST if spec == Encoding.BECH32M else 1 + polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const + return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)] + + +def bech32_encode(hrp, data, spec): + """Compute a Bech32 string given HRP and data values.""" + combined = data + bech32_create_checksum(hrp, data, spec) + return hrp + '1' + ''.join([CHARSET[d] for d in combined]) + +def bech32_decode(bech): + """Validate a Bech32/Bech32m string, and determine HRP and data.""" + if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or + (bech.lower() != bech and bech.upper() != bech)): + return (None, None, None) + bech = bech.lower() + pos = bech.rfind('1') + + # remove the requirement that bech32m be less than 90 chars + if pos < 1 or pos + 7 > len(bech): + return (None, None, None) + if not all(x in CHARSET for x in bech[pos+1:]): + return (None, None, None) + hrp = bech[:pos] + data = [CHARSET.find(x) for x in bech[pos+1:]] + spec = bech32_verify_checksum(hrp, data) + if spec is None: + return (None, None, None) + return (hrp, data[:-6], spec) + +def convertbits(data, frombits, tobits, pad=True): + """General power-of-2 base conversion.""" + acc = 0 + bits = 0 + ret = [] + maxv = (1 << tobits) - 1 + max_acc = (1 << (frombits + tobits - 1)) - 1 + for value in data: + if value < 0 or (value >> frombits): + return None + acc = ((acc << frombits) | value) & max_acc + bits += frombits + while bits >= tobits: + bits -= tobits + ret.append((acc >> bits) & maxv) + if pad: + if bits: + ret.append((acc << (tobits - bits)) & maxv) + elif bits >= frombits or ((acc << (tobits - bits)) & maxv): + return None + return ret + + +def decode(hrp, addr): + """Decode a segwit address.""" + hrpgot, data, spec = bech32_decode(addr) + if hrpgot != hrp: + return (None, None) + decoded = convertbits(data[1:], 5, 8, False) + if decoded is None or len(decoded) < 2: + return (None, None) + if data[0] > 16: + return (None, None) + return (data[0], decoded) + + +def encode(hrp, witver, witprog): + """Encode a segwit address.""" + spec = Encoding.BECH32 if witver == 0 else Encoding.BECH32M + ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5), spec) + if decode(hrp, ret) == (None, None): + return None + return ret diff --git a/bip352-testsuite/bip352-send_and_receive_test_vectors.json b/bip352-testsuite/bip352-send_and_receive_test_vectors.json new file mode 100644 index 0000000000..ef56fbb864 --- /dev/null +++ b/bip352-testsuite/bip352-send_and_receive_test_vectors.json @@ -0,0 +1,1743 @@ +[ + { + "comment": "Simple send: two inputs", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "39a1e5ff6206cd316151b9b34cee4f80bb48ce61adee0a12ce7ff05ea436a1d9", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "39a1e5ff6206cd316151b9b34cee4f80bb48ce61adee0a12ce7ff05ea436a1d9" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "39a1e5ff6206cd316151b9b34cee4f80bb48ce61adee0a12ce7ff05ea436a1d9", + "priv_key_tweak": "8e4bbee712779f746337cadf39e8b1eab8e8869dd40f2e3a7281113e858ffc0b", + "signature": "e18fe06280456ed533808606f73e0d46dea49f90751078d127379a8e176a6e56bb1e86f4ca3522a58e760a4ea68e6f3a26b24dcbcb9c614d4d5d2bce9bf956bf" + } + ] + } + } + ] + }, + { + "comment": "Simple send: two inputs, order reversed", + "sending": [ + { + "given": { + "outpoints": [ + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ], + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "39a1e5ff6206cd316151b9b34cee4f80bb48ce61adee0a12ce7ff05ea436a1d9", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ], + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "39a1e5ff6206cd316151b9b34cee4f80bb48ce61adee0a12ce7ff05ea436a1d9" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "39a1e5ff6206cd316151b9b34cee4f80bb48ce61adee0a12ce7ff05ea436a1d9", + "priv_key_tweak": "8e4bbee712779f746337cadf39e8b1eab8e8869dd40f2e3a7281113e858ffc0b", + "signature": "e18fe06280456ed533808606f73e0d46dea49f90751078d127379a8e176a6e56bb1e86f4ca3522a58e760a4ea68e6f3a26b24dcbcb9c614d4d5d2bce9bf956bf" + } + ] + } + } + ] + }, + { + "comment": "Simple send: two inputs from the same transaction", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 3 + ], + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 7 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "162f2298705b3ddca01ce1d214eedff439df3927582938d08e29e464908db00b", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 3 + ], + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 7 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "162f2298705b3ddca01ce1d214eedff439df3927582938d08e29e464908db00b" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "162f2298705b3ddca01ce1d214eedff439df3927582938d08e29e464908db00b", + "priv_key_tweak": "f06d8d90561bdbc3e511c3bec7355ad3c858aaf38a132c772d6cd82ec04102ac", + "signature": "4c900d573964d31953acdaedbcbb7866fedbdc215417adfd4173073f86179cad5903ae64490629fae610bf879263c3b9f5c7e6ec1b32a159e2d2e60a16d36597" + } + ] + } + } + ] + }, + { + "comment": "Simple send: two inputs from the same transaction, order reversed", + "sending": [ + { + "given": { + "outpoints": [ + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 7 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 3 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "93f5ed907ad5b2bdbbdcb5d9116ebc0a4e1f92f910d5260237fa45a9408aad16", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "d9ede52f7e1e64e36ccf895ca0250daad96b174987079c903519b17852b21a3f", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 7 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 3 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "d9ede52f7e1e64e36ccf895ca0250daad96b174987079c903519b17852b21a3f" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "d9ede52f7e1e64e36ccf895ca0250daad96b174987079c903519b17852b21a3f", + "priv_key_tweak": "44b827516c2128287b1d571add7cfeb42f122e86bc40b4eb2b21ac144607fdb2", + "signature": "1bdb32461dd502ee9c19c7dff5f3801a26c2bc0ffe6f34671053ef7083ea0d5adca6036564252a76e427555deb17edd6f801d45cd7b830d7e3003eb3c8c85263" + } + ] + } + } + ] + }, + { + "comment": "Single recipient: multiple UTXOs from the same public key", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "0aafdcdb5893ae813299b16eea75f34ec16653ac39171da04d7c4e6d2e09ab8e", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "0aafdcdb5893ae813299b16eea75f34ec16653ac39171da04d7c4e6d2e09ab8e" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "0aafdcdb5893ae813299b16eea75f34ec16653ac39171da04d7c4e6d2e09ab8e", + "priv_key_tweak": "bf7336bdc02f624715aab385cc62b71f6f494bf8a7dd0fd621cfd365039c39d1", + "signature": "e00ba3406cea12127896fbc198a9da889a4afcf3d66e46b3df0e7bb36de400a109442e5bbd005c3cc5ae30ae7d235ea111475ad621e1e2c27374fda906521c69" + } + ] + } + } + ] + }, + { + "comment": "Single recipient: taproot only inputs with even y-values", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + true + ], + [ + "fc8716a97a48ba9a05a98ae47b5cd201a25a7fd5d8b73c203c5f7b6b6b3b6ad7", + true + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "15d1dfe4403791509cf47f073be2eb3277decabe90da395e63b1f49a09fe965e", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "5a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "15d1dfe4403791509cf47f073be2eb3277decabe90da395e63b1f49a09fe965e" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "15d1dfe4403791509cf47f073be2eb3277decabe90da395e63b1f49a09fe965e", + "priv_key_tweak": "0734de077e436e8f6f125e16287cb60dead8ebddc8532be3589ba27156f1add2", + "signature": "d743170ded6bc695f2997caed9886deb7ddc2e0e11d5f1493d6d7e498e8686f94c393c5d20eceb700a4c2035271196897a83fe1658414c38da07e0e4af00fd0a" + } + ] + } + } + ] + }, + { + "comment": "Single recipient: taproot only with mixed even/odd y-values", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + true + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + true + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "15d1dfe4403791509cf47f073be2eb3277decabe90da395e63b1f49a09fe965e", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "5a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "15d1dfe4403791509cf47f073be2eb3277decabe90da395e63b1f49a09fe965e" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "15d1dfe4403791509cf47f073be2eb3277decabe90da395e63b1f49a09fe965e", + "priv_key_tweak": "0734de077e436e8f6f125e16287cb60dead8ebddc8532be3589ba27156f1add2", + "signature": "d743170ded6bc695f2997caed9886deb7ddc2e0e11d5f1493d6d7e498e8686f94c393c5d20eceb700a4c2035271196897a83fe1658414c38da07e0e4af00fd0a" + } + ] + } + } + ] + }, + { + "comment": "Single recipient: taproot input with even y-value and non-taproot input", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + true + ], + [ + "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "2b4ff8e5bc608cbdd12117171e7d265b6882ad597559caf67b5ecfaf15301dd0", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "5a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "2b4ff8e5bc608cbdd12117171e7d265b6882ad597559caf67b5ecfaf15301dd0" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "2b4ff8e5bc608cbdd12117171e7d265b6882ad597559caf67b5ecfaf15301dd0", + "priv_key_tweak": "17d93733d2acd8388279c24dc4413483802378c99f266f5961ac3338c5146861", + "signature": "7f8f909460c0357a2c1c784e92967e888c6b63ff799db3ce22e8acc715a42ab9177b9db2237d76db60e72bc30c827008266062506cd57f93f9b872529bd50376" + } + ] + } + } + ] + }, + { + "comment": "Single recipient: taproot input with odd y-value and non-taproot input", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + true + ], + [ + "8d4751f6e8a3586880fb66c19ae277969bd5aa06f61c4ee2f1e2486efdf666d3", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "75f501f319db549aaa613717bd7af44da566d4d859b67fe436946564fafc47a3", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338", + "03e0ec4f64b3fa2e463ccfcf4e856e37d5e1e20275bc89ec1def9eb098eff1f85d" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "75f501f319db549aaa613717bd7af44da566d4d859b67fe436946564fafc47a3" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "75f501f319db549aaa613717bd7af44da566d4d859b67fe436946564fafc47a3", + "priv_key_tweak": "619a5a59a16d4a8e857ef48e63ef7c8195c858191d4e826205e8438ab70d059e", + "signature": "ba2e40de3b3acbc97d282f2d09b9c79936de109710e8d4139409964346f1221c3d4c823a1ee0a946f98b0ce644d136fbc5ea22cd73736fe05475174b25c01e62" + } + ] + } + } + ] + }, + { + "comment": "Multiple outputs: multiple outputs, same recipient", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 2.0 + ], + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 3.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + 2.0 + ], + [ + "0a48c6ccc1d516e8244dc0153dc88db45f8f264357667c2057a29ca3c2445d09", + 3.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "0a48c6ccc1d516e8244dc0153dc88db45f8f264357667c2057a29ca3c2445d09", + "c58e121044b23cba9b4695052229a9fd9e044b579f92864eb886ae7c99b021c9", + "4b15b75f3f184328c4a2f7c79357481ed06cf3b6f95512d5ed946fdc0b60d62b" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e30", + "signature": "3f6226feb9e4cafc0bdab8c9cfe085885308f3708c222bcec6cf26467685d897f51597abe39d1d279708e63513c7be23daed78607a98837060950493de188645" + }, + { + "pub_key": "0a48c6ccc1d516e8244dc0153dc88db45f8f264357667c2057a29ca3c2445d09", + "priv_key_tweak": "d39df91bd0e7825bfa1d30096febc5bf6fa7da79d7f25b7b4bea9538cc9a9f7f", + "signature": "be5f139f6eaad2d5eb75c6e307defb29925e16d55dbbc12872b0ab6aca38959c0c6a8f3f72bf82e3deb226cb539e117f9db4b04a5efb4e2eb01a86374f5baa12" + } + ] + } + } + ] + }, + { + "comment": "Multiple outputs: multiple outputs, multiple recipients", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 2.0 + ], + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 3.0 + ], + [ + "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn", + 4.0 + ], + [ + "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn", + 5.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + 2.0 + ], + [ + "0a48c6ccc1d516e8244dc0153dc88db45f8f264357667c2057a29ca3c2445d09", + 3.0 + ], + [ + "c58e121044b23cba9b4695052229a9fd9e044b579f92864eb886ae7c99b021c9", + 4.0 + ], + [ + "4b15b75f3f184328c4a2f7c79357481ed06cf3b6f95512d5ed946fdc0b60d62b", + 5.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "0a48c6ccc1d516e8244dc0153dc88db45f8f264357667c2057a29ca3c2445d09", + "c58e121044b23cba9b4695052229a9fd9e044b579f92864eb886ae7c99b021c9", + "4b15b75f3f184328c4a2f7c79357481ed06cf3b6f95512d5ed946fdc0b60d62b" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e30", + "signature": "3f6226feb9e4cafc0bdab8c9cfe085885308f3708c222bcec6cf26467685d897f51597abe39d1d279708e63513c7be23daed78607a98837060950493de188645" + }, + { + "pub_key": "0a48c6ccc1d516e8244dc0153dc88db45f8f264357667c2057a29ca3c2445d09", + "priv_key_tweak": "d39df91bd0e7825bfa1d30096febc5bf6fa7da79d7f25b7b4bea9538cc9a9f7f", + "signature": "be5f139f6eaad2d5eb75c6e307defb29925e16d55dbbc12872b0ab6aca38959c0c6a8f3f72bf82e3deb226cb539e117f9db4b04a5efb4e2eb01a86374f5baa12" + } + ] + } + }, + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "decafbad", + "scan_priv_key": "060b751d7892149006ed7b98606955a29fe284a1e900070c0971f5fb93dbf422", + "spend_priv_key": "9902c3c56e84002a7cd410113a9ab21d142be7f53cf5200720bb01314c5eb920", + "labels": {}, + "outputs": [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "0a48c6ccc1d516e8244dc0153dc88db45f8f264357667c2057a29ca3c2445d09", + "c58e121044b23cba9b4695052229a9fd9e044b579f92864eb886ae7c99b021c9", + "4b15b75f3f184328c4a2f7c79357481ed06cf3b6f95512d5ed946fdc0b60d62b" + ] + }, + "expected": { + "addresses": [ + "sp1qqgrz6j0lcqnc04vxccydl0kpsj4frfje0ktmgcl2t346hkw30226xqupawdf48k8882j0strrvcmgg2kdawz53a54dd376ngdhak364hzcmynqtn" + ], + "outputs": [ + { + "pub_key": "c58e121044b23cba9b4695052229a9fd9e044b579f92864eb886ae7c99b021c9", + "priv_key_tweak": "567710d07bdaacc8de3f1cec467bcb162ed7daa6b901b59af257bcd7e39dffcf", + "signature": "d675fd6f55f42b61c8797c80d46048cfca5125bcef06e3a0ff555ace0e8f6d84da9b6f473b559376afd5ee11dc63c4415dc565f8272d2b673d39759f29c0d56a" + }, + { + "pub_key": "4b15b75f3f184328c4a2f7c79357481ed06cf3b6f95512d5ed946fdc0b60d62b", + "priv_key_tweak": "25dd11163a9a2853709c4c837aafb3347e2eaa875cf4c5170e2a3663879f4c58", + "signature": "ab872ee64623cf1ddb646c65159c09bc69cd64c6b60767a94934e12ec074f0fa7c9e4cc6a9bca2ec6592e4d64636a07fcfd71c622619c3bf46c5a2816aeb3456" + } + ] + } + } + ] + }, + { + "comment": "Receiving with labels: label with even parity", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqhmem6grvs4nacsu0v5v5mjs934j7qfgkdkj8c95gyuru3tjpulvcwky2dz", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "2cbceeab2a4982841eb7dc34b8b4f19c04bf3bc083ebf984f5664366778eb50f", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": true, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": { + "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5": "0000000000000000000000000000000000000000000000000000000000000002", + "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9": "0000000000000000000000000000000000000000000000000000000000000003", + "03348b4f5feb64b557dac8cfa10044bdc2094fca9147163bf514f68687e0d1dba6": "00000000000000000000000000000000000000000000000000000000000f4779" + }, + "outputs": [ + "2cbceeab2a4982841eb7dc34b8b4f19c04bf3bc083ebf984f5664366778eb50f" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqhmem6grvs4nacsu0v5v5mjs934j7qfgkdkj8c95gyuru3tjpulvcwky2dz", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqc389f45lq7jyqt8jxq6fkskfukr2tlruf6w8cpcx2krntwe4fr9ykagp3j", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq4umqa5feskydh9xadc9jlc22c89tu0apcv72u2vkuwtsrgzf0uesq45zq9" + ], + "outputs": [ + { + "pub_key": "2cbceeab2a4982841eb7dc34b8b4f19c04bf3bc083ebf984f5664366778eb50f", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e32", + "signature": "0fa1b43afde9a03901dda91a0bd66fc82b6452c14a20718dc87dc70d4cedd9aeadf7c4c96116b8053c4aa113e26cea2fb64f8c408a8e8bc6e4fc9f6a06672b95" + } + ] + } + } + ] + }, + { + "comment": "Receiving with labels: label with odd parity", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqc389f45lq7jyqt8jxq6fkskfukr2tlruf6w8cpcx2krntwe4fr9ykagp3j", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "6b4455de119f51bf4d4a12dea555f14a5dc2c1369af5fba4871c5367264c028d", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": true, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": { + "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5": "0000000000000000000000000000000000000000000000000000000000000002", + "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9": "0000000000000000000000000000000000000000000000000000000000000003", + "03348b4f5feb64b557dac8cfa10044bdc2094fca9147163bf514f68687e0d1dba6": "00000000000000000000000000000000000000000000000000000000000f4779" + }, + "outputs": [ + "6b4455de119f51bf4d4a12dea555f14a5dc2c1369af5fba4871c5367264c028d" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqhmem6grvs4nacsu0v5v5mjs934j7qfgkdkj8c95gyuru3tjpulvcwky2dz", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqc389f45lq7jyqt8jxq6fkskfukr2tlruf6w8cpcx2krntwe4fr9ykagp3j", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq4umqa5feskydh9xadc9jlc22c89tu0apcv72u2vkuwtsrgzf0uesq45zq9" + ], + "outputs": [ + { + "pub_key": "6b4455de119f51bf4d4a12dea555f14a5dc2c1369af5fba4871c5367264c028d", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e33", + "signature": "b4ea01f7f47bcdf131b5a3aa3a1c848faae75e661d63bfff84c230bcc96313d0b443b9b3a76718a7474d51994395739bc6041caabe98133e3697412e07e19c0a" + } + ] + } + } + ] + }, + { + "comment": "Receiving with labels: large label integer", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq4umqa5feskydh9xadc9jlc22c89tu0apcv72u2vkuwtsrgzf0uesq45zq9", + 1.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "c3473bfcbe5e4d20d0790ae91f1b339bc15b46de64ca068d140118d0e325b849", + 1.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": true, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": { + "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5": "0000000000000000000000000000000000000000000000000000000000000002", + "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9": "0000000000000000000000000000000000000000000000000000000000000003", + "03348b4f5feb64b557dac8cfa10044bdc2094fca9147163bf514f68687e0d1dba6": "00000000000000000000000000000000000000000000000000000000000f4779" + }, + "outputs": [ + "c3473bfcbe5e4d20d0790ae91f1b339bc15b46de64ca068d140118d0e325b849" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqhmem6grvs4nacsu0v5v5mjs934j7qfgkdkj8c95gyuru3tjpulvcwky2dz", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqc389f45lq7jyqt8jxq6fkskfukr2tlruf6w8cpcx2krntwe4fr9ykagp3j", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq4umqa5feskydh9xadc9jlc22c89tu0apcv72u2vkuwtsrgzf0uesq45zq9" + ], + "outputs": [ + { + "pub_key": "c3473bfcbe5e4d20d0790ae91f1b339bc15b46de64ca068d140118d0e325b849", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc1175a9", + "signature": "ab9f3684cb497951fd013444d35909ed10669691d9fa3ac0be57f874a4df9f43c67647c9f17528110d2df0ce41dd3c05c04f4624629f8758fff1060049dc7d6b" + } + ] + } + } + ] + }, + { + "comment": "Multiple outputs with labels: un-labeled and labeled address; same recipient", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ], + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj", + 2.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + 1.0 + ], + [ + "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e", + 2.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": true, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": { + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798": "0000000000000000000000000000000000000000000000000000000000000001" + }, + "outputs": [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj" + ], + "outputs": [ + { + "pub_key": "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e30", + "signature": "3f6226feb9e4cafc0bdab8c9cfe085885308f3708c222bcec6cf26467685d897f51597abe39d1d279708e63513c7be23daed78607a98837060950493de188645" + }, + { + "pub_key": "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e", + "priv_key_tweak": "d39df91bd0e7825bfa1d30096febc5bf6fa7da79d7f25b7b4bea9538cc9a9f80", + "signature": "567f0d4d914456141ca83fe89e99f008c1f7ab9e9a65d4a60162840824737407acbaa61d7efa1a6af5d6439d213187e2f76696bb657dc709a0077bbf3b40e2f2" + } + ] + } + } + ] + }, + { + "comment": "Multiple outputs with labels: multiple outputs for labeled address; same recipient", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj", + 3.0 + ], + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj", + 4.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "8890c19f005d6f6add5fef92d37ac6b161b7fdd5c1aef6eed1d32be3f216ac4c", + 3.0 + ], + [ + "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e", + 4.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": true, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": { + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798": "0000000000000000000000000000000000000000000000000000000000000001" + }, + "outputs": [ + "8890c19f005d6f6add5fef92d37ac6b161b7fdd5c1aef6eed1d32be3f216ac4c", + "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj" + ], + "outputs": [ + { + "pub_key": "8890c19f005d6f6add5fef92d37ac6b161b7fdd5c1aef6eed1d32be3f216ac4c", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e31", + "signature": "f0eb3b826553709356c351e1ced49a72900f261be18e64914c3c694af94595a4a80417ecbf5e86fde8b08e451fb42ec36b7a9d733eb42f92206f4f6c78da66bb" + }, + { + "pub_key": "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e", + "priv_key_tweak": "d39df91bd0e7825bfa1d30096febc5bf6fa7da79d7f25b7b4bea9538cc9a9f80", + "signature": "567f0d4d914456141ca83fe89e99f008c1f7ab9e9a65d4a60162840824737407acbaa61d7efa1a6af5d6439d213187e2f76696bb657dc709a0077bbf3b40e2f2" + } + ] + } + } + ] + }, + { + "comment": "Multiple outputs with labels: un-labeled, labeled, and multiple outputs for labeled address; multiple recipients", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 5.0 + ], + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj", + 6.0 + ], + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq562yg7htxyg8eq60rl37uul37jy62apnf5ru62uef0eajpdfrnp5cmqndj", + 7.0 + ], + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq562yg7htxyg8eq60rl37uul37jy62apnf5ru62uef0eajpdfrnp5cmqndj", + 8.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + 5.0 + ], + [ + "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e", + 6.0 + ], + [ + "1b90a42136fef9ff2ca192abffc7be4536dc83d4e61cf18ae078f7e92b297cce", + 7.0 + ], + [ + "87a82600c08a255bc97d172e10816e322967eed6a77c9f37dd926492d7fdc106", + 8.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": true, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": { + "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798": "0000000000000000000000000000000000000000000000000000000000000001", + "02db0c51cc634a4096374b0b895584a3ca2fb3bea4fd0ee2361f8db63a650fcee6": "0000000000000000000000000000000000000000000000000000000000000539" + }, + "outputs": [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e", + "1b90a42136fef9ff2ca192abffc7be4536dc83d4e61cf18ae078f7e92b297cce", + "87a82600c08a255bc97d172e10816e322967eed6a77c9f37dd926492d7fdc106" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqah4hxfsjdwyaeel4g8x2npkj7qlvf2692l5760z5ut0ggnlrhdzsy3cvsj", + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgq562yg7htxyg8eq60rl37uul37jy62apnf5ru62uef0eajpdfrnp5cmqndj" + ], + "outputs": [ + { + "pub_key": "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e30", + "signature": "3f6226feb9e4cafc0bdab8c9cfe085885308f3708c222bcec6cf26467685d897f51597abe39d1d279708e63513c7be23daed78607a98837060950493de188645" + }, + { + "pub_key": "7956317130124c32afd07b3f2432a3e92c1447cf58da95491a307ae3d564535e", + "priv_key_tweak": "d39df91bd0e7825bfa1d30096febc5bf6fa7da79d7f25b7b4bea9538cc9a9f80", + "signature": "567f0d4d914456141ca83fe89e99f008c1f7ab9e9a65d4a60162840824737407acbaa61d7efa1a6af5d6439d213187e2f76696bb657dc709a0077bbf3b40e2f2" + }, + { + "pub_key": "1b90a42136fef9ff2ca192abffc7be4536dc83d4e61cf18ae078f7e92b297cce", + "priv_key_tweak": "255a912ad6cdebc0842d49fd9f7b2d81ee37d66c62839879371b699010f78ef1", + "signature": "aa4cc7be2d90f30984d93535058f4894a6e0c7698deaaef179eda55724cc214e8e6ed055d437f1bf37c8c5c5431dad5080d03200cdd861a5b5e3855515e15d61" + }, + { + "pub_key": "87a82600c08a255bc97d172e10816e322967eed6a77c9f37dd926492d7fdc106", + "priv_key_tweak": "d7535d792cb1388ab0b3bd5ff57337436d62f7719c1796beb5d80ab2fa34f307", + "signature": "d68d0005118fcaae6d970925b452d038a03fda40d50aa9d6d3b4aff8189f226c71428838eadaf55662048f549bc7b19380438f09df9344eff30b96497b6aafa3" + } + ] + } + } + ] + }, + { + "comment": "Single recipient: use silent payments for sender change", + "sending": [ + { + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_priv_keys": [ + [ + "eadc78165ff1f8ea94ad7cfdc54990738a4c53f6e0507b42154201b8e5dff3b1", + false + ], + [ + "0378e95685b74565fa56751b84a32dfd18545d10d691641b8372e32164fad66a", + false + ] + ], + "recipients": [ + [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv", + 1.0 + ], + [ + "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqll5497pp2gcr4cmq0v5nv07x8u5jswmf8ap2q0kxmx8628mkqanyu63ck8", + 2.0 + ] + ] + }, + "expected": { + "outputs": [ + [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + 1.0 + ], + [ + "0050c52a32566c0dfb517e473c68fedce4bd4543d219348d3bbdceeeb5755e34", + 2.0 + ] + ] + } + } + ], + "receiving": [ + { + "supports_labels": true, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "deadbeef", + "scan_priv_key": "11b7a82e06ca2648d5fded2366478078ec4fc9dc1d8ff487518226f229d768fd", + "spend_priv_key": "b8f87388cbb41934c50daca018901b00070a5ff6cc25a7e9e716a9d5b9e4d664", + "labels": { + "02295dc38e877b754c0d0ed767434f1572cf34a82ccc06ffea1d9e04f1f7878e1a": "91cb04398a508c9d995ff4a18e5eae24d5e9488309f189120a3fdbb977978c46" + }, + "outputs": [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "0050c52a32566c0dfb517e473c68fedce4bd4543d219348d3bbdceeeb5755e34" + ] + }, + "expected": { + "addresses": [ + "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqauj52ymtc4xdkmx3tgyhrsemg2g3303xk2gtzfy8h8ejet8fz8jcw23zua", + "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqll5497pp2gcr4cmq0v5nv07x8u5jswmf8ap2q0kxmx8628mkqanyu63ck8" + ], + "outputs": [ + { + "pub_key": "0050c52a32566c0dfb517e473c68fedce4bd4543d219348d3bbdceeeb5755e34", + "priv_key_tweak": "2e9c2a37cfa7827907d36357f0632d258dbd14b3a7854937ecf732fb6acefdc8", + "signature": "6ba068ee36454c5ff002082578e234917de9e384df739c43a8b7c4cce58724cba4479191cf972b235bc4bb6c2a8d6081650d1d5ba043b59bd51d6ac15d55b396" + } + ] + } + }, + { + "supports_labels": false, + "given": { + "outpoints": [ + [ + "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", + 0 + ], + [ + "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d", + 0 + ] + ], + "input_pub_keys": [ + "025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5", + "03782eeb913431ca6e9b8c2fd80a5f72ed2024ef72a3c6fb10263c379937323338" + ], + "bip32_seed": "f00dbabe", + "scan_priv_key": "0f694e068028a717f8af6b9411f9a133dd3565258714cc226594b34db90c1f2c", + "spend_priv_key": "9d6ad855ce3417ef84e836892e5a56392bfba05fa5d97ccea30e266f540e08b3", + "labels": {}, + "outputs": [ + "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "0050c52a32566c0dfb517e473c68fedce4bd4543d219348d3bbdceeeb5755e34" + ] + }, + "expected": { + "addresses": [ + "sp1qqgste7k9hx0qftg6qmwlkqtwuy6cycyavzmzj85c6qdfhjdpdjtdgqjuexzk6murw56suy3e0rd2cgqvycxttddwsvgxe2usfpxumr70xc9pkqwv" + ], + "outputs": [ + { + "pub_key": "64f1c7e8992352d18cdbca600b9e1c3a6025050d56a3e1cc833222e4f3b59e18", + "priv_key_tweak": "96439446f13ddaab2c5bc5a59a08992fd9d33bf8563c8a1b362730f4dc022e30", + "signature": "3f6226feb9e4cafc0bdab8c9cfe085885308f3708c222bcec6cf26467685d897f51597abe39d1d279708e63513c7be23daed78607a98837060950493de188645" + } + ] + } + } + ] + } +] diff --git a/bip352-testsuite/run_bip352_tests.py b/bip352-testsuite/run_bip352_tests.py new file mode 100755 index 0000000000..d268848d5e --- /dev/null +++ b/bip352-testsuite/run_bip352_tests.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +import bech32m +import hashlib +import json +import secp256k1_glue + +def sha256(s): + return hashlib.sha256(s).digest() + +def calculate_outpoints_hash(outpoints): + serialized_outpoints = [bytes.fromhex(txid)[::-1] + n.to_bytes(4, 'little') for txid, n in outpoints] + return sha256(b"".join(sorted(serialized_outpoints))) + +def decode_silent_payments_address(address): + version, data = bech32m.decode("sp", address) + data = bytes(data) # convert from list to bytes + assert len(data) == 66 + return data[:33], data[33:] + +with open('./bip352-send_and_receive_test_vectors.json') as f: + test_vectors = json.load(f) + +passed_send, passed_receive = 0, 0 +for test_nr, test_vector in enumerate(test_vectors): + print(f"----- Test vector: \'{test_vector['comment']}\' {test_nr+1}/{len(test_vectors)} -----") + ###################### sending ######################### + assert len(test_vector['sending']) == 1 + send_data_given = test_vector['sending'][0]['given'] + send_data_expected = test_vector['sending'][0]['expected'] + input_priv_keys = send_data_given['input_priv_keys'] + outpoints_hash = calculate_outpoints_hash(send_data_given['outpoints']) + outputs_calculated = [] + + groups = {} + for recipient_address, recipient_value in send_data_given['recipients']: + recipient_B_scan, recipient_B_spend = decode_silent_payments_address(recipient_address) + groups.setdefault(recipient_B_scan, []).append((recipient_B_spend, recipient_value)) + + for recipient_B_scan, recipient_spend_data in groups.items(): + plain_seckeys, xonly_seckeys = [], [] + for seckey_hex, is_taproot in input_priv_keys: + (xonly_seckeys if is_taproot else plain_seckeys).append(bytes.fromhex(seckey_hex)) + tweak_data = secp256k1_glue.silentpayments_create_private_tweak_data( + plain_seckeys, xonly_seckeys, outpoints_hash) + shared_secret = secp256k1_glue.silentpayments_send_create_shared_secret(tweak_data, recipient_B_scan) + k = 0 + for recipient_B_spend in recipient_spend_data: + output = secp256k1_glue.silentpayments_create_output_pubkey(shared_secret, recipient_B_spend[0], k) + outputs_calculated.append(output.hex()) + k += 1 + outputs_expected = [o[0] for o in send_data_expected['outputs']] + if outputs_calculated == outputs_expected: + print("Sending test \033[0;32mPASSED. ✓\033[0m") + passed_send += 1 + else: + print("Sending test \033[0;31mFAILED. ✖\033[0m") + print(f"Calculated outputs: {outputs_calculated}") + print(f"Expected outputs: {outputs_expected}") + + ###################### receiving ######################## + assert len(test_vector['receiving']) >= 1 + if test_vector['receiving'][0]['supports_labels']: + print("Receiving test SKIPPED. (labels are not implemented yet)") + continue + for subtest_nr, receive_data in enumerate(test_vector['receiving']): + receive_data_given = receive_data['given'] + receive_data_expected = receive_data['expected'] + # test data sanity check: outpoints hashes of send and receive has to match + receive_outpoints_hash = calculate_outpoints_hash(receive_data_given['outpoints']) + assert outpoints_hash == receive_outpoints_hash + # derive tweak_data and shared_secret + plain_pubkeys, xonly_pubkeys = [], [] + for pubkey in receive_data_given['input_pub_keys']: + pubkey = bytes.fromhex(pubkey) + if len(pubkey) == 32: + xonly_pubkeys.append(pubkey) + elif len(pubkey) == 33: + plain_pubkeys.append(pubkey) + else: + assert False + tweak_data = secp256k1_glue.silentpayments_create_tweak_data(plain_pubkeys, xonly_pubkeys, outpoints_hash) + scan_privkey = bytes.fromhex(receive_data_given['scan_priv_key']) + spend_privkey = bytes.fromhex(receive_data_given['spend_priv_key']) + # spend pubkey is not in the given data of the receiver part, so let's compute it + scan_pubkey = secp256k1_glue.pubkey_serialize((secp256k1_glue.pubkey_create(scan_privkey))) + spend_pubkey = secp256k1_glue.pubkey_serialize((secp256k1_glue.pubkey_create(spend_privkey))) + shared_secret = secp256k1_glue.silentpayments_receive_create_shared_secret(tweak_data, scan_privkey) + outputs_pubkeys_expected = [o['pub_key'] for o in receive_data_expected['outputs']] + outputs_privkeys_expected = [o['priv_key_tweak'] for o in receive_data_expected['outputs']] + outputs_scanned = [] + outputs_k_values = [] + + # scan through outputs + k = 0 + while True: + output_pubkey = secp256k1_glue.silentpayments_create_output_pubkey(shared_secret, spend_pubkey, k) + continue_scan = False + for output_given in receive_data_given['outputs']: + if bytes.fromhex(output_given) == output_pubkey: + outputs_scanned.append(output_given) + outputs_k_values.append(k) + continue_scan = True + if not continue_scan: + break + k += 1 + + all_subtests_passed = True + if outputs_scanned == outputs_pubkeys_expected: + print(f"Receiving sub-test [output pubkey] {subtest_nr+1}/{len(test_vector['receiving'])} \033[0;32mPASSED. ✓\033[0m") + else: + print(f"Receiving sub-test [output pubkey] {subtest_nr+1}/{len(test_vector['receiving'])} \033[0;31mFAILED. ✖\033[0m") + print(f"Scanned output pubkeys: {outputs_scanned}") + print(f"Expected outputs pubkeys: {outputs_expected}") + all_subtests_passed = False + + # check if output spending key also matches + outputs_privkeys = [] + for k in outputs_k_values: + output_privkey = secp256k1_glue.silentpayments_create_output_seckey(shared_secret, spend_privkey, k) + # a bit hacky: subtract the receiver spend key from the output privkey to get the expected tweak + privkey_tweak = secp256k1_glue.seckey_subtract(output_privkey, spend_privkey) + outputs_privkeys.append(privkey_tweak.hex()) + + if outputs_privkeys == outputs_privkeys_expected: + print(f"Receiving sub-test [output privkey] {subtest_nr+1}/{len(test_vector['receiving'])} \033[0;32mPASSED. ✓\033[0m") + else: + print(f"Receiving sub-test [output privkey] {subtest_nr+1}/{len(test_vector['receiving'])} \033[0;31mFAILED. ✖\033[0m") + print(f"Calculated output privkeys: {outputs_privkeys}") + print(f"Expected outputs privkeys: {outputs_privkeys_expected}") + all_subtests_passed = False + + if all_subtests_passed: + print("Receiving test \033[0;32mPASSED. ✓\033[0m") + passed_receive += 1 + else: + print("Receiving test \033[0;31mFAILED. ✖\033[0m") + +print( "+=================================+") +print( "| Summary: |") +print( "+---------------------------------+") +print(f"| {passed_send}/{len(test_vectors)} sending tests passed. |") +print(f"| {passed_receive}/{len(test_vectors)} receiving tests passed. |") +print( "+=================================+") diff --git a/bip352-testsuite/secp256k1_glue.py b/bip352-testsuite/secp256k1_glue.py new file mode 100644 index 0000000000..52edeba19b --- /dev/null +++ b/bip352-testsuite/secp256k1_glue.py @@ -0,0 +1,278 @@ +from ctypes import * +import os + +secplib = CDLL('../.libs/libsecp256k1.so') +secplib.secp256k1_context_create.restype = c_voidp +secp_context = secplib.secp256k1_context_create(1) + +################################## +### API calls from secp256k1.h ### +################################## +SECP256K1_PUBKEY_STRUCT_SIZE = 64 +""" +int secp256k1_ec_pubkey_create( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, + const unsigned char *seckey +); +""" +secplib.secp256k1_ec_pubkey_create.argtypes = [c_voidp, c_voidp, c_voidp] +secplib.secp256k1_ec_pubkey_create.restype = c_int +def pubkey_create(privkey_bytes): + pk = create_string_buffer(SECP256K1_PUBKEY_STRUCT_SIZE) + retval = secplib.secp256k1_ec_pubkey_create(secp_context, pk, privkey_bytes) + assert retval == 1 + return pk + +""" +int secp256k1_ec_pubkey_parse( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, + const unsigned char *input, + size_t inputlen +); +""" +secplib.secp256k1_ec_pubkey_parse.argtypes = [c_voidp, c_voidp, c_voidp, c_size_t] +secplib.secp256k1_ec_pubkey_parse.restype = c_int +def pubkey_parse(pubkey_bytes): + pk = create_string_buffer(SECP256K1_PUBKEY_STRUCT_SIZE) + retval = secplib.secp256k1_ec_pubkey_parse(secp_context, pk, pubkey_bytes, 33) + assert retval == 1 + return pk + +""" +int secp256k1_ec_pubkey_serialize( + const secp256k1_context *ctx, + unsigned char *output, + size_t *outputlen, + const secp256k1_pubkey *pubkey, + unsigned int flags +); +""" +secplib.secp256k1_ec_pubkey_serialize.argtypes = [c_voidp, c_voidp, c_voidp, c_voidp, c_uint] +secplib.secp256k1_ec_pubkey_serialize.restype = c_int +def pubkey_serialize(pubkey_obj): + ser_pubkey = create_string_buffer(33) + ser_pubkey_size = c_size_t(33) + retval = secplib.secp256k1_ec_pubkey_serialize(secp_context, + ser_pubkey, pointer(ser_pubkey_size), pubkey_obj, (1 << 1) | (1 << 8)) + assert retval == 1 + return bytes(ser_pubkey) + +""" +int secp256k1_ec_seckey_negate( + const secp256k1_context *ctx, + unsigned char *seckey +); +int secp256k1_ec_seckey_tweak_add( + const secp256k1_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +); +""" +secplib.secp256k1_ec_seckey_negate.argtypes = [c_voidp, c_voidp] +secplib.secp256k1_ec_seckey_negate.restype = c_int +secplib.secp256k1_ec_seckey_tweak_add.argtypes = [c_voidp, c_voidp] +secplib.secp256k1_ec_seckey_tweak_add.restype = c_int +def seckey_subtract(seckey_lhs, seckey_rhs): + seckey_to_sub = create_string_buffer(seckey_rhs, 32) + retval = secplib.secp256k1_ec_seckey_negate(secp_context, seckey_to_sub) + assert retval == 1 + seckey_result = create_string_buffer(seckey_lhs, 32) + retval = secplib.secp256k1_ec_seckey_tweak_add(secp_context, seckey_result, seckey_to_sub) + assert retval == 1 + return bytes(seckey_result) + +############################################ +### API calls from secp256k1_extrakeys.h ### +############################################ +SECP256K1_XONLY_PUBKEY_STRUCT_SIZE = 64 +""" +int secp256k1_xonly_pubkey_parse( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *pubkey, + const unsigned char *input32 +); +""" +secplib.secp256k1_xonly_pubkey_parse.argtypes = [c_voidp, c_voidp, c_voidp] +secplib.secp256k1_xonly_pubkey_parse.restype = c_int +def xonly_pubkey_parse(xonly_pubkey_bytes): + xpk = create_string_buffer(SECP256K1_XONLY_PUBKEY_STRUCT_SIZE) + retval = secplib.secp256k1_xonly_pubkey_parse(secp_context, xpk, xonly_pubkey_bytes) + assert retval == 1 + return xpk + +""" +secp256k1_xonly_pubkey_serialize( + const secp256k1_context *ctx, + unsigned char *output32, + const secp256k1_xonly_pubkey *pubkey +); +""" +secplib.secp256k1_xonly_pubkey_serialize.argtypes = [c_voidp, c_voidp, c_voidp] +secplib.secp256k1_xonly_pubkey_serialize.restype = c_int +def xonly_pubkey_serialize(xpubkey_obj): + ser_xpubkey = create_string_buffer(32) + retval = secplib.secp256k1_xonly_pubkey_serialize(secp_context, ser_xpubkey, xpubkey_obj) + assert retval == 1 + return bytes(ser_xpubkey) + +################################################# +### API calls from secp256k1_silentpayments.h ### +################################################# +""" +int secp256k1_silentpayments_create_private_tweak_data( + const secp256k1_context *ctx, + unsigned char *tweak_data32, + const unsigned char *plain_seckeys, + size_t n_plain_seckeys, + const unsigned char *taproot_seckeys, + size_t n_taproot_seckeys, + const unsigned char *outpoints_hash32 +); +""" +secplib.secp256k1_silentpayments_create_private_tweak_data.argtypes = [ + c_voidp, c_voidp, c_voidp, c_size_t, c_voidp, c_size_t, c_voidp +] +secplib.secp256k1_silentpayments_send_create_shared_secret.restype = c_int +def silentpayments_create_private_tweak_data(plain_seckeys, xonly_seckeys, outpoints_hash): + ser_plain_seckeys = b''.join(plain_seckeys) + if len(ser_plain_seckeys) == 0: ser_plain_seckeys = None + ser_xonly_seckeys = b''.join(xonly_seckeys) + if len(ser_xonly_seckeys) == 0: ser_xonly_seckeys = None + + result_tweak_data = create_string_buffer(32) + retval = secplib.secp256k1_silentpayments_create_private_tweak_data( + secp_context, result_tweak_data, ser_plain_seckeys, len(plain_seckeys), + ser_xonly_seckeys, len(xonly_seckeys), outpoints_hash) + assert retval == 1 + + return bytes(result_tweak_data) + +""" +int secp256k1_silentpayments_send_create_shared_secret( + const secp256k1_context *ctx, + unsigned char *shared_secret33, + const unsigned char *tweak_data32, + const secp256k1_pubkey *receiver_scan_pubkey +); +""" +secplib.secp256k1_silentpayments_send_create_shared_secret.argtypes = [ + c_voidp, c_voidp, c_voidp, c_voidp +] +secplib.secp256k1_silentpayments_send_create_shared_secret.restype = c_int +def silentpayments_send_create_shared_secret(tweak_data, receiver_scan_pubkey): + # convert receiver pubkey to secp256k1 object + receiver_scan_pubkey_obj = pubkey_parse(receiver_scan_pubkey) + + result_shared_secret = create_string_buffer(33) + retval = secplib.secp256k1_silentpayments_send_create_shared_secret( + secp_context, result_shared_secret, tweak_data, receiver_scan_pubkey_obj) + assert retval == 1 + + return bytes(result_shared_secret) + +""" +int secp256k1_silentpayments_create_public_tweak_data( + const secp256k1_context *ctx, + unsigned char *tweak_data33, + const secp256k1_pubkey *plain_pubkeys, + size_t n_plain_pubkeys, + const secp256k1_xonly_pubkey *xonly_pubkeys, + size_t n_xonly_pubkeys, + const unsigned char *outpoints_hash32 +); +""" +secplib.secp256k1_silentpayments_create_public_tweak_data.argtypes = [ + c_voidp, c_voidp, c_voidp, c_size_t, c_voidp, c_size_t, c_voidp +] +secplib.secp256k1_silentpayments_create_public_tweak_data.restype = c_int +def silentpayments_create_tweak_data(plain_pubkeys, xonly_pubkeys, outpoints_hash): + # convert raw plain pubkeys to secp256k1 pubkeys and concatenate them + ser_plain_pubkeys = b'' + for plain_pubkey in plain_pubkeys: + ser_plain_pubkeys += pubkey_parse(plain_pubkey) + if len(ser_plain_pubkeys) == 0: ser_plain_pubkeys = None + # convert raw x-only pubkeys to secp256k1 x-only pubkeys and concatenate them + ser_xonly_pubkeys = b'' + for xonly_pubkey in xonly_pubkeys: + ser_xonly_pubkeys += xonly_pubkey_parse(xonly_pubkey) + if len(ser_xonly_pubkeys) == 0: ser_xonly_pubkeys = None + + result_tweak_data = create_string_buffer(33) + retval = secplib.secp256k1_silentpayments_create_public_tweak_data( + secp_context, result_tweak_data, ser_plain_pubkeys, len(plain_pubkeys), + ser_xonly_pubkeys, len(xonly_pubkeys), outpoints_hash) + assert retval == 1 + + return bytes(result_tweak_data) + +""" +int secp256k1_silentpayments_receive_create_shared_secret( + const secp256k1_context *ctx, + unsigned char *shared_secret33, + const unsigned char *tweak_data33, + const unsigned char *receiver_scan_seckey +); +""" +secplib.secp256k1_silentpayments_receive_create_shared_secret.argtypes = [ + c_voidp, c_voidp, c_voidp, c_voidp +] +secplib.secp256k1_silentpayments_receive_create_shared_secret.restype = c_int +def silentpayments_receive_create_shared_secret(tweak_data, receiver_scan_seckey): + result_shared_secret = create_string_buffer(33) + retval = secplib.secp256k1_silentpayments_receive_create_shared_secret( + secp_context, result_shared_secret, tweak_data, receiver_scan_seckey) + assert retval == 1 + return bytes(result_shared_secret) + +""" +int secp256k1_silentpayments_create_output_pubkey( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *output_xonly_pubkey, + const unsigned char *shared_secret33, + const secp256k1_pubkey *receiver_spend_pubkey, + unsigned int k, + const unsigned char *label_tweak32 +); +""" +secplib.secp256k1_silentpayments_create_output_pubkey.argtypes = [ + c_voidp, c_voidp, c_voidp, c_voidp, c_uint, c_voidp +] +secplib.secp256k1_silentpayments_create_output_pubkey.restype = c_int +def silentpayments_create_output_pubkey(shared_secret, receiver_spend_pubkey, k): + result_xpubkey = create_string_buffer(SECP256K1_XONLY_PUBKEY_STRUCT_SIZE) + # convert receiver pubkey to secp256k1 object + receiver_spend_pubkey_obj = pubkey_parse(receiver_spend_pubkey) + + retval = secplib.secp256k1_silentpayments_create_output_pubkey( + secp_context, result_xpubkey, shared_secret, receiver_spend_pubkey_obj, k, None) + assert retval == 1 + + # serialize and return resulting x-only pubkey + output = create_string_buffer(32) + retval = secplib.secp256k1_xonly_pubkey_serialize(secp_context, output, result_xpubkey) + assert retval == 1 + + return bytes(output) + +""" +int secp256k1_silentpayments_create_output_seckey( + const secp256k1_context *ctx, + unsigned char *output_seckey, + const unsigned char *shared_secret33, + const unsigned char *receiver_spend_seckey, + unsigned int k, + const unsigned char *label_tweak32 +); +""" +secplib.secp256k1_silentpayments_create_output_seckey.argtypes = [ + c_voidp, c_voidp, c_voidp, c_voidp, c_uint, c_voidp +] +secplib.secp256k1_silentpayments_create_output_seckey.restype = c_int +def silentpayments_create_output_seckey(shared_secret, receiver_spend_seckey, k): + result_seckey = create_string_buffer(32) + retval = secplib.secp256k1_silentpayments_create_output_seckey( + secp_context, result_seckey, shared_secret, receiver_spend_seckey, k, None) + assert retval == 1 + return bytes(result_seckey)