def test_p2pkh_from_pub_key() -> None: # https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses pub_key = "02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" address = "1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs" assert address == b58.p2pkh(pub_key) assert address == b58.p2pkh(pub_key, compressed=True) _, h160, _ = b58.h160_from_address(address) assert h160 == hash160(pub_key) # trailing/leading spaces in address string assert address == b58.p2pkh(" " + pub_key) assert h160 == hash160(" " + pub_key) assert address == b58.p2pkh(pub_key + " ") assert h160 == hash160(pub_key + " ") uncompr_pub_key = bytes_from_point(point_from_octets(pub_key), compressed=False) uncompr_address = "16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM" assert uncompr_address == b58.p2pkh(uncompr_pub_key, compressed=False) assert uncompr_address == b58.p2pkh(uncompr_pub_key) _, uncompr_h160, _ = b58.h160_from_address(uncompr_address) assert uncompr_h160 == hash160(uncompr_pub_key) err_msg = "not a private or uncompressed public key: " with pytest.raises(BTClibValueError, match=err_msg): assert uncompr_address == b58.p2pkh(pub_key, compressed=False) err_msg = "not a private or compressed public key: " with pytest.raises(BTClibValueError, match=err_msg): assert address == b58.p2pkh(uncompr_pub_key, compressed=True)
def test_p2wpkh() -> None: # https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki # leading/trailing spaces should be tolerated pub = " 02 79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" addr = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4" assert addr == b32.p2wpkh(pub) addr = "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx" assert addr == b32.p2wpkh(pub, "testnet") # http://bitcoinscri.pt/pages/segwit_native_p2wpkh pub = "02 530c548d402670b13ad8887ff99c294e67fc18097d236d57880c69261b42def7" addr = "bc1qg9stkxrszkdqsuj92lm4c7akvk36zvhqw7p6ck" assert addr == b32.p2wpkh(pub) _, wit_prg, _ = b32.witness_from_address(addr) assert wit_prg == hash160(pub) uncompr_pub = bytes_from_point(point_from_octets(pub), compressed=False) err_msg = "not a private or compressed public key: " with pytest.raises(BTClibValueError, match=err_msg): b32.p2wpkh(uncompr_pub) with pytest.raises(BTClibValueError, match=err_msg): b32.p2wpkh(pub + "0A") err_msg = "invalid size: " with pytest.raises(BTClibValueError, match=err_msg): b32.address_from_witness(0, hash160(pub) + b"\x00")
def assert_as_valid(msg: Octets, addr: String, sig: Union[Sig, String], lower_s: bool = True) -> None: # Private function for test/dev purposes # It raises Errors, while verify should always return True or False if isinstance(sig, Sig): sig.assert_valid() else: sig = Sig.b64decode(sig) # first two bits in rf are reserved for key_id # key_id = 00; key_id = 01; key_id = 10; key_id = 11 # 27-27 = 000000; 28-27 = 000001; 29-27 = 000010; 30-27 = 000011 # 31-27 = 000100; 32-27 = 000101; 33-27 = 000110; 34-27 = 000111 # 35-27 = 001000; 36-27 = 001001; 37-27 = 001010; 38-27 = 001011 # 39-27 = 001100; 40-27 = 001101; 41-27 = 001110; 42-27 = 001111 key_id = sig.rf - 27 & 0b11 magic_msg = magic_message(msg) Q = dsa.recover_pub_key(key_id, magic_msg, sig.dsa_sig, lower_s, sha256) compressed = sig.rf > 30 # signature is valid only if the provided address is matched pub_key = bytes_from_point(Q, compressed=compressed) if has_segwit_prefix(addr): wit_ver, h160, _ = witness_from_address(addr) if wit_ver != 0 or len(h160) != 20: raise BTClibValueError(f"not a p2wpkh address: {addr!r}") if not (30 < sig.rf < 35 or sig.rf > 38): raise BTClibValueError( f"invalid p2wpkh address recovery flag: {sig.rf}") if hash160(pub_key) != h160: raise BTClibValueError(f"invalid p2wpkh address: {addr!r}") return script_type, h160, _ = h160_from_address(addr) if script_type == "p2pkh": if sig.rf > 34: raise BTClibValueError( f"invalid p2pkh address recovery flag: {sig.rf}") if hash160(pub_key) != h160: raise BTClibValueError(f"invalid p2pkh address: {addr!r}") return # must be P2WPKH-P2SH if not 30 < sig.rf < 39: raise BTClibValueError( f"invalid p2wpkh-p2sh address recovery flag: {sig.rf}") script_pk = b"\x00\x14" + hash160(pub_key) if hash160(script_pk) != h160: raise BTClibValueError(f"invalid p2wpkh-p2sh address: {addr!r}")
def test_p2wpkh() -> None: # self-consistency pub_key = "02 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" payload = hash160(pub_key) script_pub_key = serialize(["OP_0", payload]) assert_p2wpkh(script_pub_key) assert script_pub_key == ScriptPubKey.p2wpkh(pub_key).script assert ("p2wpkh", payload) == type_and_payload(script_pub_key) # bech32 address network = "mainnet" addr = b32.p2wpkh(pub_key, network) assert addr == address(script_pub_key, network) assert addr == b32.address_from_witness(0, payload, network) # back from the address to the script_pub_key assert script_pub_key == ScriptPubKey.from_address(addr).script assert network == ScriptPubKey.from_address(addr).network # p2sh-wrapped base58 address addr = b58.p2wpkh_p2sh(pub_key, network) assert addr == "3BJxz2r8zY7LxJfdGjUpjjHNh6YEiitvf2" err_msg = "invalid witness version: " with pytest.raises(BTClibValueError, match=err_msg): assert_p2wpkh(b"\x33" + script_pub_key[1:]) err_msg = "invalid pub_key hash length marker: " with pytest.raises(BTClibValueError, match=err_msg): assert_p2wpkh(script_pub_key[:1] + b"\x00" + script_pub_key[2:])
def test_p2sh() -> None: # https://medium.com/@darosior/bitcoin-raw-transactions-part-2-p2sh-94df206fee8d network = "mainnet" address = "37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP" script_pub_key = serialize([ "OP_2DUP", "OP_EQUAL", "OP_NOT", "OP_VERIFY", "OP_SHA1", "OP_SWAP", "OP_SHA1", "OP_EQUAL", ]) assert script_pub_key.hex() == "6e879169a77ca787" assert address == b58.p2sh(script_pub_key, network) script_hash = hash160(script_pub_key) assert ("p2sh", script_hash, network) == b58.h160_from_address(address) assert ("p2sh", script_hash, network) == b58.h160_from_address(" " + address + " ") assert script_hash.hex() == "4266fc6f2c2861d7fe229b279a79803afca7ba34" script_sig: List[Command] = ["OP_HASH160", script_hash.hex(), "OP_EQUAL"] serialize(script_sig)
def assert_signable(self) -> None: self.assert_valid() for i, tx_in in enumerate(self.tx.vin): non_witness_utxo = self.inputs[i].non_witness_utxo witness_utxo = self.inputs[i].witness_utxo redeem_script = self.inputs[i].redeem_script if witness_utxo: script_pub_key = witness_utxo.script_pub_key script_type, payload = type_and_payload(script_pub_key.script) if script_type == "p2sh": script_type, _ = type_and_payload(redeem_script) if script_type not in ("p2wpkh", "p2wsh"): raise BTClibValueError( "script type not it ('p2wpkh', 'p2wsh')") elif non_witness_utxo: script_pub_key = non_witness_utxo.vout[ tx_in.prev_out.vout].script_pub_key _, payload = type_and_payload(script_pub_key.script) else: err_msg = "missing script_pub_key" raise BTClibValueError(err_msg) if redeem_script and payload != hash160(redeem_script): raise BTClibValueError("invalid redeem script hash160") if self.inputs[i].witness_script: if redeem_script: _, payload = type_and_payload(redeem_script) if payload != sha256(self.inputs[i].witness_script): raise BTClibValueError("invalid witness script sha256")
def p2pkh(key: Key, network: Optional[str] = None, compressed: Optional[bool] = None) -> str: "Return the p2pkh base58 address corresponding to a public key." pub_key, network = pub_keyinfo_from_key(key, network, compressed=compressed) return address_from_h160("p2pkh", hash160(pub_key), network)
def fingerprint(key: Key, network: Optional[str] = None) -> bytes: """Return the public key fingerprint from a private/public key. The fingerprint is the last four bytes of the compressed public key HASH160. """ pub_key, _ = pub_keyinfo_from_key(key, network, compressed=True) return hash160(pub_key)[:4]
def test_derive_exceptions() -> None: # root key, zero depth rootmxprv = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv = BIP32KeyData.b58decode(rootmxprv) # FIXME # assert xprv == _derive(xprv, "m") assert rootmxprv == derive(xprv, "m") assert rootmxprv == derive(xprv, "") fingerprint = hashes.hash160(pub_keyinfo_from_key(xprv)[0])[:4] assert fingerprint == _derive(xprv, bytes.fromhex("80000000")).parent_fingerprint for der_path in ("/1", "800000", "80000000"): xkey = _derive(xprv, der_path) assert fingerprint == xkey.parent_fingerprint err_msg = "invalid literal for int" for der_path in (";/0", "invalid index"): with pytest.raises(ValueError, match=err_msg): derive(xprv, der_path) with pytest.raises(BTClibValueError, match="depth greater than 255: "): derive(xprv, "m" + 256 * "/0") with pytest.raises(BTClibValueError, match="index are not a multiple of 4-bytes: "): derive(xprv, b"\x00" * 5) for index in (2**32, 0x8000000000): with pytest.raises(OverflowError, match="int too big to convert"): derive(xprv, index) xprv = _derive(xprv, "1") err_msg = "final depth greater than 255: " with pytest.raises(BTClibValueError, match=err_msg): derive(xprv, "m" + 255 * "/0") rootxprv = "xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS" temp = base58.b58decode(rootxprv) bad_xprv = base58.b58encode(temp[:45] + b"\x02" + temp[46:], 78) err_msg = "invalid private key prefix: " with pytest.raises(BTClibValueError, match=err_msg): derive(bad_xprv, 0x80000000) xpub = xpub_from_xprv(rootxprv) temp = base58.b58decode(xpub) bad_xpub = base58.b58encode(temp[:45] + b"\x00" + temp[46:], 78) err_msg = r"invalid public key prefix not in \(0x02, 0x03\): " with pytest.raises(BTClibValueError, match=err_msg): derive(bad_xpub, 0x80000000) err_msg = "hardened derivation from public key" with pytest.raises(BTClibValueError, match=err_msg): derive(xpub, 0x80000000)
def p2sh( cls: Type["ScriptPubKey"], redeem_script: Octets, network: str = "mainnet", check_validity: bool = True, ) -> "ScriptPubKey": "Return the p2sh ScriptPubKey of the provided redeem script." script_h160 = hash160(redeem_script) script = serialize(["OP_HASH160", script_h160, "OP_EQUAL"]) return cls(script, network, check_validity)
def test_exceptions() -> None: pub_key = "02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" payload = b"\xf5" + hash160(pub_key) invalid_address = b58encode(payload) with pytest.raises(BTClibValueError, match="invalid base58 address prefix: "): b58.h160_from_address(invalid_address) with pytest.raises(BTClibValueError, match="not a private or public key: "): b58.p2pkh(pub_key + "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 == b58.wif_from_prv_key(q, network, compressed) assert prv_keyinfo_from_prv_key(wif) == (q, network, compressed) assert address == b58.p2pkh(wif) script_type, payload, net = b58.h160_from_address(address) assert net == network assert script_type == "p2pkh" if compressed: b32_address = b32.p2wpkh(wif) assert (0, payload, net) == b32.witness_from_address(b32_address) b58_address = b58.p2wpkh_p2sh(wif) script_bin = hash160(b"\x00\x14" + payload) assert ("p2sh", script_bin, net) == b58.h160_from_address(b58_address) else: err_msg = "not a private or compressed public key: " with pytest.raises(BTClibValueError, match=err_msg): b32.p2wpkh(wif) # type: ignore with pytest.raises(BTClibValueError, match=err_msg): b58.p2wpkh_p2sh(wif) # type: ignore
def __ckd(xkey: _ExtendedBIP32KeyData, index: int) -> None: xkey.depth += 1 xkey.index = index if xkey.is_private: Q_bytes = bytes_from_point(mult(xkey.prv_key_int)) xkey.parent_fingerprint = hash160(Q_bytes)[:4] if xkey.is_hardened: # hardened derivation hmac_ = hmac.new( xkey.chain_code, xkey.key + index.to_bytes(4, byteorder="big", signed=False), "sha512", ).digest() else: # normal derivation hmac_ = hmac.new( xkey.chain_code, Q_bytes + index.to_bytes(4, byteorder="big", signed=False), "sha512", ).digest() xkey.chain_code = hmac_[32:] offset = int.from_bytes(hmac_[:32], byteorder="big", signed=False) xkey.prv_key_int = (xkey.prv_key_int + offset) % ec.n xkey.key = b"\x00" + xkey.prv_key_int.to_bytes( 32, byteorder="big", signed=False ) xkey.pub_key_point = INF else: # public key xkey.parent_fingerprint = hash160(xkey.key)[:4] if xkey.is_hardened: raise BTClibValueError("invalid hardened derivation from public key") hmac_ = hmac.new( xkey.chain_code, xkey.key + index.to_bytes(4, byteorder="big", signed=False), "sha512", ).digest() xkey.chain_code = hmac_[32:] offset = int.from_bytes(hmac_[:32], byteorder="big", signed=False) xkey.pub_key_point = ec.add(xkey.pub_key_point, mult(offset)) xkey.key = bytes_from_point(xkey.pub_key_point) xkey.prv_key_int = 0
def p2wpkh( cls: Type["ScriptPubKey"], key: Key, check_validity: bool = True, ) -> "ScriptPubKey": """Return the p2wpkh ScriptPubKey of the provided key. If the provided key is a public one, it must be compressed. """ pub_key, network = pub_keyinfo_from_key(key, compressed=True) script = serialize(["OP_0", hash160(pub_key)]) return cls(script, network, check_validity)
def test_p2w_p2sh() -> None: pub_key_str = "03 a1af804ac108a8a51782198c2d034b28bf90c8803f5a53f76276fa69a4eae77f" pub_key, network = pub_keyinfo_from_key(pub_key_str, compressed=True) witness_program = hash160(pub_key) b58addr = b58.p2wpkh_p2sh(pub_key, network) assert b58addr == "36NvZTcMsMowbt78wPzJaHHWaNiyR73Y4g" script_pub_key = serialize([ "OP_DUP", "OP_HASH160", witness_program, "OP_EQUALVERIFY", "OP_CHECKSIG" ]) b58addr = b58.p2wsh_p2sh(script_pub_key, network) assert b58addr == "3QHRam4Hvp1GZVkgjoKWUC1GEd8ck8e4WX"
def test_wrapped_p2tr() -> None: script = [ "OP_1", "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf", ] utxo = TxOut( 100000000, serialize(["OP_HASH160", hash160(serialize(script)), "OP_EQUAL"])) tx_in = TxIn(OutPoint(), serialize(script), 1, Witness(["0A" * 32])) tx = Tx(vin=[tx_in], vout=[TxOut(100000000, "")]) err_msg = "Taproot scripts cannot be wrapped in p2sh" with pytest.raises(BTClibValueError, match=err_msg): sig_hash.from_tx([utxo], tx, 0, 0)
def crack_prv_key(parent_xpub: BIP32Key, child_xprv: BIP32Key) -> str: if isinstance(parent_xpub, BIP32KeyData): p = copy.copy(parent_xpub) else: p = BIP32KeyData.b58decode(parent_xpub) if p.key[0] not in (2, 3): err_msg = "extended parent key is not a public key: " err_msg += f"{p.b58encode()}" raise BTClibValueError(err_msg) if isinstance(child_xprv, BIP32KeyData): c = child_xprv else: c = BIP32KeyData.b58decode(child_xprv) if c.key[0] != 0: err_msg = "extended child key is not a private key: " err_msg += f"{c.b58encode()}" raise BTClibValueError(err_msg) # check depth if c.depth != p.depth + 1: raise BTClibValueError("not a parent's child: wrong depths") # check fingerprint if c.parent_fingerprint != hash160(p.key)[:4]: raise BTClibValueError( "not a parent's child: wrong parent fingerprint") if c.is_hardened: raise BTClibValueError("hardened child derivation") p.version = c.version hmac_ = hmac.new( p.chain_code, p.key + c.index.to_bytes(4, byteorder="big", signed=False), "sha512", ).digest() child_q = int.from_bytes(c.key[1:], byteorder="big", signed=False) offset = int.from_bytes(hmac_[:32], byteorder="big", signed=False) parent_q = (child_q - offset) % ec.n p.key = b"\x00" + parent_q.to_bytes(32, byteorder="big", signed=False) return p.b58encode()
def p2pkh( cls: Type["ScriptPubKey"], key: Key, compressed: Optional[bool] = None, network: Optional[str] = None, check_validity: bool = True, ) -> "ScriptPubKey": "Return the p2pkh ScriptPubKey of the provided key." pub_key, network = pub_keyinfo_from_key(key, network, compressed=compressed) script = serialize([ "OP_DUP", "OP_HASH160", hash160(pub_key), "OP_EQUALVERIFY", "OP_CHECKSIG" ]) return cls(script, network, check_validity)
def test_p2pkh() -> None: # self-consistency pub_key = ( "04 " "cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" "f7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4") payload = hash160(pub_key) script_pub_key = serialize( ["OP_DUP", "OP_HASH160", payload, "OP_EQUALVERIFY", "OP_CHECKSIG"]) assert_p2pkh(script_pub_key) assert script_pub_key == ScriptPubKey.p2pkh(pub_key).script assert ("p2pkh", payload) == type_and_payload(script_pub_key) # base58 address network = "mainnet" addr = b58.p2pkh(pub_key, network) assert addr == address(script_pub_key, network) assert addr == b58.address_from_h160("p2pkh", payload, network) # back from the address to the script_pub_key assert script_pub_key == ScriptPubKey.from_address(addr).script assert network == ScriptPubKey.from_address(addr).network # documented test case: https://learnmeabitcoin.com/guide/p2pkh payload = bytes.fromhex("12ab8dc588ca9d5787dde7eb29569da63c3a238c") script_pub_key = bytes.fromhex("76a914") + payload + bytes.fromhex("88ac") assert_p2pkh(script_pub_key) addr = "12higDjoCCNXSA95xZMWUdPvXNmkAduhWv" assert addr == address(script_pub_key, network) assert script_pub_key == ScriptPubKey.from_address(addr).script assert network == ScriptPubKey.from_address(addr).network err_msg = "missing final OP_EQUALVERIFY, OP_CHECKSIG" with pytest.raises(BTClibValueError, match=err_msg): assert_p2pkh(script_pub_key[:-2] + b"\x40\x40") err_msg = "missing leading OP_DUP, OP_HASH160" with pytest.raises(BTClibValueError, match=err_msg): assert_p2pkh(b"\x40\x40" + script_pub_key[2:]) err_msg = "invalid pub_key hash length marker: " with pytest.raises(BTClibValueError, match=err_msg): assert_p2pkh(script_pub_key[:2] + b"\x40" + script_pub_key[3:])
def test_p2sh() -> None: # self-consistency pub_key = "02 cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaf" redeem_script = ScriptPubKey.p2pkh(pub_key).script payload = hash160(redeem_script) script_pub_key = serialize(["OP_HASH160", payload, "OP_EQUAL"]) assert_p2sh(script_pub_key) assert script_pub_key == ScriptPubKey.p2sh(redeem_script).script assert ("p2sh", payload) == type_and_payload(script_pub_key) # base58 address network = "mainnet" addr = b58.p2sh(redeem_script, network) assert addr == address(script_pub_key, network) assert addr == b58.address_from_h160("p2sh", payload, network) # back from the address to the script_pub_key assert script_pub_key == ScriptPubKey.from_address(addr).script assert network == ScriptPubKey.from_address(addr).network # documented test case: https://learnmeabitcoin.com/guide/p2sh payload = bytes.fromhex("748284390f9e263a4b766a75d0633c50426eb875") script_pub_key = bytes.fromhex("a914") + payload + bytes.fromhex("87") assert_p2sh(script_pub_key) addr = "3CK4fEwbMP7heJarmU4eqA3sMbVJyEnU3V" assert addr == address(script_pub_key, network) assert script_pub_key == ScriptPubKey.from_address(addr).script assert network == ScriptPubKey.from_address(addr).network err_msg = "missing final OP_EQUAL" with pytest.raises(BTClibValueError, match=err_msg): assert_p2sh(script_pub_key[:-1] + b"\x40") err_msg = "missing leading OP_HASH160" with pytest.raises(BTClibValueError, match=err_msg): assert_p2sh(b"\x40" + script_pub_key[1:]) err_msg = "invalid redeem script hash length marker: " with pytest.raises(BTClibValueError, match=err_msg): assert_p2sh(script_pub_key[:1] + b"\x40" + script_pub_key[2:])
def p2sh(script_pub_key: Octets, network: str = "mainnet") -> str: "Return the p2sh base58 address corresponding to a script_pub_key." h160 = hash160(script_pub_key) return address_from_h160("p2sh", h160, network)
def p2wpkh_p2sh(key: Key, network: Optional[str] = None) -> str: "Return the p2wpkh-p2sh base58 address corresponding to a public key." pub_key, network = pub_keyinfo_from_key(key, network, compressed=True) witness_program = hash160(pub_key) return _address_from_v0_witness(witness_program, network)
print("M") print(ext_pub) assert ( ext_prv == b"xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6" ), "failure" assert ( ext_pub == b"xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13" ), "failure" # ==first (0) hardened child== depth = b"\x01" child_n = 0 + 0x80000000 # hardened child_number = child_n.to_bytes(4, "big") fingerprint = hash160(Qbytes)[:4] idf = depth + fingerprint + child_number key = qbytes if child_number[0] > 127 else Qbytes hd = hmac.digest(chain_code, key + child_number, "sha512") p = (p + int(hd[:32].hex(), 16)) % ec.n qbytes = b"\x00" + p.to_bytes(32, "big") Q = mult(p, ec.G) Qbytes = (b"\x02" if (Q[1] % 2 == 0) else b"\x03") + Q[0].to_bytes(32, "big") chain_code = hd[32:] ext_prv = b58encode(xprv + idf + chain_code + qbytes) print("\nm/0'") print(ext_prv) ext_pub = b58encode(xpub + idf + chain_code + Qbytes) print("M/0'")
def _assert_valid_hash160_preimages( hash160_preimages: Mapping[bytes, bytes]) -> None: for h, preimage in hash160_preimages.items(): if hash160(preimage) != h: raise BTClibValueError("Invalid HASH160 preimage")
def p2wpkh(key: Key, network: Optional[str] = None) -> str: "Return the p2wpkh bech32 address corresponding to a public key." pub_key, network = pub_keyinfo_from_key(key, network, compressed=True) return address_from_witness(0, hash160(pub_key), network)
def test_hash160_hash256() -> None: test_vectors = (plain_prv_keys + net_unaware_compressed_pub_keys + net_unaware_uncompressed_pub_keys) for hexstring in test_vectors: hash160(hexstring) hash256(hexstring)