Esempio n. 1
0
    def test_pubpoint(self):
        # write a test that tests the public point for the following
        points = (
            # secret, x, y
            (
                7,
                "045CBDF0646E5DB4EAA398F365F2EA7A0E3D419B7E0330E39CE92BDDEDCAC4F9BC6AEBCA40BA255960A3178D6D861A54DBA813D0B813FDE7B5A5082628087264DA",
            ),
            (
                1485,
                "04C982196A7466FBBBB0E27A940B6AF926C1A74D5AD07128C82824A11B5398AFDA7A91F9EAE64438AFB9CE6448A1C133DB2D8FB9254E4546B6F001637D50901F55",
            ),
            (
                2**128,
                "048F68B9D2F63B5F339239C1AD981F162EE88C5678723EA3351B7B444C9EC4C0DA662A9F2DBA063986DE1D90C2B6BE215DBBEA2CFE95510BFDF23CBF79501FFF82",
            ),
            (
                2**240 + 2**31,
                "049577FF57C8234558F293DF502CA4F09CBC65A6572C842B39B366F2171794511610B49C67FA9365AD7B90DAB070BE339A1DAF9052373EC30FFAE4F72D5E66D053",
            ),
        )

        # iterate over points
        sum_secrets = 0
        point_objects = []
        for secret, sec in points:
            # initialize the secp256k1 point (S256Point)
            point = S256Point.parse(bytes.fromhex(sec))
            # check that the secret*G is the same as the point
            self.assertEqual(secret * G, point)
            sum_secrets += secret
            point_objects.append(point)

        self.assertEqual(sum_secrets * G, S256Point.combine(point_objects))
Esempio n. 2
0
 def test_p2tr_empty_script_tree(self):
     tests = [
         {
             "given": {
                 "internalPubkey": "d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d",
             },
             "intermediary": {
                 "tweak": "b86e7be8f39bab32a6f2c0443abbc210f0edac0e2c53d501b36b64437d9c6c70",
                 "tweakedPubkey": "53a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
             },
             "expected": {
                 "scriptPubKey": "512053a1f6e454df1aa2776a2814a721372d6258050de330b3c6d10ee8f4e0dda343",
                 "bip350Address": "bc1p2wsldez5mud2yam29q22wgfh9439spgduvct83k3pm50fcxa5dps59h4z5",
             },
         },
     ]
     for test in tests:
         point = S256Point.parse_bip340(
             bytes.fromhex(test["given"]["internalPubkey"])
         )
         raw_tweak = bytes.fromhex(test["intermediary"]["tweak"])
         tap_root = TapRoot(point)
         self.assertEqual(tap_root.tweak, big_endian_to_int(raw_tweak))
         tweak_point_want = S256Point.parse_bip340(
             bytes.fromhex(test["intermediary"]["tweakedPubkey"])
         )
         self.assertEqual(tap_root.bip340(), tweak_point_want.bip340())
         stream = BytesIO(
             encode_varstr(bytes.fromhex(test["expected"]["scriptPubKey"]))
         )
         script_pubkey_want = ScriptPubKey.parse(stream)
         self.assertEqual(tap_root.script_pubkey(), script_pubkey_want)
         self.assertEqual(tap_root.address(), test["expected"]["bip350Address"])
Esempio n. 3
0
 def __init__(self, points, locktime=None, sequence=None):
     if locktime is not None and sequence is not None:
         raise ValueError(
             "Both locktime and sequence are defined. Only one of them should be."
         )
     super().__init__()
     if len(points) == 0:
         raise ValueError("Need at least one public key")
     bip340s = sorted([p.bip340() for p in points])
     self.points = [S256Point.parse_bip340(b) for b in bip340s]
     self.commitment = hash_keyagglist(b"".join(bip340s))
     self.coefs = [
         big_endian_to_int(hash_keyaggcoef(self.commitment + b))
         for b in bip340s
     ]
     # the second unique public key has a coefficient of 1
     self.coefs[1] = 1
     self.coef_lookup = {b: c for c, b in zip(self.coefs, bip340s)}
     # aggregate point
     self.point = S256Point.combine(
         [c * p for c, p in zip(self.coefs, self.points)])
     if locktime is not None:
         self.commands = locktime_commands(locktime)
     elif sequence is not None:
         self.commands = sequence_commands(sequence)
     else:
         self.commands = []
     self.commands += [self.point.bip340(), 0xAC]
Esempio n. 4
0
 def test_parse(self):
     csec = bytes.fromhex(
         "0349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a"
     )
     point = S256Point.parse(csec)
     usec = bytes.fromhex(
         "0449fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278aa56c896489c71dfc65701ce25050f542f336893fb8cd15f4e8e5c124dbf58e47"
     )
     self.assertEqual(point.sec(False), usec)
Esempio n. 5
0
 def test_signing(self):
     tests = [
         (
             "0",
             "0000000000000000000000000000000000000000000000000000000000000003",
             "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
             "0000000000000000000000000000000000000000000000000000000000000000",
             "0000000000000000000000000000000000000000000000000000000000000000",
             "E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0",
             "",
         ),
         (
             "1",
             "B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF",
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "0000000000000000000000000000000000000000000000000000000000000001",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A",
             "",
         ),
         (
             "2",
             "C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9",
             "DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8",
             "C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906",
             "7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C",
             "5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB745879A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7",
             "",
         ),
         (
             "3",
             "0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710",
             "25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517",
             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
             "7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3",
             "test fails if msg is reduced modulo p or n",
         ),
     ]
     for (
             index,
             secret,
             bip340_pk,
             aux_rand,
             message,
             signature,
             comment,
     ) in tests:
         private_key = PrivateKey(secret=int(secret, 16))
         public_key = S256Point.parse(bytes.fromhex(bip340_pk))
         aux = bytes.fromhex(aux_rand)
         msg = bytes.fromhex(message)
         want_sig = SchnorrSignature.parse(bytes.fromhex(signature))
         self.assertTrue(public_key.verify_schnorr(msg, want_sig))
         sig = private_key.sign_schnorr(msg, aux)
         self.assertEqual(sig, want_sig)
Esempio n. 6
0
 def test_hd(self):
     point = S256Point.parse_bip340(
         bytes.fromhex(
             "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115"
         )
     )
     t = TapRoot(point)
     self.assertEqual(
         t.tweak_point.bip340().hex(),
         "a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c",
     )
Esempio n. 7
0
 def parse(cls, b):
     b_len = len(b)
     if b_len % 32 != 1:
         raise ValueError(
             "There should be 32*m+1 bytes where m is an integer")
     if b_len < 33 or b_len > 33 + 128 * 32:
         raise ValueError(f"length is outside the bounds {b_len}")
     tapleaf_version = b[0] & 0xFE
     parity = b[0] & 1
     internal_pubkey = S256Point.parse_bip340(b[1:33])
     m = (b_len - 33) // 32
     hashes = [b[33 + 32 * i:65 + 32 * i] for i in range(m)]
     return cls(tapleaf_version, parity, internal_pubkey, hashes)
Esempio n. 8
0
 def __init__(self, internal_pubkey, tap_node=None, merkle_root=None):
     self.internal_pubkey = S256Point.parse_bip340(internal_pubkey.bip340())
     self.tap_node = tap_node
     if merkle_root is not None:
         self.tweak = big_endian_to_int(
             hash_taptweak(internal_pubkey.bip340() + merkle_root))
     elif tap_node is None:
         self.tweak = big_endian_to_int(
             hash_taptweak(internal_pubkey.bip340()))
     else:
         self.tweak = big_endian_to_int(
             hash_taptweak(internal_pubkey.bip340() + tap_node.hash()))
     self.tweak_point = self.internal_pubkey + self.tweak
     self.parity = self.tweak_point.parity
Esempio n. 9
0
 def test_verify(self):
     tests = [
         (
             "D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9",
             "4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703",
             "00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB1548AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4",
         ),
         (
             "d0fa46cb883e940ac3dc5421f05b03859972639f51ed2eccbf3dc5a62e2e1b15",
             "11864b0142c248fdb090d08893745e0b36a78f988a8334d2056814ad5f541596",
             "23b1d4ff27b16af4b0fcb9672df671701a1a7f5a6bb7352b051f461edbc614aa6068b3e5313a174f90f3d95dc4e06f69bebd9cf5a3098fde034b01e69e8e7889",
         ),
     ]
     for bip340_pk, message, signature in tests:
         public_key = S256Point.parse(bytes.fromhex(bip340_pk))
         msg = bytes.fromhex(message)
         sig = SchnorrSignature.parse(bytes.fromhex(signature))
         self.assertTrue(public_key.verify_schnorr(msg, sig))
Esempio n. 10
0
def op_checkmultisig(stack, tx_obj, input_index):
    if len(stack) < 1:
        return False
    n = decode_num(stack.pop())
    if len(stack) < n + 1:
        return False
    sec_pubkeys = []
    for _ in range(n):
        sec_pubkeys.append(stack.pop())
    m = decode_num(stack.pop())
    if len(stack) < m + 1:
        return False
    der_signatures = []
    for _ in range(m):
        tmp = stack.pop()
        der, hash_type = tmp[:-1], tmp[-1]
        der_signatures.append((der, hash_type))
    # OP_CHECKMULTISIG bug
    stack.pop()
    try:
        # parse the sec pubkeys into an array of points
        points = [S256Point.parse(sec) for sec in sec_pubkeys]
        # loop through the signatures
        for der_signature, hash_type in der_signatures:
            sig = Signature.parse(der_signature)
            z = tx_obj.sig_hash(input_index, hash_type)
            # bail early if we don't have any points left
            if len(points) == 0:
                print("signatures no good or not in right order")
                return False
            # while we have points
            while points:
                # get the point at the front (points.pop(0))
                point = points.pop(0)
                # see if this point can verify this sig with this z
                if point.verify(z, sig):
                    # break if so, this sig is valid!
                    break
        # if we made it this far, we have to add a 1 to the stack
        # use encode_num(1)
        stack.append(encode_num(1))
    except (ValueError, SyntaxError):
        return False
    return True
Esempio n. 11
0
def op_checksig(stack, tx_obj, input_index):
    # check to see if there's at least 2 elements
    if len(stack) < 2:
        return False
    # get the sec_pubkey with stack.pop()
    sec_pubkey = stack.pop()
    # get the der_signature with stack.pop()[:-1] (last byte is removed)
    tmp = stack.pop()
    der_signature, hash_type = tmp[:-1], tmp[-1]
    # parse the sec format pubkey with S256Point
    point = S256Point.parse(sec_pubkey)
    # parse the der format signature with Signature
    sig = Signature.parse(der_signature)
    z = tx_obj.sig_hash(input_index, hash_type)
    # verify using the point, z and signature
    # if verified add encode_num(1) to the end, otherwise encode_num(0)
    if point.verify(z, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Esempio n. 12
0
 def test_verify(self):
     tests = (
         (
             0xEC208BAA0FC1C19F708A9CA96FDEFF3AC3F230BB4A7BA4AEDE4942AD003C0F60,
             "3045022100ac8d1c87e51d0d441be8b3dd5b05c8795b48875dffe00b7ffcfac23010d3a3950220068342ceff8935ededd102dd876ffd6ba72d6a427a3edb13d26eb0781cb423c4",
             "04887387e452b8eacc4acfde10d9aaf7f6d9a0f975aabb10d006e4da568744d06c61de6d95231cd89026e286df3b6ae4a894a3378e393e93a0f45b666329a0ae34",
         ),
         (
             0x7C076FF316692A3D7EB3C3BB0F8B1488CF72E1AFCD929E29307032997A838A3D,
             "3044022000eff69ef2b1bd93a66ed5219add4fb51e11a840f404876325a1e8ffe0529a2c022038df8011e682d839e75159debf909408cb3f12ae472b1d88cf6280cf01c6568b",
             "04887387e452b8eacc4acfde10d9aaf7f6d9a0f975aabb10d006e4da568744d06c61de6d95231cd89026e286df3b6ae4a894a3378e393e93a0f45b666329a0ae34",
         ),
         (
             0x2270CB0316E68389A3A23DE16023A03B8FC271A21B467B1DC97E0FC0E2CE97F7,
             "3045022100ea6d640d5275d091607e1f4ad5cdb214e45f8d17cca1095074894dde347605ba022029062e1ff0d9eee52da1f3621caf92436877d7076720e2b3d9f226bf853e2b75",
             "04f47dc2ac0ecaadda5ee2b3ab9bc4e02c3eafb2abcc426643686ad95f6d4e8c44e33fa47d96fc2dace0ef2f583965cf6a0f8faa7a070c0f8ee986d192e2d21835",
         ),
     )
     for z, der_hex, sec in tests:
         point = S256Point.parse(bytes.fromhex(sec))
         der = bytes.fromhex(der_hex)
         self.assertTrue(point.verify(z, Signature.parse(der)))
Esempio n. 13
0
def op_checksig_schnorr(stack, tx_obj, input_index):
    # check to see if there's at least 2 elements
    if len(stack) < 2:
        return False
    pubkey = stack.pop()
    signature = stack.pop()
    point = S256Point.parse_bip340(pubkey)
    if len(signature) == 65:
        hash_type = signature[-1]
        signature = signature[:-1]
    elif len(signature) == 0:
        stack.append(encode_num(0))
        return True
    else:
        hash_type = 0
    sig = SchnorrSignature.parse(signature)
    msg = tx_obj.sig_hash(input_index, hash_type)
    if point.verify_schnorr(msg, sig):
        stack.append(encode_num(1))
    else:
        stack.append(encode_num(0))
    return True
Esempio n. 14
0
 def __init__(self, points, k, locktime=None, sequence=None):
     if locktime is not None and sequence is not None:
         raise ValueError(
             "Both locktime and sequence are defined. Only one of them should be."
         )
     super().__init__()
     if len(points) == 0:
         raise ValueError(
             "To initialize MultiSigTapScript at least one point")
     bip340s = sorted([p.bip340() for p in points])
     self.points = [S256Point.parse_bip340(b) for b in bip340s]
     if locktime is not None:
         self.commands = locktime_commands(locktime)
     elif sequence is not None:
         self.commands = sequence_commands(sequence)
     else:
         self.commands = []
     self.commands += [bip340s[0], 0xAC]
     if len(points) > 1:
         for bip340 in bip340s[1:]:
             self.commands += [bip340, 0xBA]
         self.commands += [number_to_op_code(k), 0x87]
Esempio n. 15
0
    def test_p2tr_general(self):
        tests = [
            {
                "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",
                    ],
                },
            },
        ]

        def parse_item(item):
            if type(item) == dict:
                tapleaf_version = item["leafVersion"]
                tap_script = Script.parse(
                    BytesIO(encode_varstr(bytes.fromhex(item["script"])))
                )
                tap_leaf = TapLeaf(tap_script, tapleaf_version)
                return tap_leaf
            else:
                return TapBranch(parse_item(item[0]), parse_item(item[1]))

        for test in tests:
            point = S256Point.parse_bip340(
                bytes.fromhex(test["given"]["internalPubkey"])
            )
            tap_tree = parse_item(test["given"]["scriptTree"])
            merkle_root = tap_tree.hash()
            merkle_root_want = bytes.fromhex(test["intermediary"]["merkleRoot"])
            self.assertEqual(merkle_root, merkle_root_want)
            tap_root = TapRoot(point, tap_tree)
            raw_tweak = bytes.fromhex(test["intermediary"]["tweak"])
            self.assertEqual(tap_root.tweak, big_endian_to_int(raw_tweak))
            tweak_point_want = S256Point.parse_bip340(
                bytes.fromhex(test["intermediary"]["tweakedPubkey"])
            )
            self.assertEqual(tap_root.bip340(), tweak_point_want.bip340())
            stream = BytesIO(
                encode_varstr(bytes.fromhex(test["expected"]["scriptPubKey"]))
            )
            script_pubkey_want = ScriptPubKey.parse(stream)
            self.assertEqual(tap_root.script_pubkey(), script_pubkey_want)
            self.assertEqual(tap_root.address(), test["expected"]["bip350Address"])
            control_blocks = test["expected"]["scriptPathControlBlocks"]
            leaf_hashes = test["intermediary"]["leafHashes"]
            for control_block_hex, tap_leaf, leaf_hash in zip(
                control_blocks, tap_tree.leaves(), leaf_hashes
            ):
                self.assertEqual(tap_leaf.hash(), bytes.fromhex(leaf_hash))
                control_block_raw = bytes.fromhex(control_block_hex)
                control_block_want = ControlBlock.parse(control_block_raw)
                control_block = tap_root.control_block(tap_leaf)
                self.assertEqual(control_block, control_block_want)
                self.assertEqual(
                    tap_leaf.tapleaf_version, control_block.tapleaf_version
                )
                self.assertEqual(tap_root.parity, control_block.parity)
                self.assertEqual(control_block.serialize(), control_block_raw)
                self.assertEqual(control_block.internal_pubkey, point)
                self.assertEqual(control_block.merkle_root(tap_leaf), merkle_root)
                self.assertEqual(control_block.tweak(tap_leaf), raw_tweak)
Esempio n. 16
0
 def test_errors(self):
     tests = [
         (
             "EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
             ValueError,
             "public key not on the curve",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC27944640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2",
             AssertionError,
             "has_even_y(R) is false",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD",
             AssertionError,
             "negated message",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6",
             AssertionError,
             "negated s value",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "0000000000000000000000000000000000000000000000000000000000000000123DDA8328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051",
             AssertionError,
             "sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 0",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "00000000000000000000000000000000000000000000000000000000000000017615FBAF5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197",
             AssertionError,
             "sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 1",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
             ValueError,
             "sig[0:32] is not an X coordinate on the curve",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
             ValueError,
             "sig[0:32] is equal to field size",
         ),
         (
             "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
             ValueError,
             "sig[32:64] is equal to curve order",
         ),
         (
             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30",
             "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89",
             "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
             ValueError,
             "public key is not a valid X coordinate because it exceeds the field size",
         ),
     ]
     for bip340_pk, message, signature, error, comment in tests:
         with self.assertRaises(error):
             print(comment)
             public_key = S256Point.parse(bytes.fromhex(bip340_pk))
             msg = bytes.fromhex(message)
             sig = SchnorrSignature.parse(bytes.fromhex(signature))
             assert public_key.verify_schnorr(msg, sig)
Esempio n. 17
0
 def compute_r(self, nonce_sums, sig_hash):
     h = self.compute_coefficient(nonce_sums, sig_hash)
     return S256Point.combine([nonce_sums[0], h * nonce_sums[1]])
Esempio n. 18
0
 def nonce_sums(self, nonce_point_pairs):
     sum_1 = S256Point.combine([n[0] for n in nonce_point_pairs])
     sum_2 = S256Point.combine([n[1] for n in nonce_point_pairs])
     return sum_1, sum_2