async def all_outputs_set(state: State): state.mem_trace(0) await confirms.transaction_step(state.ctx, state.STEP_ALL_OUT) state.mem_trace(1) _validate(state) state.mem_trace(2) _set_tx_extra(state) # tx public keys not needed anymore state.additional_tx_public_keys = None state.tx_pub = None gc.collect() state.mem_trace(3) # Completes the transaction prefix hash by including extra _set_tx_prefix(state) extra_b = state.tx.extra state.tx = None gc.collect() state.mem_trace(4) # In the multisig mode here needs to be a check whether currently computed # transaction prefix matches expected transaction prefix sent in the # init step. from trezor.messages.MoneroRingCtSig import MoneroRingCtSig from trezor.messages.MoneroTransactionAllOutSetAck import ( MoneroTransactionAllOutSetAck, ) # Initializes RCTsig structure (fee, tx prefix hash, type) rv_pb = MoneroRingCtSig( txn_fee=state.fee, message=state.tx_prefix_hash, rv_type=get_monero_rct_type(state.rct_type, state.rsig_type), ) _out_pk(state) state.full_message_hasher.rctsig_base_done() state.current_output_index = -1 state.current_input_index = -1 state.full_message = state.full_message_hasher.get_digest() state.full_message_hasher = None return MoneroTransactionAllOutSetAck( extra=extra_b, tx_prefix_hash=state.tx_prefix_hash, rv=rv_pb, full_message_hash=state.full_message, )
async def init_transaction( state: State, address_n: list, network_type: int, tsx_data: MoneroTransactionData, keychain, ): from apps.monero.signing import offloading_keys from apps.common import paths await paths.validate_path(state.ctx, misc.validate_full_path, path=address_n) state.creds = misc.get_creds(keychain, address_n, network_type) state.fee = state.fee if state.fee > 0 else 0 state.tx_priv = crypto.random_scalar() state.tx_pub = crypto.scalarmult_base(state.tx_priv) state.mem_trace(1) # Ask for confirmation await confirms.require_confirm_transaction(state.ctx, tsx_data, state.creds.network_type) gc.collect() state.mem_trace(3) # Basic transaction parameters state.input_count = tsx_data.num_inputs state.output_count = len(tsx_data.outputs) state.output_change = tsx_data.change_dts state.mixin = tsx_data.mixin state.fee = tsx_data.fee state.account_idx = tsx_data.account # Ensure change is correct _check_change(state, tsx_data.outputs) # At least two outpus are required, this applies also for sweep txs # where one fake output is added. See _check_change for more info if state.output_count < 2: raise signing.NotEnoughOutputsError( "At least two outputs are required") _check_rsig_data(state, tsx_data.rsig_data) _check_subaddresses(state, tsx_data.outputs) # Extra processing, payment id state.tx.version = 2 # current Monero transaction format (RingCT = 2) state.tx.unlock_time = tsx_data.unlock_time _process_payment_id(state, tsx_data) await _compute_sec_keys(state, tsx_data) gc.collect() # Iterative tx_prefix_hash hash computation state.tx_prefix_hasher.uvarint(state.tx.version) state.tx_prefix_hasher.uvarint(state.tx.unlock_time) state.tx_prefix_hasher.uvarint(state.input_count) # ContainerType, size state.mem_trace(10, True) # Final message hasher state.full_message_hasher.init(state.rct_type == RctType.Simple) state.full_message_hasher.set_type_fee( signing.get_monero_rct_type(state.rct_type, state.rsig_type), state.fee) # Sub address precomputation if tsx_data.account is not None and tsx_data.minor_indices: _precompute_subaddr(state, tsx_data.account, tsx_data.minor_indices) state.mem_trace(5, True) # HMACs all outputs to disallow tampering. # Each HMAC is then sent alongside the output # and trezor validates it. hmacs = [] for idx in range(state.output_count): c_hmac = await offloading_keys.gen_hmac_tsxdest( state.key_hmac, tsx_data.outputs[idx], idx) hmacs.append(c_hmac) gc.collect() state.mem_trace(6) from trezor.messages.MoneroTransactionInitAck import MoneroTransactionInitAck from trezor.messages.MoneroTransactionRsigData import MoneroTransactionRsigData rsig_data = MoneroTransactionRsigData(offload_type=state.rsig_offload) return MoneroTransactionInitAck(hmacs=hmacs, rsig_data=rsig_data)