def op_checkmultisig(stack, z): 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): der_signatures.append(stack.pop()[:-1]) stack.pop() try: points = [S256Point.parse(sec) for sec in sec_pubkeys] sigs = [Signature.parse(der) for der in der_signatures] for sig in sigs: if len(points) == 0: return False while points: point = points.pop(0) if point.verify(z, sig): break stack.append(encode_num(1)) except (ValueError, SyntaxError): return False return True
def raw_parse(cls, s): '''Returns a HDPublicKey from a stream''' # first 4 bytes are the version version = s.read(4) # check that the version is one of the TESTNET or MAINNET # public keys, if not raise a ValueError if version in (TESTNET_XPUB, TESTNET_YPUB, TESTNET_ZPUB): testnet = True elif version in (MAINNET_XPUB, MAINNET_YPUB, MAINNET_ZPUB): testnet = False else: raise ValueError('not an xpub, ypub or zpub: {} {}'.format( s, version)) # the next byte is depth depth = byte_to_int(s.read(1)) # next 4 bytes are the parent_fingerprint parent_fingerprint = s.read(4) # next 4 bytes is the child number in big-endian child_number = big_endian_to_int(s.read(4)) # next 32 bytes are the chain code chain_code = s.read(32) # last 33 bytes should be the SEC point = S256Point.parse(s.read(33)) # return an instance of the class return cls( point=point, chain_code=chain_code, depth=depth, parent_fingerprint=parent_fingerprint, child_number=child_number, testnet=testnet, )
def test_example_4(self): sec = bytes.fromhex('0349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a') der = bytes.fromhex('3045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed') z = 0x27e0c5994dec7824e56dec6b2fcb342eb7cdb0d0957c2fce9882f715e85d81a6 point = S256Point.parse(sec) signature = Signature.parse(der) self.assertTrue(point.verify(z, signature))
def derive_pub_child(self, i): if i >= HARD_CAP: return ValueError("Chosen i is not in range [0, 2**32-1]") # Not quite sure if this is true # if int.from_bytes(self.child_num, 'big') >= SOFT_CAP: # raise TypeError("Hardened Public Keys cannot derive child keys. Use Extended Private key.") if i >= SOFT_CAP: raise TypeError( "Hardened Keys cannot be be derived from Extended Pub Keys. Use Extended Private key." ) else: ii = hmac.new(self.chaincode, self.key + i.to_bytes(4, 'big'), digestmod=sha512).digest() fingerprint = hash160(self.key)[:4] # edge case: invalid keys key_num = int.from_bytes(ii[:32], 'big') point = key_num * G if key_num >= N or point.x is None: raise ValueError(INVALID_KEY_MSG) child_key = point + S256Point.parse(self.key) child_chaincode = ii[32:] #assemble new xpub child_xpub = PUB_MAIN if self.testnet: child_xpub = PUB_TEST child_xpub += (self.depth[0] + 1).to_bytes(1, 'big') child_xpub += fingerprint child_xpub += i.to_bytes(4, 'big') child_xpub += child_chaincode child_xpub += child_key.sec() checksum = hash256(child_xpub)[:4] child_xpub += checksum return self.__class__(child_xpub)
def verify_input(self, input_index): '''Returns whether the input has a valid signature''' # get the relevant input tx_in = self.tx_ins[input_index] # get the number of signatures required. This is available in tx_in.script_sig.num_sigs_required() sigs_required = tx_in.script_sig.num_sigs_required() # iterate over the sigs required and check each signature for sig_num in range(sigs_required): # get the point from the sec format sec = tx_in.sec_pubkey(index=sig_num) # get the sec_pubkey at current signature index point = S256Point.parse(sec) # get the der sig and hash_type from input # get the der_signature at current signature index der, hash_type = tx_in.der_signature(index=sig_num) # get the signature from der format signature = Signature.parse(der) # get the hash to sign if tx_in.is_segwit(): h160 = hash160(tx_in.script_sig.redeem_script()) if h160 != tx_in.script_pubkey(self.testnet).elements[1]: return False pubkey_h160 = tx_in.script_sig.redeem_script()[-20:] if pubkey_h160 != point.h160(): return False z = self.sig_hash_bip143(input_index, hash_type) else: z = self.sig_hash(input_index, hash_type) # use point.verify on the hash to sign and signature if not point.verify(z, signature): return False return True
def test_exercise_2(self): der = bytes.fromhex( '304402201f62993ee03fca342fcb45929993fa6ee885e00ddad8de154f268d98f083991402201e1ca12ad140c04e0e022c38f7ce31da426b8009d02832f0b44f39a6b178b7a1' ) sec = bytes.fromhex( '0204519fac3d910ca7e7138f7013706f619fa8f033e6ec6e09370ea38cee6a7574' ) z = int.from_bytes(hash256(b'ECDSA is awesome!'), 'big') sig = Signature.parse(der) point = S256Point.parse(sec) self.assertTrue(point.verify(z, sig))
def op_checksig(stack, z): if len(stack) < 2: return False sec_pubkey = stack.pop() der_signature = stack.pop()[:-1] point = S256Point.parse(sec_pubkey) sig = Signature.parse(der_signature) if point.verify(z, sig): stack.append(encode_num(1)) else: stack.append(encode_num(0)) return True
def op_checkmultisig(stack, z): if len(stack) < 1: return False # n is the number of public keys n = decode_num(stack.pop()) if len(stack) < n + 1: return False # get all the public keys into a list. pubkeys = [] for _ in range(n): pubkeys.append(stack.pop()) if len(stack) < 1: return False # m is the number of signatures m = decode_num(stack.pop()) # m + 2 because of the additional element at the bottom of the stack that is added. if len(stack) < m + 1: return False # get all the signatures. signatures = [] for _ in range(m): # take off last byte, which is the hashtype signatures.append(stack.pop()[:-1]) if len(stack) < 1: return False # we remove the last element from the stack (the one included because the off by one error) stack.pop() # verify all the signatures against all pubkeys. If a signature isn't valid for any pubkeys, fail. try: sigs = [Signature.parse(signature) for signature in signatures] points = [S256Point.parse(pubkey) for pubkey in pubkeys] except (ValueError, SyntaxError) as e: LOGGER.info(e) return False # variable to count the number of valid signatures. count = 0 # in the next loop, we check that each signature is valid for a pubkey. while len(points) > 0: # point is popped so each signature can only be valid for 1 point. point = points.pop() for sig in sigs: # if the signature is valid for this pubkey, increase the count and break from the while # to check next signature. if point.verify(z, sig): count += 1 # if the number of valid signatures is m = each signature is valid for some pubkey, then script is valid. if count == m: stack.append(encode_num(1)) # else, script should fail. else: stack.append(encode_num(0)) return True
def connect_peer(host, port, node): sock = SocketClient(host, port) sock.connect() peer_address = sock.receive() sock.send(str.encode(node.address)) peer_pub_key = sock.receive() sock.send(node.public_key.sec()) peer_pub_key_point = S256Point.parse(peer_pub_key) peer_sym_key = node.secret * peer_pub_key_point return Peer(sock, peer_address, peer_pub_key_point, peer_sym_key)
def __init__(self, xpub): self.pfx = xpub[:4] self.depth = xpub[4:5] self.parent = xpub[5:9] self.child_num = xpub[9:13] self.chaincode = xpub[13:45] self.key = xpub[45:-4] self.checksum = xpub[-4:] if not self.check_sum(): raise ConfigurationError("Invalid Checksum for ExtendedPrivKey") try: #TODO use assert point = S256Point.parse(self.key) except ValueError: raise ConfigurationError("Point is not on the curve, invalid key.")
def listen_for_new_peer(host, port, node): sock = SocketServer(host, port) sock.listen() sock.send(str.encode(node.address)) peer_address = sock.receive() sock.send(node.public_key.sec()) peer_pub_key = sock.receive() peer_pub_key_point = S256Point.parse(peer_pub_key) peer_sym_key = node.secret * peer_pub_key_point return Peer(sock, peer_address, peer_pub_key_point, peer_sym_key)
def verify_input(self, input_index): '''Returns whether the input has a valid signature''' # get the relevant input tx_in = self.tx_ins[input_index] # parse the point from the sec format (tx_in.sec_pubkey()) point = S256Point.parse(tx_in.sec_pubkey()) # parse the signature from the der format (tx_in.der_signature()) signature = Signature.parse(tx_in.der_signature()) # get the hash type from the input (tx_in.hash_type()) hash_type = tx_in.hash_type() # get the sig_hash (z) z = self.sig_hash(input_index, hash_type) # use point.verify on the z and signature return point.verify(z, signature)
def op_checksig(stack, z): if len(stack) < 2: return False pub_sec = stack.pop() sig_der = stack.pop()[:-1] # except hash_type try: pub_point = S256Point.parse(pub_sec) sig = Signature.parse(sig_der) except (ValueError, SyntaxError) as e: return False if pub_point.verify(z, sig): stack.append(encode_num(1)) else: stack.append(encode_num(0)) return True
def test_example_5(self): h256 = hash256( bytes.fromhex( '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c56870000000001000000' )) z = int.from_bytes(h256, 'big') point = S256Point.parse( bytes.fromhex( '022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb70' )) sig = Signature.parse( bytes.fromhex( '3045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a89937' )) self.assertTrue(point.verify(z, sig))
def op_checksig(stack, z): if len(stack) < 2: return False sec_pubkey = stack.pop() der_signature = stack.pop()[:-1] try: point = S256Point.parse(sec_pubkey) sig = Signature.parse(der_signature) except (ValueError, SyntaxError) as e: return False if point.verify(z, sig): stack.append(encode_num(1)) else: stack.append(encode_num(0)) return True
def derive_child_seed(self, index_num): """ This function derives a child seed with provided index. Please note that an index >= 2**31 is a hardened index """ if self.private_key: pubkey = get_pubkey_sec(self.key) if index_num >= 2**31: data = b"\x00" + self.key + index_num.to_bytes(4, "big") else: data = pubkey + index_num.to_bytes(4, "big") else: pubkey = self.key if index_num >= 2**31: raise ValueError("Cannot use hardened index!") data = pubkey + index_num.to_bytes(4, "big") full_node = hmac.new(key=self.chaincode, msg=data, digestmod=sha512).digest() left_node = full_node[0:32] right_node = full_node[32:] left_node_num = int.from_bytes(left_node, "big") key_num = int.from_bytes(self.key, "big") if self.private_key: total = key_num + left_node_num total = total % N key = total.to_bytes(32, "big") else: key_point = S256Point.parse(self.key) left_point = left_node_num * G total = key_point + left_point key = total.sec() if self.root: depth = 1 else: depth = self.depth + 1 return self.__class__(key, right_node, self.private_key, root=False, depth=depth, index=index_num, parent_pubkey=pubkey)
def verify_input(self, input_index): '''Returns whether the input has a valid signature''' inp = self.tx_ins[input_index] sigs_required = inp.script_sig.num_sigs_required() for sig_num in range(sigs_required): # get the point from the sec format point = S256Point.parse(inp.sec_pubkey(index=sig_num)) # get the input signature der, sighash = inp.der_signature(index=sig_num) signature = Signature.parse(der) # get the hash to sign z = self.hash_to_sign(input_index, sighash) # verify the hash and signature are good if not point.verify(z, signature): return False return True
def test_exercise_3(self): hex_tx = '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000' hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb71' hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e754022' hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152ae' sec = bytes.fromhex(hex_sec) der = bytes.fromhex(hex_der) redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script))) stream = BytesIO(bytes.fromhex(hex_tx)) tx_obj = Tx.parse(stream) tx_obj.tx_ins[0].script_sig = redeem_script s = tx_obj.serialize() + int_to_little_endian(SIGHASH_ALL, 4) z = int.from_bytes(hash256(s), 'big') point = S256Point.parse(sec) sig = Signature.parse(der) self.assertTrue(point.verify(z, sig))
def op_checkmultisig(stack, z): 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): der_signatures.append(stack.pop()[:-1]) # <1> stack.pop() try: # <2> # end::source1[] # parse all the points # parse all the signatures # loop through the signatures # if we have no more points, signatures are no good # we loop until we find the point which works with this signature # get the current point from the list of points # we check if this signature goes with the current point # the signatures are valid, so push a 1 to the stack # tag::source1[] # points = [S256Point.parse(sec) for sec in sec_pubkeys] points = [] sigs = [] for sec in range(len(sec_pubkeys)): points.append(S256Point.parse(sec_pubkeys[sec])) for sig in range(len(der_signatures)): sigs.append(Signature.parse(der_signatures[sig])) for sig in sigs: if len(points) == 0: return False while points: point = points.pop(0) if point.verify(z, sig): break stack.append(encode_num(1)) except (ValueError, SyntaxError): return False return True
def verify_input(self, input_index): '''Returns whether the input has a valid signature''' # get the relevant input tx_in = self.tx_ins[input_index] # get the sec_pubkey at current signature index point = S256Point.parse(tx_in.sec_pubkey()) # get the der sig and hash_type from input # get the der_signature at current signature index der, hash_type = tx_in.der_signature() # get the signature from der format signature = Signature.parse(der) # get the hash to sign z = self.sig_hash_bip143(input_index, hash_type) # use point.verify on the hash to sign and signature if not point.verify(z, signature): return False return True
def op_checkmultisig(stack, z): 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): der_signatures.append(stack.pop()[:-1]) # <1> stack.pop() # <2> try: # parse all the points parsed_points = [S256Point.parse(p) for p in sec_pubkeys] # parse all the signatures parsed_signatures = [Signature.parse(s) for s in der_signatures] # loop through the signatures valid_sigs = 0 for sig in parsed_signatures: # if we have no more points, signatures are no good if len(parsed_points) == 0: return False # we loop until we find the point which works with this signature for i, p in enumerate(parsed_points): print(i) # get the current point from the list of points # we check if this signature goes with the current point if p.verify(z, sig): parsed_points.pop(i) valid_sigs += 1 # the signatures are valid, so push a 1 to the stack if valid_sigs == len(parsed_signatures): stack.pop(encode_num(1)) except (ValueError, SyntaxError): return False return True
def op_checkmultisig(stack, z): 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): der_signatures.append(stack.pop()[:-1]) # <1> stack.pop() # <2> try: # end::source1[] # parse all the points # parse all the signatures # loop through the signatures # if we have no more points, signatures are no good # we loop until we find the point which works with this signature # get the current point from the list of points # we check if this signature goes with the current point # the signatures are valid, so push a 1 to the stack # tag::source1[] #raise NotImplementedError # <3> pub_key_points = [] for pub_key in sec_pubkeys: point = S256Point.parse(pub_key) pub_key_points.append(point) signatures = [] for der_sig in der_signatures: sig = Signature.parse(der_sig) signatures.append(sig) for sig in signatures: if not valid_sig(sig, pub_key_points, z): stack.append(encode_num(0)) return False except (ValueError, SyntaxError): return False stack.append(encode_num(1)) return True
def op_checkmultisig(stack, z): 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): # signature is assumed to be using SIGHASH_ALL der_signatures.append(stack.pop()[:-1]) # OP_CHECKMULTISIG bug stack.pop() try: # parse the sec_pubkeys into an array of points points = [S256Point.parse(sec) for sec in sec_pubkeys] # parse the der_signatures into an array of signatures sigs = [Signature.parse(der) for der in der_signatures] # loop through the signatures for sig in sigs: # bail early if we don't have any points left if len(points) == 0: # add a 0 to the stack using encode_num(0) stack.append(encode_num(0)) # return True return True # 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
def op_checksig(stack, z): # check that there are at least 2 elements on the stack if len(stack) < 2: return False # the top element of the stack is the SEC pubkey pubkey = stack.pop() # the next element of the stack is the DER signature signature = stack.pop() # take off the last byte of the signature as that's the hash_type signature = signature[:-1] # parse the serialized pubkey and signature into objects point = S256Point.parse(pubkey) sig = Signature.parse(signature) # verify the signature using S256Point.verify() valid = point.verify(z, sig) # push an encoded 1 or 0 depending on whether the signature verified stack.append(encode_num(1 if valid else 0)) return True
def test_sig_hash_bip143(self): raw_tx = unhexlify( '0100000001fd5145175fafdee6d20ac376e376cf26d933848ba5aa177d0d163a462fb3f183010000006b483045022100f49a17e80098bc057e319b890bdc42fe7224e7f6beb69a650102f802239be154022069742f504fdd52906c14d0d18ff0808e01146813775602163ec10d419270c1c541210223f1c80f382f086e2af7ad9d05227d94b6cf292596b9853f04a91194048f9048ffffffff0236820100000000001976a914dc10e999a5f18eb510feec09206d1812fa24a9c288ac5c058049000000001976a91421704f258089af191df1a4abed2b48ec11d6063e88ac00000000' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) tx_in = tx.tx_ins[0] raw_tx2 = unhexlify( '010000000185037eb5531900f2f450e55cd950c509310229c0444e318a8811eecfa3b5c183010000006b483045022100f4a6e308ff7846bd19d394ec1b7263e051f2a60e6819feb006cdb9047bdd21a502206d969dfb5dfee3e53ed1a79b441d1cc2b7b8fe945ac7507c3b5e180565fbaead4121037765d8921f9559a6f03d620a1687a57e5b4ecb9efa5b41fc44555da0a376f81affffffff021ffc6c00000000001976a914fe1f6bea216c790c30d07f52966850268a3f90a788acfc8b8149000000001976a9142563b8536a228ec866e1c1084044a7730e53758888ac00000000' ) stream2 = BytesIO(raw_tx2) tx2 = Tx.parse(stream2) tx_in._value = tx2.tx_outs[1].amount tx_in._script_pubkey = tx2.tx_outs[1].script_pubkey.serialize() der, hash_type = tx_in.der_signature() sec = tx_in.sec_pubkey() sig = Signature.parse(der) point = S256Point.parse(sec) z = tx.sig_hash_bip143(0, hash_type) self.assertTrue(point.verify(z, sig)) self.assertTrue(tx.verify_input(0)) self.assertTrue(tx.verify()) raw_tx = unhexlify( '01000000066f267f335a54abf404c66a7a6e9ed3d77566a09ce11632f57029a677f42c6095000000006b483045022100fb0b16699c9b0984345c7860e208c04694aaa5117c8306082cfafc58b53e489a02203cd53408f1f8c8ff29701a9d1f6960b2dc5e1039f0eea949c5a886ac367e1e38412102fdcae0e5a55b20c8d3cbdf451d39f6d47daa50f884ed0ffcf0ae0adfeec4abb9ffffffff4ceb6a2894b19b96fedd543750bf7307805a2f6ca189c8c42d1abbe2930235fa000000006a4730440220794c269d519b567aa694de6dcde1d09dffa30b69dc18a619ce9ea65f239899150220156394f70f405c0710851490b9f21dc8a23931fbdc8a70ea51f73e9b00274a5c412103b708cd0b3329cff03611b0155384d1d4f40cb3aa30f82d8f4a34da044c868058ffffffff15053ac5123a25e0adf0ed998dfb710fff827861ac1a4c6601be8034179350ab000000006a473044022020e7b448318fa44b977d557b639aaf3a9666cf6d8dd446bd7812e752ddfcd1d302207159d22c2e379b77b0514b8e0767d0e9fff7063a659c268d605be436f65703884121031a97eb1664ceffa32988f7ea7c6726d681f1385b9765be1a40d6083fba4e6c69ffffffff2e1fb2ad94461104b147ffe95d0534eb98495c45831547b70eae652ac6cf52d0000000006b483045022100b0ce5496d51673f82430eee24c57f7f2f2631e5b9b32c78bbd79e1cbf3f6297b02201c807ecfa86c1c493e83f1235a19e4426da651e8f76c2f4b41ceebf1222a9291412102e4aa3631fd0b4a877c7c0a040b8211636f743c392ce17e6f266beb1b62490af9ffffffff311368bcf1bac2ae2e906bd7e84e9b45da861a63154ae5c3d69840f65486ba86000000006b483045022100d5f63c5284604eefb942fa9710f8d5b5bccf431e63c496237a0c41eb5c6debf102202bda17f3b7406b9c41f44c7377261413cfa144489a70a40e9e9126b3e7f2fc734121032e413587a71814365b7912eac3a052d8ac0c5f2351d3d84863a02bafefd41f19ffffffff2e9e219c5a68079891a8d2b00bfcf3772fa605997773c2c516bb5ac99aa8ee06000000006a47304402207b6e0d96d0ce538fb54fcb1731a35632b6e40efde834ce45ee22f0c0f5baa886022009327de37e3fb657af29161d265db558869c09e295e84ddb2f686a492db0015a41210389c44f336f7c8cc3096f8f40bc5bdbffea24da9e26649dbe6b862d7d369698d0ffffffff0102b84f05000000001976a9145c52250125494685f133df34f47fb88799b2903588ac00000000' ) stream = BytesIO(raw_tx) tx = Tx.parse(stream) inputs = ( ('18Lk6CB2WSpc4BVbxWhZrxLaYaJA2XVtyU', 24285000), ('13xY6E2tnBC5eGFCkayAUdVVcuGkFPoebJ', 824730), ('1BjFmsA4StiDa9xjAwahFXNpzR6SfXxBFD', 7583000), ('1Nn5QirD9iFT5kSF35XN8E3SX3SJM1daPL', 13150000), ('1HE8AdXHkP2bbnKmgENET4iyCHncP7rd7G', 32850000), ('1J3BgNjoqeR5JhHzC2rgorzBXTmdbmYcau', 10422900), ) for i, data in enumerate(inputs): addr, value = data tx_in = tx.tx_ins[i] i += 1 h160 = decode_base58(addr) tx_in._value = value tx_in._script_pubkey = p2pkh_script(h160) self.assertTrue(tx.verify())
def op_checksig(stack, z): # 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) der_signature = stack.pop()[:-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) # 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
def op_checkmultisig(stack, z): 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): der_signatures.append(stack.pop()[:-1]) # <1> stack.pop() # <2> try: # end::source1[] # parse all the points points = [S256Point.parse(sec_pubkey) for sec_pubkey in sec_pubkeys] # parse all the signatures signatures = [Signature.parse(der) for der in der_signatures] # loop through the signatures for sig in signatures: # if we have no more points, signatures are no good if not points: return False # we loop until we find the point which works with this signature while points: # get the current point from the list of points point = points.pop(0) # we check if this signature goes with the current point if point.verify(z, sig): break # the signatures are valid, so push a 1 to the stack if points: return False stack.append(encode_num(1)) # tag::source1[] except (ValueError, SyntaxError): return False return True
def __init__(self, xpub): self.testnet = (xpub[:4] == PUB_TEST) self.depth = xpub[4:5] # print(type(self.depth)) self.parent = xpub[5:9] # print(type(self.parent)) self.child_num = xpub[9:13] # print(type(self.child_num)) self.chaincode = xpub[13:45] # print(type(self.chaincode)) self.key = xpub[45:-4] # print(type(self.key)) self.checksum = xpub[-4:] # print(type(self.checksum)) if not self.check_sum(): raise ConfigurationError("Invalid Checksum for ExtendedPrivKey") try: point = S256Point.parse(self.key) except ValueError: raise ConfigurationError("Point is not on the curve, invalid key.")
def op_checkmultisig2(stack, z): 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): # signature is assumed to be using SIGHASH_ALL der_signatures.append(stack.pop()[:-1]) # OP_CHECKMULTISIG bug stack.pop() try: # parse all the points points = [S256Point.parse(sec) for sec in sec_pubkeys] # parse all the signatures sigs = [Signature.parse(der) for der in der_signatures] # loop through the signatures for sig in sigs: # if we have no more points, signatures are no good if len(points) == 0: LOGGER.info("signatures no good or not in right order") return False # we loop until we find the point which works with this signature while points: # get the current point from the list of points point = points.pop(0) # we check if this signature goes with the current point if point.verify(z, sig): break # the signatures are valid, so push a 1 to the stack stack.append(encode_num(1)) except (ValueError, SyntaxError): return False return True
def xpub_raw_parse(cls, s): version = s.read(4) if version in (TESTNET_XPUB, TESTNET_YPUB, TESTNET_ZPUB): testnet = True elif version in (MAINNET_XPUB, MAINNET_YPUB, MAINNET_ZPUB): testnet = False else: raise ValueError('not an xpub, ypub or zpub: {} {}'.format(s, version)) depth = byte_to_int(s.read(1)) parent_fingerprint = s.read(4) child_number = big_endian_to_int(s.read(4)) chain_code = s.read(32) point = S256Point.parse(s.read(33)) return cls( point=point, chain_code=chain_code, depth=depth, parent_fingerprint=parent_fingerprint, child_number=child_number, testnet=testnet, )