def address_multisig_p2sh(pubkeys: List[bytes], m: int, coin: CoinInfo) -> str: if coin.address_type_p2sh is None: raise AddressError(FailureType.ProcessError, "Multisig not enabled on this coin") redeem_script = output_script_multisig(pubkeys, m) redeem_script_hash = coin.script_hash(redeem_script) return address_p2sh(redeem_script_hash, coin)
def ecdsa_hash_pubkey(pubkey: bytes, coin: CoinInfo) -> bytes: if pubkey[0] == 0x04: ensure(len(pubkey) == 65) # uncompressed format elif pubkey[0] == 0x00: ensure(len(pubkey) == 1) # point at infinity else: ensure(len(pubkey) == 33) # compresssed format return coin.script_hash(pubkey)
def address_p2wsh_in_p2sh(witness_script_hash: bytes, coin: CoinInfo) -> str: redeem_script = output_script_native_p2wpkh_or_p2wsh(witness_script_hash) redeem_script_hash = coin.script_hash(redeem_script) return address_p2sh(redeem_script_hash, coin)
def address_p2wpkh_in_p2sh(pubkey: bytes, coin: CoinInfo) -> str: pubkey_hash = ecdsa_hash_pubkey(pubkey, coin) redeem_script = output_script_native_p2wpkh_or_p2wsh(pubkey_hash) redeem_script_hash = coin.script_hash(redeem_script) return address_p2sh(redeem_script_hash, coin)
def address_pkh(pubkey: bytes, coin: CoinInfo) -> str: s = address_type.tobytes(coin.address_type) + coin.script_hash(pubkey) return base58.encode_check(bytes(s), coin.b58_hash)
def address_multisig_p2sh(pubkeys: list[bytes], m: int, coin: CoinInfo) -> str: if coin.address_type_p2sh is None: raise wire.ProcessError("Multisig not enabled on this coin") redeem_script = HashWriter(coin.script_hash()) write_output_script_multisig(redeem_script, pubkeys, m) return address_p2sh(redeem_script.get_digest(), coin)
def address_p2wsh_in_p2sh(witness_script_hash: bytes, coin: CoinInfo) -> str: redeem_script = output_script_native_segwit(0, witness_script_hash) redeem_script_hash = coin.script_hash(redeem_script).digest() return address_p2sh(redeem_script_hash, coin)
def __init__( self, script_pubkey: bytes, script_sig: bytes | None, witness: bytes | None, coin: CoinInfo, ): self.threshold = 1 self.public_keys: list[memoryview] = [] self.signatures: list[tuple[memoryview, SigHashType]] = [] self.is_taproot = False if not script_sig: if not witness: raise wire.DataError("Signature data not provided") if len(script_pubkey) == 22: # P2WPKH public_key, signature, hash_type = parse_witness_p2wpkh(witness) pubkey_hash = ecdsa_hash_pubkey(public_key, coin) if output_script_native_segwit(0, pubkey_hash) != script_pubkey: raise wire.DataError("Invalid public key hash") self.public_keys = [public_key] self.signatures = [(signature, hash_type)] elif len(script_pubkey) == 34 and script_pubkey[0] == OP_0: # P2WSH script, self.signatures = parse_witness_multisig(witness) script_hash = sha256(script).digest() if output_script_native_segwit(0, script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys, self.threshold = parse_output_script_multisig(script) elif len(script_pubkey) == 34 and script_pubkey[0] == OP_1: # P2TR self.is_taproot = True self.public_keys = [parse_output_script_p2tr(script_pubkey)] self.signatures = [parse_witness_p2tr(witness)] else: raise wire.DataError("Unsupported signature script") elif witness and witness != b"\x00": if len(script_sig) == 23: # P2WPKH nested in BIP16 P2SH public_key, signature, hash_type = parse_witness_p2wpkh(witness) pubkey_hash = ecdsa_hash_pubkey(public_key, coin) w = utils.empty_bytearray(23) write_input_script_p2wpkh_in_p2sh(w, pubkey_hash) if w != script_sig: raise wire.DataError("Invalid public key hash") script_hash = coin.script_hash(script_sig[1:]).digest() if output_script_p2sh(script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys = [public_key] self.signatures = [(signature, hash_type)] elif len(script_sig) == 35: # P2WSH nested in BIP16 P2SH script, self.signatures = parse_witness_multisig(witness) script_hash = sha256(script).digest() w = utils.empty_bytearray(35) write_input_script_p2wsh_in_p2sh(w, script_hash) if w != script_sig: raise wire.DataError("Invalid script hash") script_hash = coin.script_hash(script_sig[1:]).digest() if output_script_p2sh(script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys, self.threshold = parse_output_script_multisig(script) else: raise wire.DataError("Unsupported signature script") else: if len(script_pubkey) == 25: # P2PKH public_key, signature, hash_type = parse_input_script_p2pkh(script_sig) pubkey_hash = ecdsa_hash_pubkey(public_key, coin) if output_script_p2pkh(pubkey_hash) != script_pubkey: raise wire.DataError("Invalid public key hash") self.public_keys = [public_key] self.signatures = [(signature, hash_type)] elif len(script_pubkey) == 23: # P2SH script, self.signatures = parse_input_script_multisig(script_sig) script_hash = coin.script_hash(script).digest() if output_script_p2sh(script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys, self.threshold = parse_output_script_multisig(script) else: raise wire.DataError("Unsupported signature script") if self.threshold != len(self.signatures): raise wire.DataError("Invalid signature")
def __init__( self, script_pubkey: bytes, script_sig: bytes | None, witness: bytes | None, coin: CoinInfo, ): self.threshold = 1 self.public_keys: list[bytes] = [] self.signatures: list[tuple[bytes, int]] = [] if not script_sig: if not witness: raise wire.DataError("Signature data not provided") if len(script_pubkey) == 22: # P2WPKH public_key, signature, hash_type = parse_witness_p2wpkh( witness) pubkey_hash = ecdsa_hash_pubkey(public_key, coin) if output_script_native_p2wpkh_or_p2wsh( pubkey_hash) != script_pubkey: raise wire.DataError("Invalid public key hash") self.public_keys = [public_key] self.signatures = [(signature, hash_type)] elif len(script_pubkey) == 34: # P2WSH script, self.signatures = parse_witness_multisig(witness) script_hash = sha256(script).digest() if output_script_native_p2wpkh_or_p2wsh( script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys, self.threshold = parse_output_script_multisig( script) else: raise wire.DataError("Unsupported signature script") elif witness and witness != b"\x00": if len(script_sig) == 23: # P2WPKH nested in BIP16 P2SH public_key, signature, hash_type = parse_witness_p2wpkh( witness) pubkey_hash = ecdsa_hash_pubkey(public_key, coin) if input_script_p2wpkh_in_p2sh(pubkey_hash) != script_sig: raise wire.DataError("Invalid public key hash") script_hash = coin.script_hash(script_sig[1:]) if output_script_p2sh(script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys = [public_key] self.signatures = [(signature, hash_type)] elif len(script_sig) == 35: # P2WSH nested in BIP16 P2SH script, self.signatures = parse_witness_multisig(witness) script_hash = sha256(script).digest() if input_script_p2wsh_in_p2sh(script_hash) != script_sig: raise wire.DataError("Invalid script hash") script_hash = coin.script_hash(script_sig[1:]) if output_script_p2sh(script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys, self.threshold = parse_output_script_multisig( script) else: raise wire.DataError("Unsupported signature script") else: if len(script_pubkey) == 25: # P2PKH public_key, signature, hash_type = parse_input_script_p2pkh( script_sig) pubkey_hash = ecdsa_hash_pubkey(public_key, coin) if output_script_p2pkh(pubkey_hash) != script_pubkey: raise wire.DataError("Invalid public key hash") self.public_keys = [public_key] self.signatures = [(signature, hash_type)] elif len(script_pubkey) == 23: # P2SH script, self.signatures = parse_input_script_multisig( script_sig) script_hash = coin.script_hash(script) if output_script_p2sh(script_hash) != script_pubkey: raise wire.DataError("Invalid script hash") self.public_keys, self.threshold = parse_output_script_multisig( script) else: raise wire.DataError("Unsupported signature script") if self.threshold != len(self.signatures): raise wire.DataError("Invalid signature")