Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add assertnonce action. #646

Merged
merged 2 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class [[eosio::contract]] evm_contract : public contract
[[eosio::action]] void bridgereg(eosio::name receiver, const eosio::asset& min_fee);
[[eosio::action]] void bridgeunreg(eosio::name receiver);

[[eosio::action]] void assertnonce(eosio::name account, uint64_t next_nonce);

#ifdef WITH_TEST_ACTIONS
[[eosio::action]] void testtx(const std::optional<bytes>& orlptx, const evm_runtime::test::block_info& bi);
[[eosio::action]] void
Expand Down
13 changes: 13 additions & 0 deletions src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,19 @@ void evm_contract::bridgeunreg(eosio::name receiver) {
message_receivers.erase(*it);
}


void evm_contract::assertnonce(eosio::name account, uint64_t next_nonce) {
nextnonces nextnonce_table(get_self(), get_self().value);

auto next_nonce_iter = nextnonce_table.find(account.value);
if (next_nonce_iter == nextnonce_table.end()) {
eosio::check(0 == next_nonce, "wrong nonce");
}
else {
eosio::check(next_nonce_iter->next_nonce == next_nonce, "wrong nonce");
}
}

#ifdef WITH_TEST_ACTIONS
[[eosio::action]] void evm_contract::testtx( const std::optional<bytes>& orlptx, const evm_runtime::test::block_info& bi ) {
assert_unfrozen();
Expand Down
5 changes: 5 additions & 0 deletions tests/basic_evm_tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ transaction_trace_ptr basic_evm_tester::bridgeunreg(name receiver) {
mvo()("receiver", receiver));
}

transaction_trace_ptr basic_evm_tester::assertnonce(name account, uint64_t next_nonce) {
return basic_evm_tester::push_action(evm_account_name, "assertnonce"_n, account,
mvo()("account", account)("next_nonce", next_nonce));
}

transaction_trace_ptr basic_evm_tester::pushtx(const silkworm::Transaction& trx, name miner)
{
silkworm::Bytes rlp;
Expand Down
1 change: 1 addition & 0 deletions tests/basic_evm_tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class basic_evm_tester : public testing::validating_tester
transaction_trace_ptr bridgereg(name receiver, asset min_fee, vector<account_name> extra_signers={evm_account_name});
transaction_trace_ptr bridgeunreg(name receiver);
transaction_trace_ptr exec(const exec_input& input, const std::optional<exec_callback>& callback);
transaction_trace_ptr assertnonce(name account, uint64_t next_nonce);
transaction_trace_ptr pushtx(const silkworm::Transaction& trx, name miner = evm_account_name);
void call(name from, const evmc::bytes& to, const evmc::bytes& value, evmc::bytes& data, uint64_t gas_limit, name actor);
void admincall(const evmc::bytes& from, const evmc::bytes& to, const evmc::bytes& value, evmc::bytes& data, uint64_t gas_limit, name actor);
Expand Down
66 changes: 62 additions & 4 deletions tests/call_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,28 +471,86 @@ BOOST_FIXTURE_TEST_CASE(deploy_contract_function, call_evm_tester) try {
auto to = evmc::bytes();

auto data = evmc::from_hex(contract_bytecode);

assertnonce("alice"_n, 0);
call("alice"_n, to, silkworm::Bytes(v), *data, 1000000, "alice"_n); // nonce 0->1

auto addr = silkworm::create_address(alice_addr, 0);

assertnonce("alice"_n, 1);
call_test(addr, 1234, "alice"_n, "alice"_n); // nonce 1->2

auto count = get_count(addr);
BOOST_REQUIRE(count == 1234);

// Advance block so we do not generate same transaction.
produce_block();

auto from = evmc::bytes{std::begin(alice_addr.bytes), std::end(alice_addr.bytes)};

assertnonce("alice"_n, 2);
admincall(from, to, silkworm::Bytes(v), *data, 1000000, evm_account_name); // nonce 2->3

addr = silkworm::create_address(alice_addr, 2);
assertnonce("alice"_n, 3);
call_test(addr, 2222, "alice"_n, "alice"_n); // nonce 3->4
assertnonce("alice"_n, 4);
count = get_count(addr);
BOOST_REQUIRE(count == 2222);
} FC_LOG_AND_RETHROW()

BOOST_FIXTURE_TEST_CASE(assetnonce_test, call_evm_tester) try {
auto alice_addr = make_reserved_address("alice"_n.to_uint64_t());

// nonce for not opened account is zero.
assertnonce("alice"_n, 0);
BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 1),
eosio_assert_message_exception, eosio_assert_message_is("wrong nonce"));

// Advance block so we do not generate same transaction.
produce_block();

open("alice"_n);
transfer_token("alice"_n, evm_account_name, make_asset(1000000), "alice");

evm_eoa evm1;
evmc::bytes32 v;

auto to = evmc::bytes();

auto data = evmc::from_hex(contract_bytecode);

// Fail when nonce is 0 but tested with non-zero value
BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 1),
eosio_assert_message_exception, eosio_assert_message_is("wrong nonce"));

assertnonce("alice"_n, 0);
call("alice"_n, to, silkworm::Bytes(v), *data, 1000000, "alice"_n); // nonce 0->1

// Advance block so we do not generate same transaction.
produce_block();

assertnonce("alice"_n, 1);
assertnonce(evm_account_name, 0);
// Fund evm1 address with 100 EOS, should NOT increase alice nonce, but increase evm nonce.
transfer_token("alice"_n, evm_account_name, make_asset(1000000), evm1.address_0x());

// Advance block so we do not generate same transaction.
produce_block();
assertnonce("alice"_n, 1);
assertnonce(evm_account_name, 1);

// Advance block so we do not generate same transaction.
produce_block();

// Fail when nonce is non-zero but tested with another value
BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 2),
eosio_assert_message_exception, eosio_assert_message_is("wrong nonce"));
// Fail when nonce is non-zero but tested with 0
BOOST_REQUIRE_EXCEPTION(assertnonce("alice"_n, 0),
eosio_assert_message_exception, eosio_assert_message_is("wrong nonce"));



} FC_LOG_AND_RETHROW()



BOOST_AUTO_TEST_SUITE_END()