def test_address_scriptPubKey(self): pubkey = "03 a1af804ac108a8a51782198c2d034b28bf90c8803f5a53f76276fa69a4eae77f" pubkey_hash = hash160(pubkey).hex() opcodes = [0, pubkey_hash] address_from_scriptPubKey(opcodes) opcodes2, _ = scriptPubKey_from_address(address_from_scriptPubKey(opcodes)) self.assertEqual(opcodes, opcodes2) opcodes = ['OP_DUP', 'OP_HASH160', pubkey_hash, 'OP_EQUALVERIFY', 'OP_CHECKSIG'] opcodes2, _ = scriptPubKey_from_address(address_from_scriptPubKey(opcodes)) self.assertEqual(opcodes, opcodes2) script_hash = hash160(encode(opcodes)).hex() opcodes = ['OP_HASH160',script_hash, 'OP_EQUAL'] opcodes2, _ = scriptPubKey_from_address(address_from_scriptPubKey(opcodes)) self.assertEqual(opcodes, opcodes2) script_hash = sha256(encode(opcodes)).hex() opcodes = [0, script_hash] opcodes2, _ = scriptPubKey_from_address(address_from_scriptPubKey(opcodes)) self.assertEqual(opcodes, opcodes2) # Unknown script opcodes = [16, pubkey_hash] self.assertRaises(ValueError, address_from_scriptPubKey, opcodes) #address_from_scriptPubKey(opcodes) # Unhandled witness version (16) wp = hash160(pubkey)[2:] addr = b32address_from_witness(16, wp) self.assertRaises(ValueError, scriptPubKey_from_address, addr)
def test_nulldata3(self): # Invalid data lenght (81 bytes) for nulldata scriptPubKey payload = "00" * 81 self.assertRaises(ValueError, scriptPubKey_from_payload, "nulldata", payload) # scriptPubKey_from_payload('nulldata', payload) # Wrong data lenght (32) in 35-bytes nulldata script: # it should have been 33 script = encode(["OP_RETURN", b"\x00" * 33]) script = script[:1] + b"\x20" + script[2:] self.assertRaises(ValueError, payload_from_scriptPubKey, script) # payload_from_scriptPubKey(script) # Wrong data lenght (32) in 83-bytes nulldata script: # it should have been 80 script = encode(["OP_RETURN", b"\x00" * 80]) script = script[:2] + b"\x20" + script[3:] self.assertRaises(ValueError, payload_from_scriptPubKey, script) # payload_from_scriptPubKey(script) # Missing OP_PUSHDATA1 (0x4c) in 83-bytes nulldata script, # got 0x20 instead script = encode(["OP_RETURN", b"\x00" * 80]) script = script[:1] + b"\x20" + script[2:] self.assertRaises(ValueError, payload_from_scriptPubKey, script) # payload_from_scriptPubKey(script) # Invalid 77 bytes OP_RETURN script length script = b"\x6A" + b"\x4B" * 76 self.assertRaises(ValueError, payload_from_scriptPubKey, script)
def test_p2sh(self): # https://medium.com/@darosior/bitcoin-raw-transactions-part-2-p2sh-94df206fee8d script = ['OP_2DUP', 'OP_EQUAL', 'OP_NOT', 'OP_VERIFY', 'OP_SHA1', 'OP_SWAP', 'OP_SHA1', 'OP_EQUAL'] script_bytes = encode(script) self.assertEqual(script_bytes.hex(), '6e879169a77ca787') network = 'mainnet' addr = p2sh(script_bytes, network) self.assertEqual(addr, b'37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP') _, redeem_script_hash, network2, is_p2sh = h160_from_b58address(addr) self.assertEqual(network, network2) self.assertTrue(is_p2sh) self.assertEqual(redeem_script_hash, hash160(script_bytes)) self.assertEqual(redeem_script_hash.hex(), '4266fc6f2c2861d7fe229b279a79803afca7ba34') output_script = ['OP_HASH160', redeem_script_hash.hex(), 'OP_EQUAL'] _ = encode(output_script) # address with trailing/leading spaces _, h160, _, _ = h160_from_b58address( ' 37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP ') self.assertEqual(redeem_script_hash, h160)
def test_nulldata(self): # https://learnmeabitcoin.com/guide/nulldata # opcodes = ['OP_RETURN', data.hex()] data = "hello world".encode().hex() self.assertEqual(data, "68656c6c6f20776f726c64") opcodes = nulldata_scriptPubKey(data) scriptPubKey = encode(opcodes) self.assertEqual(scriptPubKey.hex(), "6a0b68656c6c6f20776f726c64") # no address for this script data = "charley loves heidi".encode().hex() self.assertEqual(data, "636861726c6579206c6f766573206865696469") opcodes = nulldata_scriptPubKey(data) scriptPubKey = encode(opcodes) self.assertEqual(scriptPubKey.hex(), "6a13636861726c6579206c6f766573206865696469") # no address for this script data = "家族も友達もみんなが笑顔の毎日がほしい".encode().hex() self.assertEqual(data, "e5aeb6e6978fe38282e58f8be98194e38282e381bfe38293e381aae3818ce7ac91e9a194e381aee6af8ee697a5e3818ce381bbe38197e38184") opcodes = nulldata_scriptPubKey(data) scriptPubKey = encode(opcodes) self.assertEqual(scriptPubKey.hex(), "6a39e5aeb6e6978fe38282e58f8be98194e38282e381bfe38293e381aae3818ce7ac91e9a194e381aee6af8ee697a5e3818ce381bbe38197e38184") # no address for this script # Invalid data lenght (81 bytes) for nulldata scriptPubKey data = '00'*81 self.assertRaises(ValueError, nulldata_scriptPubKey, data)
def test_simple(): script_list = [ [2, 3, "OP_ADD", 5, "OP_EQUAL"], ["1ADD", "OP_1ADD", "1ADE", "OP_EQUAL"], [hex(26)[2:].upper(), -1, "OP_ADD", hex(26)[2:].upper(), "OP_EQUAL"], [ hex(0xFFFFFFFF)[2:].upper(), -1, "OP_ADD", hex(0xFFFFFFFF)[2:].upper(), "OP_EQUAL", ], ["1F" * 250, "OP_DROP"], ["1F" * 520, "OP_DROP"], ] for script in script_list: script_bytes = encode(script) script2 = decode(script_bytes) assert script == script2 script_bytes2 = encode(script2) assert script_bytes == script_bytes2 script_serialized = serialize(script) script3 = deserialize(script_serialized) assert script == script3 script4 = deserialize(script_serialized.hex()) assert script == script4
def test_nulldata() -> None: scripts: List[List[Token]] = [["OP_RETURN", "11" * 79], ["OP_RETURN", "00" * 79]] for scriptPubKey in scripts: assert scriptPubKey == script.decode(script.encode(scriptPubKey)) assert scriptPubKey == script.decode(script.encode(scriptPubKey).hex()) assert scriptPubKey == script.deserialize( script.serialize(scriptPubKey)) assert scriptPubKey == script.deserialize( script.serialize(scriptPubKey).hex())
def test_selfconsistency(self): # OP_RETURN data = "time-stamped data".encode().hex() # opcodes = ['OP_RETURN', data.hex()] opcodes = nulldata_scriptPubKey(data) scriptPubKey = encode(opcodes) opcodes2 = decode(scriptPubKey) self.assertEqual(opcodes, opcodes2) # p2pk pubkey = "04 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf f7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4" # opcodes = [pubkey, 'OP_CHECKSIG'] opcodes = p2pk_scriptPubKey(pubkey) scriptPubKey = encode(opcodes) opcodes2 = decode(scriptPubKey) self.assertEqual(opcodes, opcodes2) # multi-sig pubkey2 = "04 61cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d765 19aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af" # opcodes = [1, pubkey, pubKey2, 2, 'OP_CHECKMULTISIG'] opcodes = p2ms_scriptPubKey(1, (pubkey, pubkey2)) scriptPubKey = encode(opcodes) opcodes2 = decode(scriptPubKey) self.assertEqual(opcodes, opcodes2) # p2pkh pubkey_hash = hash160(pubkey).hex() # opcodes = ['OP_DUP', 'OP_HASH160', pubkey_hash.hex(), 'OP_EQUALVERIFY', 'OP_CHECKSIG'] opcodes = p2pkh_scriptPubKey(pubkey_hash) scriptPubKey = encode(opcodes) opcodes2 = decode(scriptPubKey) self.assertEqual(opcodes, opcodes2) # p2sh (p2pkh-p2sh) redeem_script_hash = hash160(scriptPubKey).hex() # opcodes = ['OP_HASH160', redeem_script_hash.hex(), 'OP_EQUAL'] opcodes = p2sh_scriptPubKey(redeem_script_hash) scriptPubKey = encode(opcodes) opcodes2 = decode(scriptPubKey) self.assertEqual(opcodes, opcodes2) # p2wpkh # opcodes = [0, pubkey_hash.hex()] opcodes = p2wpkh_scriptPubKey(pubkey_hash) scriptPubKey = encode(opcodes) self.assertEqual(scriptPubKey.hex(), "0014"+pubkey_hash) opcodes2 = decode(scriptPubKey) self.assertEqual(opcodes, opcodes2) # p2wsh witness_script = [pubkey, 'OP_CHECKSIG'] witness_script_bytes = encode(witness_script) witness_script_hash = sha256(witness_script_bytes) # opcodes = [0, witness_script_hash.hex()] opcodes = p2wsh_scriptPubKey(witness_script_hash.hex()) scriptPubKey = encode(opcodes) self.assertEqual(scriptPubKey.hex(), "0020"+witness_script_hash.hex()) opcodes2 = decode(scriptPubKey) self.assertEqual(opcodes, opcodes2)
def test_p2pk() -> None: # self-consistency pubkey = "02 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" scriptPubKey = script.encode([pubkey, "OP_CHECKSIG"]) assert scriptPubKey == p2pk(pubkey) # to the scriptPubKey in two steps (through payload) script_type = "p2pk" assert scriptPubKey == scriptPubKey_from_payload(script_type, pubkey) # back from the scriptPubKey to the payload assert (script_type, bytes.fromhex(pubkey), 0) == payload_from_scriptPubKey(scriptPubKey) err_msg = "no address for p2pk scriptPubKey" with pytest.raises(ValueError, match=err_msg): address_from_scriptPubKey(scriptPubKey) # documented test case: https://learnmeabitcoin.com/guide/p2pk pubkey = ( "04" "ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414" "e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c") scriptPubKey = "41" + pubkey + "ac" assert scriptPubKey == p2pk(pubkey).hex() # invalid size: 34 bytes instead of (33, 65) pubkey = ( # fmt: off "03" "ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414" "14") # fmt: on err_msg = "not a private or public key: " with pytest.raises(ValueError, match=err_msg): p2pk(pubkey)
def test_p2ms_3(self): # mixed compressed / uncompressed public keys pubkey1 = ( "04" "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" "f7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4" ) pubkey2 = ( "03" "61cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d765" ) pubkey3 = ( "02" "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" ) pubkeys = [ bytes.fromhex(pubkey1), bytes.fromhex(pubkey2), bytes.fromhex(pubkey3), ] m = 1 n = len(pubkeys) script = scriptPubKey_from_payload("p2ms", pubkeys, m) pubkeys.sort() exp_script = encode([m] + pubkeys + [n, "OP_CHECKMULTISIG"]) self.assertEqual(script.hex(), exp_script.hex()) script_type, payload, m2 = payload_from_scriptPubKey(script) self.assertEqual(script_type, "p2ms") self.assertEqual(m, m2) self.assertEqual(pubkeys, payload)
def test_p2sh(self): script_type = "p2sh" # self-consistency pubkey = "02" "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" pubkey_hash = hash160(pubkey) redeem_script = scriptPubKey_from_payload("p2pkh", pubkey_hash) payload = hash160(redeem_script) script = encode(["OP_HASH160", payload, "OP_EQUAL"]) # straight to the scriptPubKey scriptPubKey = p2sh(redeem_script) self.assertEqual(scriptPubKey.hex(), script.hex()) # to the scriptPubKey in two steps (through payload) scriptPubKey = scriptPubKey_from_payload(script_type, payload) self.assertEqual(scriptPubKey.hex(), script.hex()) # back from the scriptPubKey to the payload script_type2, payload2, m2 = payload_from_scriptPubKey(scriptPubKey) self.assertEqual(script_type, script_type2) self.assertEqual(0, m2) self.assertEqual(payload.hex(), payload2.hex()) script_type2, payload2, m2 = payload_from_scriptPubKey(script) self.assertEqual(script_type, script_type2) self.assertEqual(0, m2) self.assertEqual(payload.hex(), payload2.hex()) # data -> payload is not invertible (hash functions) # address network = "mainnet" address = base58address.p2sh(decode(redeem_script), network) address2 = address_from_scriptPubKey(scriptPubKey, network) self.assertEqual(address, address2) prefix = NETWORKS[network]["p2sh"] address2 = b58address_from_h160(prefix, payload, network) self.assertEqual(address, address2) scriptPubKey2, network2 = scriptPubKey_from_address(address) self.assertEqual(scriptPubKey2, scriptPubKey) self.assertEqual(network2, network) # documented test case: https://learnmeabitcoin.com/guide/p2sh payload = "748284390f9e263a4b766a75d0633c50426eb875" script = "a914748284390f9e263a4b766a75d0633c50426eb87587" scriptPubKey = scriptPubKey_from_payload(script_type, payload) self.assertEqual(scriptPubKey.hex(), script) network = "mainnet" address = b"3CK4fEwbMP7heJarmU4eqA3sMbVJyEnU3V" address2 = address_from_scriptPubKey(scriptPubKey, network) self.assertEqual(address, address2) scriptPubKey2, network2 = scriptPubKey_from_address(address) self.assertEqual(scriptPubKey2, scriptPubKey) self.assertEqual(network2, network) # invalid size: 21 bytes instead of 20 self.assertRaises(ValueError, scriptPubKey_from_payload, "00" * 21, "p2sh")
def test_CLT(self): network = 'mainnet' vault_pubkeys = [b'\x00' * 33, b'\x11' * 33, b'\x22' * 33] recovery_pubkeys = [b'\x77' * 33, b'\x88' * 33, b'\x99' * 33] redeem_script = encode([ 'OP_IF', 2, *vault_pubkeys, 3, 'OP_CHECKMULTISIG', 'OP_ELSE', 500, 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 2, *recovery_pubkeys, 3, 'OP_CHECKMULTISIG', 'OP_ENDIF' ]) payload = sha256(redeem_script) script = "00207b5310339c6001f75614daa5083839fa54d46165f6c56025cc54d397a85a5708" scriptPubKey = p2wsh(redeem_script) self.assertEqual(scriptPubKey.hex(), script) scriptPubKey = scriptPubKey_from_payload('p2wsh', payload) self.assertEqual(scriptPubKey.hex(), script) address = b"bc1q0df3qvuuvqqlw4s5m2jsswpelf2dgct97mzkqfwv2nfe02z62uyq7n4zjj" address2 = address_from_scriptPubKey(scriptPubKey, network) self.assertEqual(address, address2) address2 = bech32address.p2wsh(redeem_script, network) self.assertEqual(address, address2) address2 = b32address_from_witness(0, payload, network) self.assertEqual(address, address2)
def test_p2wsh() -> None: # self-consistency pubkey = "02 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" pubkey_hash = hash160(pubkey) redeem_script = scriptPubKey_from_payload("p2pkh", pubkey_hash) payload = sha256(redeem_script) scriptPubKey = script.encode([0, payload]) assert scriptPubKey == p2wsh(script.decode(redeem_script)) # to the scriptPubKey in two steps (through payload) script_type = "p2wsh" assert scriptPubKey == scriptPubKey_from_payload(script_type, payload) # back from the scriptPubKey to the payload assert (script_type, payload, 0) == payload_from_scriptPubKey(scriptPubKey) # bech32 address network = "mainnet" address = bech32address.p2wsh(redeem_script, network) assert address == address_from_scriptPubKey(scriptPubKey, network) wit_ver = 0 assert address == b32address_from_witness(wit_ver, payload, network) # back from the address to the scriptPubKey assert (scriptPubKey, network) == scriptPubKey_from_address(address) # p2sh-wrapped base58 address address = base58address.p2wsh_p2sh(redeem_script, network) assert address == b58address_from_witness(payload, network)
def test_p2pk(self): # https://learnmeabitcoin.com/guide/p2pk # opcodes = [pubkey, 'OP_CHECKSIG'] pubkey = "04 ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414 e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c" opcodes = p2pk_scriptPubKey(pubkey) scriptPubKey = encode(opcodes) self.assertEqual(scriptPubKey.hex(), "4104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac")
def test_CLT() -> None: network = "mainnet" fed_pubkeys = [b"\x00" * 33, b"\x11" * 33, b"\x22" * 33] rec_pubkeys = [b"\x77" * 33, b"\x88" * 33, b"\x99" * 33] # fmt: off redeem_script = script.encode([ "OP_IF", 2, *fed_pubkeys, 3, "OP_CHECKMULTISIG", # noqa E131 "OP_ELSE", 500, "OP_CHECKLOCKTIMEVERIFY", "OP_DROP", # noqa E131 2, *rec_pubkeys, 3, "OP_CHECKMULTISIG", # noqa E131 "OP_ENDIF", ]) # fmt: on payload = sha256(redeem_script) scriptPubKey = ( "00207b5310339c6001f75614daa5083839fa54d46165f6c56025cc54d397a85a5708") assert scriptPubKey == p2wsh(redeem_script).hex() assert scriptPubKey == scriptPubKey_from_payload("p2wsh", payload).hex() address = b"bc1q0df3qvuuvqqlw4s5m2jsswpelf2dgct97mzkqfwv2nfe02z62uyq7n4zjj" assert address == address_from_scriptPubKey(scriptPubKey, network) assert address == b32address_from_witness(0, payload, network)
def test_p2pkh(self): script_type = 'p2pkh' # self-consistency pubkey = "04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4" payload = hash160(pubkey) script = encode(['OP_DUP', 'OP_HASH160', payload, 'OP_EQUALVERIFY', 'OP_CHECKSIG']) # straight to the scriptPubKey scriptPubKey = p2pkh(pubkey) self.assertEqual(scriptPubKey.hex(), script.hex()) # to the scriptPubKey in two steps (through payload) scriptPubKey = scriptPubKey_from_payload(script_type, payload) self.assertEqual(scriptPubKey.hex(), script.hex()) # back from the scriptPubKey to the payload script_type2, payload2, m2 = payload_from_scriptPubKey(scriptPubKey) self.assertEqual(script_type, script_type2) self.assertEqual(0, m2) self.assertEqual(payload.hex(), payload2.hex()) script_type2, payload2, m2 = payload_from_scriptPubKey(script) self.assertEqual(script_type, script_type2) self.assertEqual(0, m2) self.assertEqual(payload.hex(), payload2.hex()) # data -> payload is not invertible (hash functions) # address network = 'mainnet' address = base58address.p2pkh(pubkey, network) address2 = address_from_scriptPubKey(scriptPubKey, network) self.assertEqual(address, address2) prefix = p2pkh_prefix_from_network(network) address2 = b58address_from_h160(prefix, payload) self.assertEqual(address, address2) scriptPubKey2, network2 = scriptPubKey_from_address(address) self.assertEqual(scriptPubKey2, scriptPubKey) self.assertEqual(network2, network) # documented test case: https://learnmeabitcoin.com/guide/p2pkh payload = "12ab8dc588ca9d5787dde7eb29569da63c3a238c" script = "76a91412ab8dc588ca9d5787dde7eb29569da63c3a238c88ac" scriptPubKey = scriptPubKey_from_payload(script_type, payload) self.assertEqual(scriptPubKey.hex(), script) network = 'mainnet' address = b"12higDjoCCNXSA95xZMWUdPvXNmkAduhWv" address2 = address_from_scriptPubKey(scriptPubKey, network) self.assertEqual(address, address2) scriptPubKey2, network2 = scriptPubKey_from_address(address) self.assertEqual(scriptPubKey2, scriptPubKey) self.assertEqual(network2, network) # Invalid size: 11 bytes instead of 20 self.assertRaises( ValueError, scriptPubKey_from_payload, "00" * 11, 'p2pkh')
def test_nulldata(self): script = ["OP_RETURN", "11" * 79] bscript = encode(script) self.assertEqual(script, decode(bscript)) script2 = ["OP_RETURN", b"\x11" * 79] bscript = encode(script2) self.assertEqual(script, decode(bscript)) script = ["OP_RETURN", "00" * 79] bscript = encode(script) self.assertEqual(script, decode(bscript)) script2 = ["OP_RETURN", b"\x11" * 79] bscript = encode(script) self.assertEqual(script, decode(bscript))
def test_nulldata(self): script = ['OP_RETURN', '11' * 79] bscript = encode(script) self.assertEqual(script, decode(bscript)) script2 = ['OP_RETURN', b'\x11' * 79] bscript = encode(script2) self.assertEqual(script, decode(bscript)) script = ['OP_RETURN', '00' * 79] bscript = encode(script) self.assertEqual(script, decode(bscript)) script2 = ['OP_RETURN', b'\x11' * 79] bscript = encode(script) self.assertEqual(script, decode(bscript))
def test_p2wsh_p2sh() -> None: # leading/trailing spaces should be tolerated pub = " 02 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" scriptPubKey: List[Token] = [pub, "OP_CHECKSIG"] witness_script_bytes = script.encode(scriptPubKey) p2wsh_p2sh(witness_script_bytes) p2wsh_p2sh(witness_script_bytes, "testnet")
def test_p2wsh_p2sh(self): # leading/trailing spaces should be tolerated pub = " 0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2D" "CE28D959F2815B16F81798" witness_script = [pub, "OP_CHECKSIG"] witness_script_bytes = encode(witness_script) p2wsh_p2sh(witness_script_bytes) p2wsh_p2sh(witness_script_bytes, "testnet")
def test_simple(self): script_list = [2, 3, 'OP_ADD', 5, 'OP_EQUAL'] script_bytes = encode(script_list) script_list2 = decode(script_bytes) self.assertEqual(script_list, script_list2) script_serialized = serialize(script_list) script_list2 = parse(script_serialized) self.assertEqual(script_list, script_list2) script_list = [26, -1, 'OP_ADD', 25, 'OP_EQUAL'] script_bytes = encode(script_list) script_list2 = decode(script_bytes) self.assertEqual(script_list, script_list2) script_serialized = serialize(script_list) script_list2 = parse(script_serialized) self.assertEqual(script_list, script_list2) script_list = [0xffffffff, -1, 'OP_ADD', 0xfffffffe, 'OP_EQUAL'] script_bytes = encode(script_list) script_list2 = decode(script_bytes) self.assertEqual(script_list, script_list2) script_serialized = serialize(script_list) script_list2 = parse(script_serialized) self.assertEqual(script_list, script_list2) script_list = ["1f" * 250, 'OP_DROP'] script_bytes = encode(script_list) script_list2 = decode(script_bytes) self.assertEqual(script_list, script_list2) script_serialized = serialize(script_list) script_list2 = parse(script_serialized) self.assertEqual(script_list, script_list2) script_list = ["1f" * 520, 'OP_DROP'] script_bytes = encode(script_list) script_list2 = decode(script_bytes.hex()) self.assertEqual(script_list, script_list2) script_serialized = serialize(script_list) script_list2 = parse(script_serialized.hex()) self.assertEqual(script_list, script_list2)
def test_valid_address(self): """Test whether valid addresses decode to the correct output""" for a, hexscript in VALID_BC_ADDRESS + VALID_TB_ADDRESS: self.assertTrue(has_segwit_prefix(a)) network, witvers, witprog = _decode(a) script_pubkey = [witvers, bytes(witprog)] self.assertEqual(encode(script_pubkey).hex(), hexscript) address = _encode(network, witvers, witprog) self.assertEqual(a.lower().strip(), address.decode())
def test_nulldata(): scripts = [ ["OP_RETURN", "11" * 79], ["OP_RETURN", "00" * 79], ] for script in scripts: bscript = encode(script) assert script == decode(bscript)
def test_valid_address(self): """Test whether valid addresses decode to the correct output""" for a, hexscript in VALID_BC_ADDRESS + VALID_TB_ADDRESS: self.assertTrue(has_segwit_prefix(a)) witvers, witprog, network, _ = witness_from_b32address(a) script_pubkey = [witvers, witprog] self.assertEqual(encode(script_pubkey).hex(), hexscript) address = b32address_from_witness(witvers, witprog, network) self.assertEqual(a.lower().strip(), address.decode('ascii'))
def test_p2ms_2(self): pubkey1 = ( "04" "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" "f7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4" ) pubkey2 = ( "04" "61cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d765" "19aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af" ) pubkey3 = ( "04" "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8" ) pubkeys = [pubkey1, pubkey2, pubkey3] m = 1 n = len(pubkeys) script = [m] + pubkeys + [n, "OP_CHECKMULTISIG"] payload_from_scriptPubKey(script) scriptPubKey_from_payload("p2ms", pubkeys, m) # Invalid list of Octets for p2sh script self.assertRaises(ValueError, scriptPubKey_from_payload, "p2sh", pubkeys, 0) # scriptPubKey_from_payload('p2sh', pubkeys, 0) # Invalid number of keys (0) in m-of-n multisignature script = [1, 3, "OP_CHECKMULTISIG"] self.assertRaises(ValueError, payload_from_scriptPubKey, script) # payload_from_scriptPubKey(script) # Keys (2) / n (3) mismatch in m-of-n multisignature script = [1, pubkey1, pubkey2, 3, "OP_CHECKMULTISIG"] self.assertRaises(ValueError, payload_from_scriptPubKey, script) # payload_from_scriptPubKey(script) # Impossible 3-of-2 multisignature script = [3, pubkey1, pubkey2, 2, "OP_CHECKMULTISIG"] self.assertRaises(ValueError, payload_from_scriptPubKey, script) # payload_from_scriptPubKey(script) # Invalid m (0) in 0-of-2 multisignature script = [0, pubkey1, pubkey2, 2, "OP_CHECKMULTISIG"] self.assertRaises(ValueError, payload_from_scriptPubKey, script) # payload_from_scriptPubKey(script) # 133-th byte in 1-of-3 multisignature payload is 0x40, # it should have been 0x41 script = [1, pubkey1, pubkey2, pubkey3, 3, "OP_CHECKMULTISIG"] bscript = encode(script) script = bscript[:133] + b"\x40" + bscript[134:] self.assertRaises(ValueError, payload_from_scriptPubKey, script)
def test_CLT(self): vault_pubkeys = [b'\x00'*33, b'\x11'*33, b'\x22'*33] recovery_pubkeys = [b'\x77'*33, b'\x88'*33, b'\x99'*33] opcodes = [ 'OP_IF', 2, *vault_pubkeys, 3, 'OP_CHECKMULTISIG', 'OP_ELSE', 500, 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 2, *recovery_pubkeys, 3, 'OP_CHECKMULTISIG', 'OP_ENDIF' ] witness_program = encode(opcodes) witness_hash = sha256(witness_program) script_pubkey = p2wsh_scriptPubKey(witness_hash) self.assertEqual(encode(script_pubkey).hex(), "00207b5310339c6001f75614daa5083839fa54d46165f6c56025cc54d397a85a5708") address = b32address_from_witness(0, witness_hash) self.assertEqual(address, b"bc1q0df3qvuuvqqlw4s5m2jsswpelf2dgct97mzkqfwv2nfe02z62uyq7n4zjj")
def test_p2pk(self): script_type = "p2pk" # self-consistency pubkey = "02" "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" script = encode([pubkey, "OP_CHECKSIG"]) # straight to the scriptPubKey scriptPubKey = p2pk(pubkey) self.assertEqual(scriptPubKey.hex(), script.hex()) # to the scriptPubKey in two steps (through payload) scriptPubKey = scriptPubKey_from_payload(script_type, pubkey) self.assertEqual(scriptPubKey.hex(), script.hex()) # back from the scriptPubKey to the payload script_type2, payload2, m2 = payload_from_scriptPubKey(scriptPubKey) self.assertEqual(script_type, script_type2) self.assertEqual(0, m2) self.assertEqual(bytes.fromhex(pubkey).hex(), payload2.hex()) script_type2, payload2, m2 = payload_from_scriptPubKey(script) self.assertEqual(script_type, script_type2) self.assertEqual(0, m2) self.assertEqual(bytes.fromhex(pubkey).hex(), payload2.hex()) # data -> payload in this case is invertible (no hash functions) # No address for p2pk script self.assertRaises(ValueError, address_from_scriptPubKey, scriptPubKey) # address_from_scriptPubKey(scriptPubKey) # documented test case: https://learnmeabitcoin.com/guide/p2pk pubkey = ( "04" "ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414" "e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c" ) script = ( "4104" "ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414" "e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84c" "ac" ) scriptPubKey = p2pk(pubkey) self.assertEqual(scriptPubKey.hex(), script) # Invalid size: 34 bytes instead of (33, 65) pubkey = ( "03" "ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414" "14" ) self.assertRaises(ValueError, p2pk, pubkey)
def test_nulldata() -> None: # self-consistency string = "time-stamped data" payload = string.encode() scriptPubKey = script.encode(["OP_RETURN", payload]) assert scriptPubKey == nulldata(string) # to the scriptPubKey in two steps (through payload) script_type = "nulldata" assert scriptPubKey == scriptPubKey_from_payload(script_type, payload) # back from the scriptPubKey to the payload assert (script_type, payload, 0) == payload_from_scriptPubKey(scriptPubKey) # data -> payload in this case is invertible (no hash functions) assert payload.decode() == string err_msg = "no address for null data script" with pytest.raises(ValueError, match=err_msg): address_from_scriptPubKey(scriptPubKey) # documented test cases: https://learnmeabitcoin.com/guide/nulldata string = "hello world" payload = string.encode() assert payload.hex() == "68656c6c6f20776f726c64" # pylint: disable=no-member scriptPubKey = b"\x6a\x0b" + payload assert scriptPubKey == nulldata(string) assert scriptPubKey == scriptPubKey_from_payload(script_type, payload) assert (script_type, payload, 0) == payload_from_scriptPubKey(scriptPubKey) # documented test cases: https://learnmeabitcoin.com/guide/nulldata string = "charley loves heidi" payload = string.encode() assert (payload.hex() # pylint: disable=no-member == "636861726c6579206c6f766573206865696469") scriptPubKey = b"\x6a\x13" + payload assert scriptPubKey == nulldata(string) assert scriptPubKey == scriptPubKey_from_payload(script_type, payload) assert (script_type, payload, 0) == payload_from_scriptPubKey(scriptPubKey) # documented test cases: https://learnmeabitcoin.com/guide/nulldata string = "家族も友達もみんなが笑顔の毎日がほしい" payload = string.encode() assert ( payload.hex() # pylint: disable=no-member == "e5aeb6e6978fe38282e58f8be98194e38282e381bfe38293e381aae3818ce7ac91e9a194e381aee6af8ee697a5e3818ce381bbe38197e38184" ) scriptPubKey = b"\x6a\x39" + payload assert scriptPubKey == nulldata(string) assert scriptPubKey == scriptPubKey_from_payload(script_type, payload) assert (script_type, payload, 0) == payload_from_scriptPubKey(scriptPubKey)
def test_p2sh(self): # https://learnmeabitcoin.com/guide/p2sh # opcodes = ['OP_HASH160', redeem_script_hash.hex(), 'OP_EQUAL'] redeem_script_hash = "748284390f9e263a4b766a75d0633c50426eb875" opcodes = p2sh_scriptPubKey(redeem_script_hash) scriptPubKey = encode(opcodes) self.assertEqual(scriptPubKey.hex(), "a914748284390f9e263a4b766a75d0633c50426eb87587") addr = address_from_scriptPubKey(scriptPubKey) self.assertEqual(addr.decode(), "3CK4fEwbMP7heJarmU4eqA3sMbVJyEnU3V") # Invalid size: 21 bytes instead of 20 self.assertRaises(ValueError, p2sh_scriptPubKey, "00"*21)
def test_simple() -> None: script_list: List[List[Token]] = [ [2, 3, "OP_ADD", 5, "OP_EQUAL"], ["1ADD", "OP_1ADD", "1ADE", "OP_EQUAL"], [hex(26)[2:].upper(), -1, "OP_ADD", hex(26)[2:].upper(), "OP_EQUAL"], [ hex(0xFFFFFFFF)[2:].upper(), -1, "OP_ADD", hex(0xFFFFFFFF)[2:].upper(), "OP_EQUAL", ], ["1F" * 250, "OP_DROP"], ["1F" * 520, "OP_DROP"], ] for scriptPubKey in script_list: assert scriptPubKey == script.decode(script.encode(scriptPubKey)) assert scriptPubKey == script.decode(script.encode(scriptPubKey).hex()) assert scriptPubKey == script.deserialize( script.serialize(scriptPubKey)) assert scriptPubKey == script.deserialize( script.serialize(scriptPubKey).hex())
def test_p2sh() -> None: # https://medium.com/@darosior/bitcoin-raw-transactions-part-2-p2sh-94df206fee8d scriptPubKey: List[Token] = [ "OP_2DUP", "OP_EQUAL", "OP_NOT", "OP_VERIFY", "OP_SHA1", "OP_SWAP", "OP_SHA1", "OP_EQUAL", ] assert script.encode(scriptPubKey).hex() == "6e879169a77ca787" network = "mainnet" addr = p2sh(scriptPubKey, network) assert addr == b"37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP" _, redeem_script_hash, network2, is_script_hash = h160_from_b58address( addr) assert network == network2 assert is_script_hash assert redeem_script_hash == hash160(script.encode(scriptPubKey)) assert redeem_script_hash.hex( ) == "4266fc6f2c2861d7fe229b279a79803afca7ba34" output_script: List[Token] = [ "OP_HASH160", redeem_script_hash.hex(), "OP_EQUAL" ] script.encode(output_script) # address with trailing/leading spaces _, h160, network2, is_script_hash = h160_from_b58address( " 37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP ") assert network == network2 assert is_script_hash assert redeem_script_hash == h160