예제 #1
0
def parse_witness_multisig(
        witness: bytes) -> Tuple[bytes, List[Tuple[bytes, int]]]:
    try:
        r = utils.BufferReader(witness)

        # Get number of witness stack items.
        item_count = read_bitcoin_varint(r)

        # Skip over OP_FALSE, which is due to the old OP_CHECKMULTISIG bug.
        if r.get() != 0:
            raise ValueError

        signatures = []
        for i in range(item_count - 2):
            n = read_bitcoin_varint(r)
            signature = r.read(n - 1)
            hash_type = r.get()
            signatures.append((signature, hash_type))

        script = read_bytes_prefixed(r)
        if r.remaining_count():
            raise ValueError
    except (ValueError, EOFError):
        raise wire.DataError("Invalid witness.")

    return script, signatures
예제 #2
0
def verify_nonownership(
    proof: bytes,
    script_pubkey: bytes,
    commitment_data: bytes | None,
    keychain: Keychain,
    coin: CoinInfo,
) -> bool:
    try:
        r = utils.BufferReader(proof)
        if r.read_memoryview(4) != _VERSION_MAGIC:
            raise wire.DataError("Unknown format of proof of ownership")

        flags = r.get()
        if flags & 0b1111_1110:
            raise wire.DataError("Unknown flags in proof of ownership")

        # Determine whether our ownership ID appears in the proof.
        id_count = read_bitcoin_varint(r)
        ownership_id = get_identifier(script_pubkey, keychain)
        not_owned = True
        for _ in range(id_count):
            if utils.consteq(ownership_id,
                             r.read_memoryview(_OWNERSHIP_ID_LEN)):
                not_owned = False

        # Verify the BIP-322 SignatureProof.

        proof_body = memoryview(proof)[:r.offset]
        if commitment_data is None:
            commitment_data = bytes()

        sighash = HashWriter(sha256(proof_body))
        write_bytes_prefixed(sighash, script_pubkey)
        write_bytes_prefixed(sighash, commitment_data)
        script_sig, witness = read_bip322_signature_proof(r)

        # We don't call verifier.ensure_hash_type() to avoid possible compatibility
        # issues between implementations, because the hash type doesn't influence
        # the digest and the value to use is not defined in BIP-322.
        verifier = SignatureVerifier(script_pubkey, script_sig, witness, coin)
        verifier.verify(sighash.get_digest())
    except (ValueError, EOFError):
        raise wire.DataError("Invalid proof of ownership")

    return not_owned
예제 #3
0
def read_scriptsig_witness(
        ownership_proof: bytes) -> tuple[memoryview, memoryview]:
    try:
        r = utils.BufferReader(ownership_proof)
        if r.read_memoryview(4) != _VERSION_MAGIC:
            raise wire.DataError("Unknown format of proof of ownership")

        flags = r.get()
        if flags & 0b1111_1110:
            raise wire.DataError("Unknown flags in proof of ownership")

        # Skip ownership IDs.
        id_count = read_bitcoin_varint(r)
        r.read_memoryview(_OWNERSHIP_ID_LEN * id_count)

        return read_bip322_signature_proof(r)

    except (ValueError, EOFError):
        raise wire.DataError("Invalid proof of ownership")
예제 #4
0
def parse_witness_p2wpkh(witness: bytes) -> Tuple[bytes, bytes, int]:
    try:
        r = utils.BufferReader(witness)

        if r.get() != 2:
            # num of stack items, in P2WPKH it's always 2
            raise ValueError

        n = read_bitcoin_varint(r)
        signature = r.read(n - 1)
        hash_type = r.get()

        pubkey = read_bytes_prefixed(r)
        if r.remaining_count():
            raise ValueError
    except (ValueError, EOFError):
        raise wire.DataError("Invalid witness.")

    return pubkey, signature, hash_type
예제 #5
0
def parse_witness_p2wpkh(
        witness: bytes) -> tuple[memoryview, memoryview, SigHashType]:
    try:
        r = utils.BufferReader(witness)

        if r.get() != 2:
            # num of stack items, in P2WPKH it's always 2
            raise ValueError

        n = read_bitcoin_varint(r)
        signature = r.read_memoryview(n - 1)
        sighash_type = SigHashType.from_int(r.get())

        pubkey = read_memoryview_prefixed(r)
        if r.remaining_count():
            raise ValueError
    except (ValueError, EOFError):
        raise wire.DataError("Invalid witness.")

    return pubkey, signature, sighash_type
예제 #6
0
def parse_witness_p2tr(witness: bytes) -> tuple[memoryview, SigHashType]:
    try:
        r = utils.BufferReader(witness)

        if r.get() != 1:  # Number of stack items.
            # Only Taproot key path spending without annex is supported.
            raise ValueError

        n = read_bitcoin_varint(r)
        if n not in (64, 65):
            raise ValueError

        signature = r.read_memoryview(64)
        if n == 65:
            sighash_type = SigHashType.from_int(r.get())
        else:
            sighash_type = SigHashType.SIGHASH_ALL_TAPROOT

        if r.remaining_count():
            raise ValueError
    except (ValueError, EOFError):
        raise wire.DataError("Invalid witness.")

    return signature, sighash_type
예제 #7
0
def read_bytes_prefixed(r: BytearrayReader) -> bytes:
    n = read_bitcoin_varint(r)
    return r.read(n)
예제 #8
0
def read_memoryview_prefixed(r: BufferReader) -> memoryview:
    n = read_bitcoin_varint(r)
    return r.read_memoryview(n)