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
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
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
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
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
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
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
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)
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
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
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
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))
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")
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
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
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
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
def decode(cbor: bytes) -> Value: r = utils.BufferReader(cbor) res = _cbor_decode(r) if r.remaining_count(): raise ValueError return res