async def process_unknown_action(ctx: wire.Context, w: Writer, action: EosTxActionAck) -> None: checksum = HashWriter(sha256()) writers.write_variant32(checksum, action.unknown.data_size) checksum.extend(action.unknown.data_chunk) writers.write_bytes_unchecked(w, action.unknown.data_chunk) bytes_left = action.unknown.data_size - len(action.unknown.data_chunk) while bytes_left != 0: action = await ctx.call(EosTxActionRequest(data_size=bytes_left), EosTxActionAck) if action.unknown is None: raise ValueError("Bad response. Unknown struct expected.") checksum.extend(action.unknown.data_chunk) writers.write_bytes_unchecked(w, action.unknown.data_chunk) bytes_left -= len(action.unknown.data_chunk) if bytes_left < 0: raise ValueError("Bad response. Buffer overflow.") await layout.confirm_action_unknown(ctx, action.common, checksum.get_digest())
async def _init(ctx: wire.Context, sha: HashWriter, msg: EosSignTx) -> None: writers.write_bytes_unchecked(sha, msg.chain_id) writers.write_header(sha, msg.header) writers.write_variant32(sha, 0) writers.write_variant32(sha, msg.num_actions) await require_sign_tx(ctx, msg.num_actions)
async def process_action(ctx: wire.Context, sha: HashWriter, action: EosTxActionAck) -> None: name = helpers.eos_name_to_string(action.common.name) account = helpers.eos_name_to_string(action.common.account) if not check_action(action, name, account): raise ValueError("Invalid action") w = bytearray() if account == "eosio": if name == "buyram": await layout.confirm_action_buyram(ctx, action.buy_ram) writers.write_action_buyram(w, action.buy_ram) elif name == "buyrambytes": await layout.confirm_action_buyrambytes(ctx, action.buy_ram_bytes) writers.write_action_buyrambytes(w, action.buy_ram_bytes) elif name == "sellram": await layout.confirm_action_sellram(ctx, action.sell_ram) writers.write_action_sellram(w, action.sell_ram) elif name == "delegatebw": await layout.confirm_action_delegate(ctx, action.delegate) writers.write_action_delegate(w, action.delegate) elif name == "undelegatebw": await layout.confirm_action_undelegate(ctx, action.undelegate) writers.write_action_undelegate(w, action.undelegate) elif name == "refund": await layout.confirm_action_refund(ctx, action.refund) writers.write_action_refund(w, action.refund) elif name == "voteproducer": await layout.confirm_action_voteproducer(ctx, action.vote_producer) writers.write_action_voteproducer(w, action.vote_producer) elif name == "updateauth": await layout.confirm_action_updateauth(ctx, action.update_auth) writers.write_action_updateauth(w, action.update_auth) elif name == "deleteauth": await layout.confirm_action_deleteauth(ctx, action.delete_auth) writers.write_action_deleteauth(w, action.delete_auth) elif name == "linkauth": await layout.confirm_action_linkauth(ctx, action.link_auth) writers.write_action_linkauth(w, action.link_auth) elif name == "unlinkauth": await layout.confirm_action_unlinkauth(ctx, action.unlink_auth) writers.write_action_unlinkauth(w, action.unlink_auth) elif name == "newaccount": await layout.confirm_action_newaccount(ctx, action.new_account) writers.write_action_newaccount(w, action.new_account) else: raise ValueError("Unrecognized action type for eosio") elif name == "transfer": await layout.confirm_action_transfer(ctx, action.transfer, account) writers.write_action_transfer(w, action.transfer) else: await process_unknown_action(ctx, w, action) writers.write_action_common(sha, action.common) writers.write_variant32(sha, len(w)) writers.write_bytes_unchecked(sha, w)
async def sign_tx(ctx: wire.Context, msg: EosSignTx, keychain: Keychain) -> EosSignedTx: if msg.chain_id is None: raise wire.DataError("No chain id") if msg.header is None: raise wire.DataError("No header") if msg.num_actions is None or msg.num_actions == 0: raise wire.DataError("No actions") await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE) node = keychain.derive(msg.address_n) sha = HashWriter(sha256()) await _init(ctx, sha, msg) await _actions(ctx, sha, msg.num_actions) writers.write_variant32(sha, 0) writers.write_bytes_unchecked(sha, bytearray(32)) digest = sha.get_digest() signature = secp256k1.sign(node.private_key(), digest, True, secp256k1.CANONICAL_SIG_EOS) return EosSignedTx(signature=base58_encode("SIG_", "K1", signature))