def _encode_manager_common(w: bytearray, sequence_length, operation, to_contract=False): IMPLICIT_ADDRESS_LENGTH = 21 SMART_CONTRACT_ADDRESS_LENGTH = 22 # 5 = tag and sequence_length (1 byte + 4 bytes) argument_length = sequence_length + 5 helpers.write_bool(w, True) write_uint8(w, helpers.DO_ENTRYPOINT_TAG) write_uint32_be(w, argument_length) write_uint8(w, helpers.MICHELSON_SEQUENCE_TAG) write_uint32_be(w, sequence_length) helpers.write_instruction(w, "DROP") helpers.write_instruction(w, "NIL") helpers.write_instruction(w, "operation") helpers.write_instruction(w, operation) if to_contract is True: helpers.write_instruction(w, "address") else: helpers.write_instruction(w, "key_hash") if operation == "PUSH": write_bytes_unchecked(w, bytes([10])) # byte sequence if to_contract is True: write_uint32_be(w, SMART_CONTRACT_ADDRESS_LENGTH) else: write_uint32_be(w, IMPLICIT_ADDRESS_LENGTH)
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_unchecked(w, delegate) helpers.write_instruction(w, "SOME") helpers.write_instruction(w, "SET_DELEGATE") helpers.write_instruction(w, "CONS")
def _encode_ballot(w: bytearray, ballot): ballot_tag = 6 write_uint8(w, ballot_tag) write_bytes_unchecked(w, ballot.source) write_uint32_be(w, ballot.period) write_bytes_unchecked(w, ballot.proposal) write_uint8(w, ballot.ballot)
def _encode_proposal(w: bytearray, proposal): proposal_tag = 5 write_uint8(w, proposal_tag) write_bytes_unchecked(w, proposal.source) write_uint32_be(w, proposal.period) write_uint32_be(w, len(proposal.proposals) * PROPOSAL_LENGTH) for proposal_hash in proposal.proposals: write_bytes_unchecked(w, proposal_hash)
def write_variant32(w: Writer, value: int) -> None: variant = bytearray() while True: b = value & 0x7F value >>= 7 b |= (value > 0) << 7 variant.append(b) if value == 0: break write_bytes_unchecked(w, bytes(variant))
def write_string(w: Writer, s: AnyStr) -> None: """Write XDR string padded to a multiple of 4 bytes.""" if isinstance(s, str): buf = s.encode() else: buf = s write_uint32(w, len(buf)) write_bytes_unchecked(w, buf) # if len isn't a multiple of 4, add padding bytes remainder = len(buf) % 4 if remainder: write_bytes_unchecked(w, bytes([0] * (4 - remainder)))
def _encode_common(w: bytearray, operation, str_operation): operation_tags = { "reveal": 107, "transaction": 108, "origination": 109, "delegation": 110, } write_uint8(w, operation_tags[str_operation]) write_bytes_unchecked(w, operation.source) _encode_zarith(w, operation.fee) _encode_zarith(w, operation.counter) _encode_zarith(w, operation.gas_limit) _encode_zarith(w, operation.storage_limit)
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_unchecked(w, manager_transfer.destination.hash) 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_unchecked(w, key.key) 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 _get_operation_bytes(w: bytearray, msg): write_bytes_unchecked(w, msg.branch) # 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") write_bytes_unchecked(w, msg.reveal.public_key) # 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: _encode_data_with_bool_prefix(w, msg.transaction.parameters) # 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) 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) elif msg.proposal is not None: _encode_proposal(w, msg.proposal) elif msg.ballot is not None: _encode_ballot(w, msg.ballot)
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 write_bytes_with_len(w, buf: bytes): write_uint32_le(w, len(buf)) write_bytes_unchecked(w, buf)
def write_pubkey(w, address: str): # first 4 bytes of an address are the type, there's only one type (0) write_uint32(w, 0) write_bytes_unchecked(w, public_key_from_address(address))
def write_bytes_with_len(w: Writer, buf: bytes) -> None: write_uint32_le(w, len(buf)) write_bytes_unchecked(w, buf)
def _encode_data_with_bool_prefix(w: bytearray, data): if data: helpers.write_bool(w, True) write_bytes_unchecked(w, data) else: helpers.write_bool(w, False)
def _encode_contract_id(w: bytearray, contract_id): write_uint8(w, contract_id.tag) write_bytes_unchecked(w, contract_id.hash)
def write_bytes_prefixed(w: Writer, data: bytes) -> None: write_variant32(w, len(data)) write_bytes_unchecked(w, data)
def write_bytes_prefixed(w: Writer, b: bytes) -> None: write_compact_size(w, len(b)) write_bytes_unchecked(w, b)
def write_instruction(w: bytearray, instruction: str) -> int: write_bytes_unchecked(w, MICHELSON_INSTRUCTION_BYTES[instruction])
def write_action_transfer(w: Writer, msg: EosActionTransfer) -> None: write_uint64_le(w, msg.sender) write_uint64_le(w, msg.receiver) write_asset(w, msg.quantity) write_variant32(w, len(msg.memo)) write_bytes_unchecked(w, msg.memo)
def write_bytes_prefixed(w: Writer, b: bytes) -> None: write_bitcoin_varint(w, len(b)) write_bytes_unchecked(w, b)
def write_instruction(w: Writer, instruction: str) -> None: write_bytes_unchecked(w, MICHELSON_INSTRUCTION_BYTES[instruction])