From bc173c30ea824a7dc13f07a288c84f58d562dbcb Mon Sep 17 00:00:00 2001 From: yarkin Date: Wed, 9 Aug 2023 16:48:37 +0800 Subject: [PATCH] Optimze logic when processing tx with special signature. --- src/actions.cpp | 49 ++++++++++++++++++++++---------------------- tests/call_tests.cpp | 4 ++-- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/actions.cpp b/src/actions.cpp index 898d0602..91b792c2 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -220,39 +220,38 @@ Receipt evm_contract::execute_tx( eosio::name miner, Block& block, Transaction& inevm.emplace(get_self(), get_self().value); }; - bool is_special_signature = (tx.r == intx::uint256()); + bool is_special_signature = silkworm::is_special_signature(tx.r, tx.s); tx.from.reset(); tx.recover_sender(); eosio::check(tx.from.has_value(), "unable to recover sender"); LOGTIME("EVM RECOVER SENDER"); - // type 1: normal signature (normal address recovered from normal signature), required !from_self - // type 2: special signature (r == 0), reserved address (stored in s), required from_self + reduce special balance - // type 3: special signature (r == 0), normal address (stored in s), required from_self - if(from_self) { - check(is_special_signature, "actions from self without a special signature are unexpected"); - if (is_reserved_address(*tx.from)) { - const name ingress_account(*extract_reserved_address(*tx.from)); - - const intx::uint512 max_gas_cost = intx::uint256(tx.gas_limit) * tx.max_fee_per_gas; - check(max_gas_cost + tx.value < std::numeric_limits::max(), "too much gas"); - const intx::uint256 value_with_max_gas = tx.value + (intx::uint256)max_gas_cost; - - populate_bridge_accessors(); - balance_table.modify(balance_table.get(ingress_account.value), eosio::same_payer, [&](balance& b){ - b.balance -= value_with_max_gas; - }); - inevm->set(inevm->get() += value_with_max_gas, eosio::same_payer); + // 1 Reject special signature NOT from self. + // 2 All other cases (normal signature or special signature from self) will be accepted. + // 3 If the from address is reserved address, the special balance needs some process. + check(from_self || !is_special_signature, "bridge signature used outside of bridge transaction"); + + if (is_reserved_address(*tx.from)) { + const name ingress_account(*extract_reserved_address(*tx.from)); - ep.state().set_balance(*tx.from, value_with_max_gas); - ep.state().set_nonce(*tx.from, tx.nonce); - } + const intx::uint512 max_gas_cost = intx::uint256(tx.gas_limit) * tx.max_fee_per_gas; + check(max_gas_cost + tx.value < std::numeric_limits::max(), "too much gas"); + const intx::uint256 value_with_max_gas = tx.value + (intx::uint256)max_gas_cost; + + populate_bridge_accessors(); + balance_table.modify(balance_table.get(ingress_account.value), eosio::same_payer, [&](balance& b){ + b.balance -= value_with_max_gas; + }); + inevm->set(inevm->get() += value_with_max_gas, eosio::same_payer); + + ep.state().set_balance(*tx.from, value_with_max_gas); + ep.state().set_nonce(*tx.from, tx.nonce); } - else if(is_special_signature) - check(false, "bridge signature used outside of bridge transaction"); - if(enforce_chain_id && !from_self) { + // A tx from self with regular signature can potentially from external source. + // Therefore, only tx with special signature can waive the chain_id check. + if(enforce_chain_id && !is_special_signature) { check(tx.chain_id.has_value(), "tx without chain-id"); } @@ -277,7 +276,7 @@ Receipt evm_contract::execute_tx( eosio::name miner, Block& block, Transaction& } if(from_self) - eosio::check(receipt.success, "inline actions must succeed"); + eosio::check(receipt.success, "tx executed inline by contract must succeed"); if(!ep.state().reserved_objects().empty()) { bool non_open_account_sent = false; diff --git a/tests/call_tests.cpp b/tests/call_tests.cpp index f1fd36e2..b01f8306 100644 --- a/tests/call_tests.cpp +++ b/tests/call_tests.cpp @@ -155,7 +155,7 @@ BOOST_FIXTURE_TEST_CASE(call_test_function, call_evm_tester) try { auto total_fund2 = intx::uint256(vault_balance("alice"_n)) + intx::uint256(vault_balance("evm"_n)); BOOST_REQUIRE_EXCEPTION(call_test(token_addr, 0, "alice"_n, "alice"_n), - eosio_assert_message_exception, eosio_assert_message_is("inline actions must succeed")); + eosio_assert_message_exception, eosio_assert_message_is("tx executed inline by contract must succeed")); // Call and check results @@ -230,7 +230,7 @@ BOOST_FIXTURE_TEST_CASE(admincall_test_function, call_evm_tester) try { BOOST_REQUIRE_EXCEPTION(admincall_test(token_addr, 0, evm2, "evm"_n), - eosio_assert_message_exception, eosio_assert_message_is("inline actions must succeed")); + eosio_assert_message_exception, eosio_assert_message_is("tx executed inline by contract must succeed")); // Call and check results admincall_test(token_addr, 1234, evm2, "evm"_n);