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_p2pkh_from_pubkey(self): # https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses pub = "02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" addr = p2pkh(pub) self.assertEqual(addr, b'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs') _, h160, _, _ = h160_from_b58address(addr) self.assertEqual(h160, hash160(pub)) uncompr_pub = bytes_from_point( point_from_octets(pub), compressed=False) addr = p2pkh(uncompr_pub, compressed=False) self.assertEqual(addr, b'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM') _, h160, _, _ = h160_from_b58address(addr) self.assertEqual(h160, hash160(uncompr_pub)) # trailing/leading spaces in string pub = ' 02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352' addr = p2pkh(pub) self.assertEqual(addr, b'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs') _, h160, _, _ = h160_from_b58address(addr) self.assertEqual(h160, hash160(pub)) pub = '02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352 ' addr = p2pkh(pub) self.assertEqual(addr, b'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs')
def test_witness(self): pub = "03 a1af804ac108a8a51782198c2d034b28bf90c8803f5a53f76276fa69a4eae77f" b58addr = p2wpkh_p2sh(pub) _, h160, network, is_script_hash = h160_from_b58address(b58addr) self.assertEqual(network, 'mainnet') self.assertEqual(is_script_hash, True) #?!?!? self.assertEqual(len(h160), 20) b58addr = _b58segwitaddress(hash160(to_pubkey_bytes(pub, True, ec)), network) _, h160_2, network, is_script_hash = h160_from_b58address(b58addr) self.assertEqual(network, 'mainnet') self.assertEqual(is_script_hash, True) #?!?!? self.assertEqual(len(h160), 20) self.assertEqual(h160.hex(), h160_2.hex()) wscript = "a8a58c2d034b28bf90c8803f5a53f769a4" b58addr = p2wsh_p2sh(wscript) _, h160, network, is_script_hash = h160_from_b58address(b58addr) self.assertEqual(network, 'mainnet') self.assertEqual(is_script_hash, True) #?!?!? self.assertEqual(len(h160), 20) b58addr = _b58segwitaddress(sha256(wscript), network) _, h160_2, network, is_script_hash = h160_from_b58address(b58addr) self.assertEqual(network, 'mainnet') self.assertEqual(is_script_hash, True) #?!?!? self.assertEqual(len(h160), 20) self.assertEqual(h160.hex(), h160_2.hex()) # Invalid witness program length (19) self.assertRaises(ValueError, _b58segwitaddress, h160[:-1], network)
def test_exceptions() -> None: pubkey = "02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" payload = b"\xf5" + hash160(pubkey) invalid_address = b58encode(payload) with pytest.raises(ValueError, match="invalid base58 address prefix: "): h160_from_b58address(invalid_address) with pytest.raises(ValueError, match="not a private or public key: "): p2pkh(pubkey + "00")
def test_address_from_wif() -> None: q = 0x19E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 test_cases: List[Tuple[bool, str, str, str]] = [ ( False, "mainnet", "5J1geo9kcAUSM6GJJmhYRX1eZEjvos9nFyWwPstVziTVueRJYvW", "1LPM8SZ4RQDMZymUmVSiSSvrDfj1UZY9ig", ), ( True, "mainnet", "Kx621phdUCp6sgEXPSHwhDTrmHeUVrMkm6T95ycJyjyxbDXkr162", "1HJC7kFvXHepkSzdc8RX6khQKkAyntdfkB", ), ( False, "testnet", "91nKEXyJCPYaK9maw7bTJ7ZcCu6dy2gybvNtUWF1LTCYggzhZgy", "mzuJRVe3ERecM6F6V4R6GN9B5fKiPC9HxF", ), ( True, "testnet", "cNT1UjhUuGWN37hnmr754XxvPWwtAJTSq8bcCQ4pUrdxqxbA1iU1", "mwp9QoLuLK65XZUFKhPtvfujBjmgkZnmPx", ), ] for compressed, network, wif, address in test_cases: assert wif.encode() == wif_from_prvkey(q, network, compressed) assert prvkeyinfo_from_prvkey(wif) == (q, network, compressed) b58 = p2pkh(wif) assert b58 == address.encode() _, payload, net, is_script = h160_from_b58address(b58) assert net == network assert not is_script if compressed: b32 = p2wpkh(wif) assert (payload, network, is_script) == witness_from_b32address(b32)[1:] b = p2wpkh_p2sh(wif) _, payload2, net, is_script = h160_from_b58address(b) assert is_script assert (hash160(b"\x00\x14" + payload), network) == (payload2, net) else: err_msg = "not a private or compressed public key: " with pytest.raises(ValueError, match=err_msg): p2wpkh(wif) # type: ignore with pytest.raises(ValueError, match=err_msg): p2wpkh_p2sh(wif) # type: ignore
def test_b58address_from_h160() -> None: addr = b"1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" prefix, payload, network, _ = h160_from_b58address(addr) assert addr == b58address_from_h160(prefix, payload, network) addr = b"16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM" prefix, payload, network, _ = h160_from_b58address(addr) assert addr == b58address_from_h160(prefix, payload, network) addr = b"37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP" prefix, payload, network, _ = h160_from_b58address(addr) assert addr == b58address_from_h160(prefix, payload, network) err_msg = "invalid mainnet base58 address prefix: " with pytest.raises(ValueError, match=err_msg): bad_prefix = b"\xbb" b58address_from_h160(bad_prefix, payload, network)
def test_b58address_from_h160(self): addr = b'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs' prefix, payload, _, _ = h160_from_b58address(addr) self.assertEqual(addr, b58address_from_h160(prefix, payload)) addr = b'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM' prefix, payload, _, _ = h160_from_b58address(addr) self.assertEqual(addr, b58address_from_h160(prefix, payload)) addr = b'37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP' prefix, payload, _, _ = h160_from_b58address(addr) self.assertEqual(addr, b58address_from_h160(prefix, payload)) # Invalid base58 address prefix b'\xbb' bad_prefix = b'\xbb' self.assertRaises(ValueError, b58address_from_h160, bad_prefix, payload)
def test_p2sh() -> None: # https://medium.com/@darosior/bitcoin-raw-transactions-part-2-p2sh-94df206fee8d scriptPubKey: List[ScriptToken] = [ "OP_2DUP", "OP_EQUAL", "OP_NOT", "OP_VERIFY", "OP_SHA1", "OP_SWAP", "OP_SHA1", "OP_EQUAL", ] assert script.serialize(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.serialize(scriptPubKey)) assert redeem_script_hash.hex( ) == "4266fc6f2c2861d7fe229b279a79803afca7ba34" output_script: List[ScriptToken] = [ "OP_HASH160", redeem_script_hash.hex(), "OP_EQUAL", ] script.serialize(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
def test_address_from_wif(self): # uncompressed mainnet wif1 = "5J1geo9kcAUSM6GJJmhYRX1eZEjvos9nFyWwPstVziTVueRJYvW" pubkey, network = pubkey_info_from_prvkey(wif1) b58 = p2pkh(pubkey) self.assertEqual(b58, b'1LPM8SZ4RQDMZymUmVSiSSvrDfj1UZY9ig') self.assertRaises(ValueError, p2wpkh, pubkey) self.assertRaises(ValueError, p2wpkh_p2sh, pubkey) # compressed mainnet wif2 = "Kx621phdUCp6sgEXPSHwhDTrmHeUVrMkm6T95ycJyjyxbDXkr162" pubkey, network = pubkey_info_from_prvkey(wif2) b58 = p2pkh(pubkey) self.assertEqual(b58, b'1HJC7kFvXHepkSzdc8RX6khQKkAyntdfkB') b32 = p2wpkh(pubkey) self.assertEqual(h160_from_b58address( b58)[1:], witness_from_b32address(b32)[1:]) h160 = h160_from_b58address(b58)[1] b = p2wpkh_p2sh(pubkey) self.assertEqual(hash160(b'\x00\x14' + h160), h160_from_b58address(b)[1]) self.assertEqual(prvkey_info_from_prvkey( wif1)[0], prvkey_info_from_prvkey(wif2)[0]) # uncompressed testnet wif1 = "91gGn1HgSap6CbU12F6z3pJri26xzp7Ay1VW6NHCoEayNXwRpu2" pubkey, network = pubkey_info_from_prvkey(wif1) b58 = p2pkh(pubkey, network, None) self.assertEqual(b58, b'mvgbzkCSgKbYgaeG38auUzR7otscEGi8U7') self.assertRaises(ValueError, p2wpkh, pubkey) self.assertRaises(ValueError, p2wpkh_p2sh, pubkey) # compressed testnet wif2 = "cMzLdeGd5vEqxB8B6VFQoRopQ3sLAAvEzDAoQgvX54xwofSWj1fx" pubkey, network = pubkey_info_from_prvkey(wif2) b58 = p2pkh(pubkey, network, None) self.assertEqual(b58, b'n1KSZGmQgB8iSZqv6UVhGkCGUbEdw8Lm3Q') b32 = p2wpkh(pubkey, network) self.assertEqual(h160_from_b58address( b58)[1:], witness_from_b32address(b32)[1:]) h160 = h160_from_b58address(b58)[1] b = p2wpkh_p2sh(pubkey, network) self.assertEqual(hash160(b'\x00\x14' + h160), h160_from_b58address(b)[1]) self.assertEqual(prvkey_info_from_prvkey( wif1)[0], prvkey_info_from_prvkey(wif2)[0]) # uncompressed mainnet, trailing/leading spaces in string wif1 = " 5J1geo9kcAUSM6GJJmhYRX1eZEjvos9nFyWwPstVziTVueRJYvW" pubkey, network = pubkey_info_from_prvkey(wif1) b58 = p2pkh(pubkey) self.assertEqual(b58, b'1LPM8SZ4RQDMZymUmVSiSSvrDfj1UZY9ig') self.assertRaises(ValueError, p2wpkh, pubkey) self.assertRaises(ValueError, p2wpkh_p2sh, pubkey) # compressed mainnet, trailing/leading spaces in string wif2 = "Kx621phdUCp6sgEXPSHwhDTrmHeUVrMkm6T95ycJyjyxbDXkr162 " pubkey, network = pubkey_info_from_prvkey(wif2) b58 = p2pkh(pubkey) self.assertEqual(b58, b'1HJC7kFvXHepkSzdc8RX6khQKkAyntdfkB') b32 = p2wpkh(pubkey) self.assertEqual(h160_from_b58address( b58)[1:], witness_from_b32address(b32)[1:]) h160 = h160_from_b58address(b58)[1] b = p2wpkh_p2sh(pubkey) self.assertEqual(hash160(b'\x00\x14' + h160), h160_from_b58address(b)[1])