def _encode_data_with_bool_prefix(w: bytearray, data: bytes, expected_length: int): if data: helpers.write_bool(w, True) write_bytes_fixed(w, data, expected_length) else: helpers.write_bool(w, False)
def _encode_proposal(w: bytearray, proposal): write_uint8(w, helpers.OP_TAG_PROPOSALS) write_bytes_fixed(w, proposal.source, helpers.TAGGED_PUBKEY_HASH_SIZE) write_uint32_be(w, proposal.period) write_uint32_be(w, len(proposal.proposals) * helpers.PROPOSAL_HASH_SIZE) for proposal_hash in proposal.proposals: write_bytes_fixed(w, proposal_hash, helpers.PROPOSAL_HASH_SIZE)
def generate_proof( node: bip32.HDNode, script_type: EnumTypeInputScriptType, multisig: Optional[MultisigRedeemScriptType], coin: CoinInfo, user_confirmed: bool, ownership_ids: List[bytes], script_pubkey: bytes, commitment_data: bytes, ) -> Tuple[bytes, bytes]: flags = 0 if user_confirmed: flags |= _FLAG_USER_CONFIRMED proof = empty_bytearray(4 + 1 + 1 + len(ownership_ids) * _OWNERSHIP_ID_LEN) write_bytes_fixed(proof, _VERSION_MAGIC, 4) write_uint8(proof, flags) write_bitcoin_varint(proof, len(ownership_ids)) for ownership_id in ownership_ids: write_bytes_fixed(proof, ownership_id, _OWNERSHIP_ID_LEN) sighash = hashlib.sha256(proof) sighash.update(script_pubkey) sighash.update(commitment_data) signature = common.ecdsa_sign(node, sighash.digest()) public_key = node.public_key() write_bip322_signature_proof(proof, script_type, multisig, coin, public_key, signature) return proof, signature
def _encode_manager_delegation(w: bytearray, delegate): MICHELSON_LENGTH = 42 # length is fixed this time(no variable length fields) _encode_manager_common(w, MICHELSON_LENGTH, "PUSH") write_bytes_fixed(w, delegate, helpers.TAGGED_PUBKEY_HASH_SIZE) helpers.write_instruction(w, "SOME") helpers.write_instruction(w, "SET_DELEGATE") helpers.write_instruction(w, "CONS")
def write_tx_input_check(w: Writer, i: TxInput) -> None: write_bytes_fixed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index) write_uint32(w, i.script_type) write_uint32(w, len(i.address_n)) for n in i.address_n: write_uint32(w, n) write_uint32(w, i.sequence) write_uint64(w, i.amount or 0)
def write_tx_input_check(w: Writer, i: TxInput) -> None: write_bytes_fixed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index) write_uint32(w, i.script_type) write_uint8(w, input_is_external_unverified(i)) write_uint32(w, len(i.address_n)) for n in i.address_n: write_uint32(w, n) write_uint32(w, i.sequence) write_uint64(w, i.amount or 0) write_bytes_prefixed(w, i.script_pubkey or b"")
def _encode_common(w: bytearray, operation, str_operation): operation_tags = { "reveal": helpers.OP_TAG_REVEAL, "transaction": helpers.OP_TAG_TRANSACTION, "origination": helpers.OP_TAG_ORIGINATION, "delegation": helpers.OP_TAG_DELEGATION, } write_uint8(w, operation_tags[str_operation]) write_bytes_fixed(w, operation.source, helpers.TAGGED_PUBKEY_HASH_SIZE) _encode_zarith(w, operation.fee) _encode_zarith(w, operation.counter) _encode_zarith(w, operation.gas_limit) _encode_zarith(w, operation.storage_limit)
def output_script_sstxchange(addr: str) -> bytearray: try: raw_address = base58.decode_check(addr, blake256d_32) except ValueError: raise wire.DataError("Invalid address") w = utils.empty_bytearray(26) w.append(0xBD) # OP_SSTXCHANGE w.append(0x76) # OP_DUP w.append(0xA9) # OP_HASH160 w.append(0x14) # OP_DATA_20 write_bytes_fixed(w, raw_address[2:], 20) w.append(0x88) # OP_EQUALVERIFY w.append(0xAC) # OP_CHECKSIG return w
def _encode_manager_to_implicit_transfer(w: bytearray, manager_transfer): MICHELSON_LENGTH = 48 value_natural = bytearray() _encode_natural(value_natural, manager_transfer.amount) sequence_length = MICHELSON_LENGTH + len(value_natural) _encode_manager_common(w, sequence_length, "PUSH") write_bytes_fixed(w, manager_transfer.destination.hash, helpers.TAGGED_PUBKEY_HASH_SIZE) helpers.write_instruction(w, "IMPLICIT_ACCOUNT") helpers.write_instruction(w, "PUSH") helpers.write_instruction(w, "mutez") _encode_natural(w, manager_transfer.amount) helpers.write_instruction(w, "UNIT") helpers.write_instruction(w, "TRANSFER_TOKENS") helpers.write_instruction(w, "CONS")
def write_auth(w: Writer, auth: EosAuthorization) -> None: write_uint32_le(w, auth.threshold) write_variant32(w, len(auth.keys)) for key in auth.keys: write_variant32(w, key.type) write_bytes_fixed(w, key.key, 33) write_uint16_le(w, key.weight) write_variant32(w, len(auth.accounts)) for account in auth.accounts: write_uint64_le(w, account.account.actor) write_uint64_le(w, account.account.permission) write_uint16_le(w, account.weight) write_variant32(w, len(auth.waits)) for wait in auth.waits: write_uint32_le(w, wait.wait_sec) write_uint16_le(w, wait.weight)
def write_tx_input_check(w: Writer, i: TxInput) -> None: from .multisig import multisig_fingerprint write_uint32(w, len(i.address_n)) for n in i.address_n: write_uint32(w, n) write_bytes_fixed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index) write_bytes_prefixed(w, i.script_sig or b"") write_uint32(w, i.sequence) write_uint32(w, i.script_type) multisig_fp = multisig_fingerprint(i.multisig) if i.multisig else b"" write_bytes_prefixed(w, multisig_fp) write_uint64(w, i.amount or 0) write_bytes_prefixed(w, i.witness or b"") write_bytes_prefixed(w, i.ownership_proof or b"") write_bytes_prefixed(w, i.orig_hash or b"") write_uint32(w, i.orig_index or 0) write_bytes_prefixed(w, i.script_pubkey or b"")
def generate_proof( node: bip32.HDNode, script_type: InputScriptType, multisig: MultisigRedeemScriptType | None, coin: CoinInfo, user_confirmed: bool, ownership_ids: list[bytes], script_pubkey: bytes, commitment_data: bytes, ) -> tuple[bytes, bytes]: flags = 0 if user_confirmed: flags |= _FLAG_USER_CONFIRMED proof = utils.empty_bytearray(4 + 1 + 1 + len(ownership_ids) * _OWNERSHIP_ID_LEN) write_bytes_fixed(proof, _VERSION_MAGIC, 4) write_uint8(proof, flags) write_bitcoin_varint(proof, len(ownership_ids)) for ownership_id in ownership_ids: write_bytes_fixed(proof, ownership_id, _OWNERSHIP_ID_LEN) sighash = hashlib.sha256(proof) sighash.update(script_pubkey) sighash.update(commitment_data) if script_type in ( InputScriptType.SPENDADDRESS, InputScriptType.SPENDMULTISIG, InputScriptType.SPENDWITNESS, InputScriptType.SPENDP2SHWITNESS, ): signature = common.ecdsa_sign(node, sighash.digest()) elif script_type == InputScriptType.SPENDTAPROOT: signature = common.bip340_sign(node, sighash.digest()) else: raise wire.DataError("Unsupported script type.") public_key = node.public_key() write_bip322_signature_proof(proof, script_type, multisig, coin, public_key, signature) return proof, signature
def write_auth(w: Writer, auth: EosAuthorization) -> None: write_uint32_le(w, auth.threshold) write_uvarint(w, len(auth.keys)) for key in auth.keys: if key.key is None: raise wire.DataError("Key must be provided explicitly.") write_uvarint(w, key.type) write_bytes_fixed(w, key.key, 33) write_uint16_le(w, key.weight) write_uvarint(w, len(auth.accounts)) for account in auth.accounts: write_uint64_le(w, account.account.actor) write_uint64_le(w, account.account.permission) write_uint16_le(w, account.weight) write_uvarint(w, len(auth.waits)) for wait in auth.waits: write_uint32_le(w, wait.wait_sec) write_uint16_le(w, wait.weight)
def write_pubkey(w: Writer, address: str) -> None: # first 4 bytes of an address are the type, there's only one type (0) write_uint32(w, 0) write_bytes_fixed(w, public_key_from_address(address), 32)
def _encode_ballot(w: bytearray, ballot): write_uint8(w, helpers.OP_TAG_BALLOT) write_bytes_fixed(w, ballot.source, helpers.TAGGED_PUBKEY_HASH_SIZE) write_uint32_be(w, ballot.period) write_bytes_fixed(w, ballot.proposal, helpers.PROPOSAL_HASH_SIZE) write_uint8(w, ballot.ballot)
def _encode_contract_id(w: bytearray, contract_id): write_uint8(w, contract_id.tag) write_bytes_fixed(w, contract_id.hash, helpers.CONTRACT_ID_SIZE - 1)
def _get_operation_bytes(w: bytearray, msg): write_bytes_fixed(w, msg.branch, helpers.BRANCH_HASH_SIZE) # when the account sends first operation in lifetime, # we need to reveal its public key if msg.reveal is not None: _encode_common(w, msg.reveal, "reveal") tag = int(msg.reveal.public_key[0]) try: public_key_size = helpers.PUBLIC_KEY_TAG_TO_SIZE[tag] except KeyError: raise wire.DataError("Invalid tag in public key") write_bytes_fixed(w, msg.reveal.public_key, 1 + public_key_size) # transaction operation if msg.transaction is not None: _encode_common(w, msg.transaction, "transaction") _encode_zarith(w, msg.transaction.amount) _encode_contract_id(w, msg.transaction.destination) # support delegation and transfer from the old scriptless contracts (now with manager.tz script) if msg.transaction.parameters_manager is not None: parameters_manager = msg.transaction.parameters_manager if parameters_manager.set_delegate is not None: _encode_manager_delegation(w, parameters_manager.set_delegate) elif parameters_manager.cancel_delegate is not None: _encode_manager_delegation_remove(w) elif parameters_manager.transfer is not None: if (parameters_manager.transfer.destination.tag == TezosContractType.Implicit): _encode_manager_to_implicit_transfer( w, parameters_manager.transfer) else: _encode_manager_to_manager_transfer( w, parameters_manager.transfer) else: if msg.transaction.parameters: helpers.write_bool(w, True) helpers.check_tx_params_size(msg.transaction.parameters) write_bytes_unchecked(w, msg.transaction.parameters) else: helpers.write_bool(w, False) # origination operation elif msg.origination is not None: _encode_common(w, msg.origination, "origination") _encode_zarith(w, msg.origination.balance) _encode_data_with_bool_prefix(w, msg.origination.delegate, helpers.TAGGED_PUBKEY_HASH_SIZE) helpers.check_script_size(msg.origination.script) write_bytes_unchecked(w, msg.origination.script) # delegation operation elif msg.delegation is not None: _encode_common(w, msg.delegation, "delegation") _encode_data_with_bool_prefix(w, msg.delegation.delegate, helpers.TAGGED_PUBKEY_HASH_SIZE) elif msg.proposal is not None: _encode_proposal(w, msg.proposal) elif msg.ballot is not None: _encode_ballot(w, msg.ballot)
def sstxcommitment_pkh(pkh: bytes, amount: int) -> bytes: w = utils.empty_bytearray(30) write_bytes_fixed(w, pkh, 20) write_uint64_le(w, amount) write_bytes_fixed(w, b"\x00\x58", 2) # standard fee limits return w