Exemple #1
0
def encode_chunked(value: Value, max_chunk_size: int) -> Iterator[bytes]:
    """
    Returns the encoded value as an iterable of chunks of a given size,
    removing the need to reserve a continuous chunk of memory for the
    full serialized representation of the value.
    """
    if max_chunk_size <= 0:
        raise ValueError

    chunks = encode_streamed(value)

    chunk_buffer = writers.empty_bytearray(max_chunk_size)
    try:
        current_chunk_view = utils.BufferReader(next(chunks))
        while True:
            num_bytes_to_write = min(
                current_chunk_view.remaining_count(),
                max_chunk_size - len(chunk_buffer),
            )
            chunk_buffer.extend(current_chunk_view.read(num_bytes_to_write))

            if len(chunk_buffer) >= max_chunk_size:
                yield chunk_buffer
                chunk_buffer[:] = bytes()

            if current_chunk_view.remaining_count() == 0:
                current_chunk_view = utils.BufferReader(next(chunks))
    except StopIteration:
        if len(chunk_buffer) > 0:
            yield chunk_buffer
Exemple #2
0
def decode(cbor: bytes, offset: int = 0) -> Value:
    r = utils.BufferReader(cbor)
    r.seek(offset)
    res = _cbor_decode(r)
    if r.remaining_count():
        raise ValueError
    return res
Exemple #3
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
Exemple #4
0
def parse_input_script_multisig(
    script_sig: bytes,
) -> Tuple[bytes, List[Tuple[bytes, int]]]:
    try:
        r = utils.BufferReader(script_sig)

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

        signatures = []
        n = read_op_push(r)
        while r.remaining_count() > n:
            signature = r.read(n - 1)
            hash_type = r.get()
            signatures.append((signature, hash_type))
            n = read_op_push(r)

        script = r.read()
        if len(script) != n:
            raise ValueError
    except (ValueError, EOFError):
        raise wire.DataError("Invalid scriptSig.")

    return script, signatures
Exemple #5
0
def parse_output_script_multisig(script: bytes) -> Tuple[List[bytes], int]:
    try:
        r = utils.BufferReader(script)

        threshold = r.get() - 0x50
        pubkey_count = script[-2] - 0x50

        if (not 1 <= threshold <= 15 or not 1 <= pubkey_count <= 15
                or threshold > pubkey_count):
            raise ValueError

        public_keys = []
        for i in range(pubkey_count):
            n = read_op_push(r)
            if n != 33:
                raise ValueError
            public_keys.append(r.read(n))

        r.get()  # ignore pubkey_count
        if r.get() != 0xAE:  # OP_CHECKMULTISIG
            raise ValueError
        if r.remaining_count():
            raise ValueError

    except (ValueError, IndexError, EOFError):
        raise wire.DataError("Invalid multisig script")

    return public_keys, threshold
Exemple #6
0
def parse_witness_multisig(
    witness: bytes,
) -> tuple[memoryview, list[tuple[memoryview, SigHashType]]]:
    try:
        r = utils.BufferReader(witness)

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

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

        signatures = []
        for _ in range(item_count - 2):
            n = read_compact_size(r)
            signature = r.read_memoryview(n - 1)
            sighash_type = SigHashType.from_int(r.get())
            signatures.append((signature, sighash_type))

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

    return script, signatures
Exemple #7
0
    def __init__(self, iface: WireInterface, sid: int) -> None:
        self.iface = iface
        self.sid = sid
        self.buffer = bytearray(PROTOBUF_BUFFER_SIZE)
        self.buffer_reader = utils.BufferReader(self.buffer)
        self.buffer_writer = utils.BufferWriter(self.buffer)

        self._field_cache = {}  # type: protobuf.FieldCache
Exemple #8
0
def get() -> protobuf.MessageType | None:
    stored_auth_type = storage.cache.get(
        storage.cache.APP_COMMON_AUTHORIZATION_TYPE)
    if not stored_auth_type:
        return None

    msg_wire_type = int.from_bytes(stored_auth_type, "big")
    msg_type = messages.get_type(msg_wire_type)
    buffer = storage.cache.get(storage.cache.APP_COMMON_AUTHORIZATION_DATA)
    reader = utils.BufferReader(buffer)

    return protobuf.load_message(reader, msg_type)
Exemple #9
0
def parse_input_script_p2pkh(script_sig: bytes) -> Tuple[bytes, bytes, int]:
    try:
        r = utils.BufferReader(script_sig)
        n = read_op_push(r)
        signature = r.read(n - 1)
        hash_type = r.get()

        n = read_op_push(r)
        pubkey = r.read()
        if len(pubkey) != n:
            raise ValueError
    except (ValueError, EOFError):
        wire.DataError("Invalid scriptSig.")

    return pubkey, signature, hash_type
Exemple #10
0
def parse_input_script_p2pkh(
    script_sig: bytes, ) -> tuple[memoryview, memoryview, SigHashType]:
    try:
        r = utils.BufferReader(script_sig)
        n = read_op_push(r)
        signature = r.read_memoryview(n - 1)
        sighash_type = SigHashType.from_int(r.get())

        n = read_op_push(r)
        pubkey = r.read_memoryview()
        if len(pubkey) != n:
            raise ValueError
    except (ValueError, EOFError):
        raise wire.DataError("Invalid scriptSig.")

    return pubkey, signature, sighash_type
Exemple #11
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
Exemple #12
0
async def read_message(iface: WireInterface,
                       buffer: utils.BufferType) -> Message:
    read = loop.wait(iface.iface_num() | io.POLL_READ)

    # wait for initial report
    report = await read
    if report[0] != _REP_MARKER:
        raise CodecError("Invalid magic")
    _, magic1, magic2, mtype, msize = ustruct.unpack(_REP_INIT, report)
    if magic1 != _REP_MAGIC or magic2 != _REP_MAGIC:
        raise CodecError("Invalid magic")

    read_and_throw_away = False

    if msize > len(buffer):
        # allocate a new buffer to fit the message
        try:
            mdata: utils.BufferType = bytearray(msize)
        except MemoryError:
            mdata = bytearray(_REP_LEN)
            read_and_throw_away = True
    else:
        # reuse a part of the supplied buffer
        mdata = memoryview(buffer)[:msize]

    # buffer the initial data
    nread = utils.memcpy(mdata, 0, report, _REP_INIT_DATA)

    while nread < msize:
        # wait for continuation report
        report = await read
        if report[0] != _REP_MARKER:
            raise CodecError("Invalid magic")

        # buffer the continuation data
        if read_and_throw_away:
            nread += len(report) - 1
        else:
            nread += utils.memcpy(mdata, nread, report, _REP_CONT_DATA)

    if read_and_throw_away:
        raise CodecError("Message too large")

    return Message(mtype, utils.BufferReader(mdata))
Exemple #13
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")
Exemple #14
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
Exemple #15
0
def parse_output_script_p2tr(script_pubkey: bytes) -> memoryview:
    # 51 20 <32-byte-taproot-output-key>
    try:
        r = utils.BufferReader(script_pubkey)

        if r.get() != common.OP_1:
            # P2TR should be SegWit version 1
            raise ValueError

        if r.get() != 32:
            # taproot output key should be 32 bytes
            raise ValueError

        pubkey = r.read_memoryview(32)
        if r.remaining_count():
            raise ValueError
    except (ValueError, EOFError):
        raise wire.DataError("Invalid scriptPubKey.")

    return pubkey
Exemple #16
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
Exemple #17
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
Exemple #18
0
def decode(cbor: bytes) -> Value:
    r = utils.BufferReader(cbor)
    res = _cbor_decode(r)
    if r.remaining_count():
        raise ValueError
    return res