From 22b34b0c791645cc09b6977e6834b1ed09bce5ea Mon Sep 17 00:00:00 2001 From: kayan Date: Fri, 11 Aug 2023 14:34:16 +0800 Subject: [PATCH 01/15] integration of defer transactions and action ordering --- src/ship_receiver_plugin.cpp | 61 ++++++----- tests/CMakeLists.txt | 4 + tests/defertest.abi | 97 +++++++++++++++++ tests/defertest.cpp | 94 ++++++++++++++++ tests/defertest.wasm | Bin 0 -> 18428 bytes tests/defertest2.abi | 44 ++++++++ tests/defertest2.cpp | 32 ++++++ tests/defertest2.wasm | Bin 0 -> 3660 bytes tests/nodeos_eos_evm_test.py | 200 +++++++++++++++++++++++++++++++---- 9 files changed, 486 insertions(+), 46 deletions(-) create mode 100644 tests/defertest.abi create mode 100644 tests/defertest.cpp create mode 100755 tests/defertest.wasm create mode 100644 tests/defertest2.abi create mode 100644 tests/defertest2.cpp create mode 100755 tests/defertest2.wasm diff --git a/src/ship_receiver_plugin.cpp b/src/ship_receiver_plugin.cpp index 8c2f260..5559ed0 100644 --- a/src/ship_receiver_plugin.cpp +++ b/src/ship_receiver_plugin.cpp @@ -156,26 +156,20 @@ class ship_receiver_plugin_impl : std::enable_shared_from_thisblock_num << " with " << num << " transactions"; + SILK_DEBUG << "Block #" << block.this_block->block_num << " with " << num << " transactions"; for (std::size_t i = 0; i < num; i++) { auto tt = eosio::from_bin(*block.traces); const auto& trace = std::get(tt); - const auto& actions = trace.action_traces; - bool found = false; - for (std::size_t j=0; j < actions.size(); j++) { - std::visit([&](auto& act){ - if (act.act.name == pushtx && core_account == act.receiver) { - append_to_block(current_block, trace, j); - found = true; - } - }, actions[j]); - if (found) break; + if (trace.status != eosio::ship_protocol::transaction_status::executed) { + SILK_DEBUG << "Block #" << block.this_block->block_num << " ignore transaction with status " << (int)trace.status; + continue; } + append_to_block(current_block, trace); } } @@ -198,27 +192,42 @@ class ship_receiver_plugin_impl : std::enable_shared_from_this - inline void append_to_block(native_block_t& block, Trace& trace, std::size_t idx) { + inline void append_to_block(native_block_t& block, const eosio::ship_protocol::transaction_trace_v0& trace) { channels::native_trx native_trx = {trace.id, trace.cpu_usage_us, trace.elapsed}; const auto& actions = trace.action_traces; //SILK_DEBUG << "Appending transaction "; - for (std::size_t j=idx; j < actions.size(); j++) { - std::visit([&](auto& act){ + std::map ordered_action_traces; + for (std::size_t j = 0; j < actions.size(); ++j) { + std::visit([&](auto& act) { if (act.act.name == pushtx && core_account == act.receiver) { - channels::native_action action = { - act.action_ordinal, - act.receiver, - act.act.account, - act.act.name, - std::vector(act.act.data.pos, act.act.data.end) - }; - native_trx.actions.emplace_back(std::move(action)); + if (!act.receipt.has_value()) { + SILK_ERROR << "action_trace does not have receipt"; + throw std::runtime_error("action_trace does not have receipt"); + } + uint64_t global_sequence = 0; + std::visit([&](auto &receipt) { + global_sequence = receipt.global_sequence; + }, act.receipt.value()); + ordered_action_traces[global_sequence] = std::move(actions[j]); + SILK_DEBUG << "add action sequence " << global_sequence; } }, actions[j]); - //SILK_DEBUG << "Appending action " << native_trx.actions.back().name.to_string(); } - block.transactions.emplace_back(std::move(native_trx)); + if (ordered_action_traces.size()) { + for (const auto &pair: ordered_action_traces) { + std::visit([&](const auto& act) { + channels::native_action action = { + act.action_ordinal, + act.receiver, + act.act.account, + act.act.name, + std::vector(act.act.data.pos, act.act.data.end) + }; + native_trx.actions.emplace_back(std::move(action)); + }, pair.second); + } + block.transactions.emplace_back(std::move(native_trx)); + } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 04d2925..f8d8ceb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,3 +3,7 @@ add_subdirectory( nodeos_eos_evm_server ) configure_file(antelope_name.py . COPYONLY) configure_file(nodeos_eos_evm_server.py . COPYONLY) configure_file(nodeos_eos_evm_test.py . COPYONLY) +configure_file(defertest.wasm . COPYONLY) +configure_file(defertest.abi . COPYONLY) +configure_file(defertest2.wasm . COPYONLY) +configure_file(defertest2.abi . COPYONLY) diff --git a/tests/defertest.abi b/tests/defertest.abi new file mode 100644 index 0000000..ce86aed --- /dev/null +++ b/tests/defertest.abi @@ -0,0 +1,97 @@ +{ + "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", + "version": "eosio::abi/1.2", + "types": [], + "structs": [ + { + "name": "pending", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "account", + "type": "name" + }, + { + "name": "miner", + "type": "name" + }, + { + "name": "rlptx", + "type": "bytes" + } + ] + }, + { + "name": "pushdefer", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "account", + "type": "name" + }, + { + "name": "miner", + "type": "name" + }, + { + "name": "rlptx", + "type": "bytes" + }, + { + "name": "rlptx2", + "type": "bytes" + } + ] + }, + { + "name": "pushtxinline", + "base": "", + "fields": [ + { + "name": "account", + "type": "name" + }, + { + "name": "miner", + "type": "name" + }, + { + "name": "rlptx", + "type": "bytes" + } + ] + } + ], + "actions": [ + { + "name": "pushdefer", + "type": "pushdefer", + "ricardian_contract": "" + }, + { + "name": "pushtxinline", + "type": "pushtxinline", + "ricardian_contract": "" + } + ], + "tables": [ + { + "name": "pending", + "type": "pending", + "index_type": "i64", + "key_names": [], + "key_types": [] + } + ], + "ricardian_clauses": [], + "variants": [], + "action_results": [] +} \ No newline at end of file diff --git a/tests/defertest.cpp b/tests/defertest.cpp new file mode 100644 index 0000000..9b80640 --- /dev/null +++ b/tests/defertest.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace eosio; +using namespace std; + +extern "C" { + __attribute__((eosio_wasm_import)) + uint64_t current_time(); +} + +class [[eosio::contract("defertest")]] defertest : public eosio::contract { + +public: + using contract::contract; + + int32_t now() { + return current_time() / 1000000; + } + + struct [[eosio::table]] pending { + uint64_t id; + eosio::name account; + eosio::name miner; + std::vector rlptx; + + uint64_t primary_key() const { return id; } + }; + typedef eosio::multi_index<"pending"_n, pending> pending_table_t; + + // notify by the contract account of contract "defertest2.cpp" + [[eosio::on_notify("*::notifytest")]] void notifytest(eosio::name recipient, eosio::name account, eosio::name miner, const std::vector &rlptx, const std::vector &rlptx2) { + action act({_self, "active"_n}, account, "pushtx"_n, + std::tuple >(miner, rlptx2)); + act.send(); + } + + [[eosio::action]] void pushtxinline(eosio::name account, eosio::name miner, const std::vector &rlptx) { + action act({_self, "active"_n}, account, "pushtx"_n, + std::tuple >(miner, rlptx)); + act.send(); + } + + [[eosio::action]] void pushdefer(uint64_t id, eosio::name account, eosio::name miner, const std::vector &rlptx, const std::vector &rlptx2) { + + printf("enter defertest.cpp::pushdefer:%d %d", (int)rlptx.size(), (int)rlptx2.size()); + + action act(permission_level{_self, "active"_n}, account, "pushtx"_n, std::tuple >(miner, rlptx)); + transaction txn(time_point_sec(current_time() + 3590)); + txn.actions.push_back(act); + auto serialize = pack(txn); + ::send_deferred((uint128_t)(id), _self, serialize.data(), serialize.size(), true); + + if (rlptx2.size()) { + pending_table_t pending_table(_self, _self.value); + pending_table.emplace(_self, [&](auto &v) { + v.id = id; + v.account = account; + v.miner = miner; + v.rlptx = rlptx2; + }); + } + } + + [[eosio::on_notify("eosio::onerror")]] void onerror() { + + pending_table_t pending_table(_self, _self.value); + if (pending_table.begin() != pending_table.end()) { + + printf("defertest.cpp::onerror() 1"); + auto itr = pending_table.end(); + --itr; + action act(permission_level{_self, "active"_n}, itr->account, "pushtx"_n, + std::tuple >(itr->miner, itr->rlptx)); + act.send(); + pending_table.erase(itr); + } + else { + printf("defertest.cpp::onerror() 2"); + check(false, "hard-fail"); + } + } +}; diff --git a/tests/defertest.wasm b/tests/defertest.wasm new file mode 100755 index 0000000000000000000000000000000000000000..0b5c3113bf6d36c47729579ad638139f9d11c064 GIT binary patch literal 18428 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 L8T0gw%DMjuDdxwR literal 0 HcmV?d00001 diff --git a/tests/defertest2.abi b/tests/defertest2.abi new file mode 100644 index 0000000..88ae9fa --- /dev/null +++ b/tests/defertest2.abi @@ -0,0 +1,44 @@ +{ + "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ", + "version": "eosio::abi/1.2", + "types": [], + "structs": [ + { + "name": "notifytest", + "base": "", + "fields": [ + { + "name": "recipient", + "type": "name" + }, + { + "name": "account", + "type": "name" + }, + { + "name": "miner", + "type": "name" + }, + { + "name": "rlptx", + "type": "bytes" + }, + { + "name": "rlptx2", + "type": "bytes" + } + ] + } + ], + "actions": [ + { + "name": "notifytest", + "type": "notifytest", + "ricardian_contract": "" + } + ], + "tables": [], + "ricardian_clauses": [], + "variants": [], + "action_results": [] +} \ No newline at end of file diff --git a/tests/defertest2.cpp b/tests/defertest2.cpp new file mode 100644 index 0000000..1781552 --- /dev/null +++ b/tests/defertest2.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace eosio; +using namespace std; + +class [[eosio::contract("defertest2")]] defertest2 : public eosio::contract { + +public: + using contract::contract; + + // recipient is the contract account of contract "defertest.cpp" + [[eosio::action]] void notifytest(eosio::name recipient, eosio::name account, eosio::name miner, const std::vector &rlptx, const std::vector &rlptx2) { + + action act({_self, "active"_n}, recipient, "pushtxinline"_n, + std::tuple >(account, miner, rlptx)); + act.send(); + + require_recipient(recipient); + } + +}; diff --git a/tests/defertest2.wasm b/tests/defertest2.wasm new file mode 100755 index 0000000000000000000000000000000000000000..b210c42f5fbf2a13a9e9029bda94f0ae4edcf5c1 GIT binary patch literal 3660 zcmcgvO^jPt6+ZXpJ==Mnnb~sYd<=+XT~1; zCA2KY24%q_NU%#JKoLU9hDH?#@zVvV1QH7>ArPo6KuBy55~6Ds4Bxreo|tH+u)+)9 z`_4W8=R4=VNA1auAR_U?$xWh764OmNof7|HtEOQQ`;oAZ^L-rQQSI;JUoewkc795y zAVOIFLY`E`?k&^ql)d3@tJ^Nytx4}o1qmkCi{Yd~u!2k>-b_{qhj}#QSVg>~>qd-R<6P5jC717kf8*fqMsfSfe`5;{onvjI@o+Sp6kXnQZ+4)HQZ`lZ+#HW# zxK;Lc3aT*aDOSs2-71#2gR1Ii+}kZDt?jx0%SmZg*Y+oyh1!mL*wTtw^bq z(uo)eArd7>r03LB_}L@MrsTiz*5OjAiKIOmZNEmRPQ3l}8BOL)wojJKIdjsI6`$A5 ztFzg?-+%vSKe_jcq0fAIIO{DaI299cSFD4NY4 z{_{_N`)*VOi7(G)OA?tU^K>>AYARu6g*=@C$x}n#!Lv8Foaj5bhNnoq-E_)Q-=FIH z(Vn97pA)5;Njd8RhJmpZ-kl$-M`SBHDl_8*(0-<$ zUm>fF2}CPF3Ymc5CCd2O$nyx#B4uS7 z?}ADBUsB(^A71idGahan9&XIfs(pkIso0>z3@QTQS%evOR$W#jm#(WS0v7AaVnM8{ zSU_xmbrlLOt1bT9?`R+^_6f1qDqqQ4mE5W6q>sM>*0 zn3Ve(plV2+%d35W_*_hF1-YX z%Zl=fO;If5ol8qLW$dj&iCR|%i$twr&*jzFAFNfw&w;CP6>5I^BKk13HFK6{1VTG)78MQSGuNCF_8zH45mR7~%ioaKa!iPnjcjp1 zYqA@cO)RNLvvP0owu;>itlWdC|25j{BJu>(U;LRY)NGJ=#3eyxL8m17due=Zj&5s|=FEO2K_CzjjF6Ik>o;$`5 z`4Ot6>@qF?hm#!Hp!2&Yh^sN#5O z^@Ma7pO6NMK8WRF-#nB3Cf+7${$_*Mf-t~C>d-;~B}fw2@d2hf%FAO!VT=GWl``HS zIU0Vl)~UM)Rq%>Og20K#w|YL{YmDKzdP)+6d3Qk6VWxsa#-Neu5TOBn`YLWUEh z27R95r53G!n5gWYP~janvtMZUwu`PUhqk?q51e*c*irkHVnU0be*<3z?Zp#+g-uF) tXzkc`Sr$8^G75ij+zXPE(w19=#fKFg$I4%6u(8C6?;Ap~Gkw<*{TmN1bV~pL literal 0 HcmV?d00001 diff --git a/tests/nodeos_eos_evm_test.py b/tests/nodeos_eos_evm_test.py index fc099f8..99b23ec 100755 --- a/tests/nodeos_eos_evm_test.py +++ b/tests/nodeos_eos_evm_test.py @@ -205,7 +205,7 @@ def processUrllibRequest(endpoint, payload={}, silentErrors=False, exitOnError=F def getGasPrice(): if useTrxWrapper is None: - return 1 + return 10000000000 else: result = processUrllibRequest("http://127.0.0.1:18888", payload={"method":"eth_gasPrice","params":[],"id":1,"jsonrpc":"2.0"}) Utils.Print("result: ", result) @@ -273,7 +273,7 @@ def makeReservedEvmAddress(account): prodNode = cluster.getNode(0) nonProdNode = cluster.getNode(1) - accounts=cluster.createAccountKeys(3) + accounts=cluster.createAccountKeys(5) if accounts is None: Utils.errorExit("FAILURE - create keys") @@ -281,12 +281,14 @@ def makeReservedEvmAddress(account): evmAcc.name = "evmevmevmevm" testAcc = accounts[1] txWrapAcc = accounts[2] + defertestAcc = accounts[3] + defertest2Acc = accounts[4] minerAcc = txWrapAcc testWalletName="test" Print("Creating wallet \"%s\"." % (testWalletName)) - testWallet=walletMgr.create(testWalletName, [cluster.eosioAccount,accounts[0],accounts[1],accounts[2]]) + testWallet=walletMgr.create(testWalletName, [cluster.eosioAccount,accounts[0],accounts[1],accounts[2],accounts[3],accounts[4]]) addys = { "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266":"0x038318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed75,0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" @@ -311,13 +313,35 @@ def makeReservedEvmAddress(account): contractDir=eosEvmContractRoot + "/evm_runtime" wasmFile="evm_runtime.wasm" abiFile="evm_runtime.abi" - Utils.Print("Publish evm_runtime contract") + Utils.Print(f"Publish evm_runtime contract {contractDir}/{wasmFile} to account {evmAcc}") prodNode.publishContract(evmAcc, contractDir, wasmFile, abiFile, waitForTransBlock=True) # add eosio.code permission cmd="set account permission evmevmevmevm active --add-code -p evmevmevmevm@active" prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + # set defertest contract + contractDir=eosEvmBuildRoot + "/tests" + wasmFile="defertest.wasm" + abiFile="defertest.abi" + Utils.Print(f"Publish defertest contract {contractDir}/{wasmFile} to account {defertestAcc}") + prodNode.publishContract(defertestAcc, contractDir, wasmFile, abiFile, waitForTransBlock=True) + + # add eosio.code permission to defertest account + cmd="set account permission " + defertestAcc.name + " active --add-code -p " + defertestAcc.name + "@active" + prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + + # set defertest2 contract + contractDir=eosEvmBuildRoot + "/tests" + wasmFile="defertest2.wasm" + abiFile="defertest2.abi" + Utils.Print(f"Publish defertest2 contract {contractDir}/{wasmFile} to account {defertest2Acc}") + prodNode.publishContract(defertest2Acc, contractDir, wasmFile, abiFile, waitForTransBlock=True) + + # add eosio.code permission to defertest2 account + cmd="set account permission " + defertest2Acc.name + " active --add-code -p " + defertest2Acc.name + "@active" + prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + trans = prodNode.pushMessage(evmAcc.name, "init", '{{"chainid":15555, "fee_params": {{"gas_price": "10000000000", "miner_cut": 100000, "ingress_bridge_fee": "0.0000 {0}"}}}}'.format(CORE_SYMBOL), '-p evmevmevmevm') prodNode.waitForTransBlockIfNeeded(trans[1], True) transId=prodNode.getTransId(trans[1]) @@ -642,6 +666,7 @@ def makeReservedEvmAddress(account): Utils.Print("\taccount row4: ", row4) assert(row4["eth_address"] == "9e126c57330fa71556628e0aabd6b6b6783d99fa") assert(row4["balance"] == "000000000000000000000000000000000000000000000001887f8db687170000") # 0x1887f8db687170000 => 28282480000000000000 (42.4242 - 0.0100 - 13.1313 - 1.0000 - 2 * 21000 * 10^10) + assert(row4["nonce"] == 2) expectedAmount="60000135.8250 {0}".format(CORE_SYMBOL) evmAccActualAmount=prodNode.getAccountEosBalanceStr(evmAcc.name) Utils.Print("\tEVM Account balance %s" % evmAccActualAmount) @@ -653,6 +678,138 @@ def makeReservedEvmAddress(account): if testAccActualAmount != expectedAmount: Utils.errorExit("Transfer verification failed. Excepted %s, actual: %s" % (expectedAmount, testAccActualAmount)) + # test hard-failed transaction (with --delay-sec) + amount=7.0000 + transferAmount="7.000 {0}".format(CORE_SYMBOL) + Print("Test hard-failed EVM transaction (with delay)") + signed_trx = w3.eth.account.sign_transaction(dict( + nonce=nonce + 1000, # Wrong nonce -> should hard fails + gas=100000, #100k Gas + gasPrice=gasP, + to=Web3.to_checksum_address(toAdd), + value=int(amount*10000*szabo*100), + data=b'', + chainId=evmChainId + ), evmSendKey) + actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:]} + cmd="push action " + evmAcc.name + " pushtx \"" + json.dumps(actData).replace("\"","\\\"") + "\" --delay-sec 2 -p " + minerAcc.name + trans=prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + Utils.Print(f"trans is {trans}"); + time.sleep(4) # sleep enough time to get hard fails. + row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test + Utils.Print("\taccount row4: ", row4) + assert(row4["eth_address"] == "9e126c57330fa71556628e0aabd6b6b6783d99fa") + assert(row4["balance"] == "000000000000000000000000000000000000000000000001887f8db687170000") # + assert(row4["nonce"] == 2) + + + # test hard-failed transaction (with defer) + amount=9.0000 + transferAmount="9.000 {0}".format(CORE_SYMBOL) + Print("Test hard-failed EVM transaction (with defer)") + signed_trx = w3.eth.account.sign_transaction(dict( + nonce=nonce + 1000, # Wrong nonce -> should hard fails + gas=100000, #100k Gas + gasPrice=gasP, + to=Web3.to_checksum_address(toAdd), + value=int(amount*10000*szabo*100), + data=b'', + chainId=evmChainId + ), evmSendKey) + actData = {"id":1,"account":evmAcc.name,"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:], "rlptx2":""} + trans = prodNode.pushMessage(defertestAcc.name, "pushdefer", json.dumps(actData), '-p {0}'.format(defertestAcc.name), silentErrors=False) + prodNode.waitForTransBlockIfNeeded(trans[1], True) + Utils.Print(f"trans is {trans}"); + time.sleep(4) # sleep enough time to get hard fails. + row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test + Utils.Print("\taccount row4: ", row4) + assert(row4["eth_address"] == "9e126c57330fa71556628e0aabd6b6b6783d99fa") + assert(row4["balance"] == "000000000000000000000000000000000000000000000001887f8db687170000") # + assert(row4["nonce"] == 2) # nothing should execute + + + # test soft-failed transaction (with defer) + amount=11.0000 + transferAmount="11.000 {0}".format(CORE_SYMBOL) + Print("Test soft-failed EVM transaction (with defer)") + signed_trx = w3.eth.account.sign_transaction(dict( + nonce=nonce + 1000, # Wrong nonce -> should hard fails + gas=100000, #100k Gas + gasPrice=gasP, + to=Web3.to_checksum_address(toAdd), + value=int(amount*10000*szabo*100), + data=b'', + chainId=evmChainId + ), evmSendKey) + amount=13.0000 + transferAmount="13.000 {0}".format(CORE_SYMBOL) + nonce = nonce + 1 + signed_trx2 = w3.eth.account.sign_transaction(dict( + nonce=nonce, # right nonce + gas=100000, #100k Gas + gasPrice=gasP, + to=Web3.to_checksum_address(toAdd), + value=int(amount*10000*szabo*100), + data=b'', + chainId=evmChainId + ), evmSendKey) + actData = {"id":2,"account":evmAcc.name,"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:], "rlptx2":Web3.to_hex(signed_trx2.rawTransaction)[2:]} + trans = prodNode.pushMessage(defertestAcc.name, "pushdefer", json.dumps(actData), '-p {0}'.format(defertestAcc.name), silentErrors=False) + prodNode.waitForTransBlockIfNeeded(trans[1], True) + Utils.Print(f"trans is {trans}"); + time.sleep(4) # sleep enough time to get soft fails. + row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test + Utils.Print("\taccount row4: ", row4) + assert(row4["eth_address"] == "9e126c57330fa71556628e0aabd6b6b6783d99fa") + assert(row4["nonce"] == 3) # rlptx2 is executed by onerror handler + assert(row4["balance"] == "000000000000000000000000000000000000000000000000d4158798979be000") + + + # test action trace execution order which is different than creation order + # defertest2::notifytest(defertest, evmevmevmevm, miner, rlptx, rlptx2) + # -> 1. create inline action (a) defertest::pushtxinline(evmevmevmevm, miner, rlptx1) + # -> 2. require_recipient(defertest) + # -> 3. on_notify of defertest::notifytest, create inline action (b) evmevmevmevm::pushtx(miner, rlptx2) + # -> 4. inline action (a) executes: create inline action (c) evmevmevmevm::pushtx(rlptx1) + # -> 5. action (c) executes: evmevmevmevm::pushtx(rlptx1) + # -> 6. action (b) executes: evmevmevmevm::pushtx(rlptx2) + # in the above case, evmevmevmevm::pushtx(miner, rlptx2) will be created before evmevmevmevm::pushtx(rlptx1), + # but evmevmevmevm::pushtx(rlptx1) will be executed before evmevmevmevm::pushtx(miner, rlptx2) + amount=2.0000 + transferAmount="2.000 {0}".format(CORE_SYMBOL) + Utils.Print("Test action ordering: action1: transfer EVM->EOS funds %s from account %s to %s via inline action" % (transferAmount, evmAcc.name, testAcc.name)) + nonce = nonce + 1 + gasP = getGasPrice() + signed_trx = w3.eth.account.sign_transaction(dict( + nonce=nonce, + gas=100000, #100k Gas + gasPrice=gasP, + to=Web3.to_checksum_address(toAdd), + value=int(amount*10000*szabo*100), + data=b'', + chainId=evmChainId + ), evmSendKey) + amount=4.0000 + transferAmount="4.000 {0}".format(CORE_SYMBOL) + Utils.Print("Test action ordering: action 2: transfer EVM->EOS funds %s from account %s to %s via inline action" % (transferAmount, evmAcc.name, testAcc.name)) + nonce = nonce + 1 + gasP = getGasPrice() + signed_trx2 = w3.eth.account.sign_transaction(dict( + nonce=nonce, + gas=100000, #100k Gas + gasPrice=gasP, + to=Web3.to_checksum_address(toAdd), + value=int(amount*10000*szabo*100), + data=b'', + chainId=evmChainId + ), evmSendKey) + actData = {"recipient":defertestAcc.name, "account":evmAcc.name, "miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:], "rlptx2":Web3.to_hex(signed_trx2.rawTransaction)[2:]} + trans = prodNode.pushMessage(defertest2Acc.name, "notifytest", json.dumps(actData), '-p {0}'.format(defertest2Acc.name), silentErrors=False) + prodNode.waitForTransBlockIfNeeded(trans[1], True) + row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test + Utils.Print("\taccount row4: ", row4) + assert(row4["nonce"] == 5) + # Launch eos-evm-node dataDir = Utils.DataDir + "eos_evm" @@ -677,34 +834,37 @@ def makeReservedEvmAddress(account): Utils.Print(f"Launching: {cmd}") evmRPCPOpen=Utils.delayedCheckOutput(cmd, stdout=outFile, stderr=errFile) - # Validate all balances are the same on both sides - rows=prodNode.getTable(evmAcc.name, evmAcc.name, "account") - for row in rows['rows']: - Utils.Print("Checking 0x{0} balance".format(row['eth_address'])) - r = 0 - try: - r = w3.eth.get_balance(Web3.to_checksum_address('0x'+row['eth_address'])) - except: - Utils.Print("ERROR - RPC endpoint not available - Exception thrown - Checking 0x{0} balance".format(row['eth_address'])) - raise - assert r == int(row['balance'],16), f"{row['eth_address']} {r} != {int(row['balance'],16)}" - - foundErr = False + Utils.Print("Checking ERROR or CRIT in EOS EVM Node log") stdErrFile = open(nodeStdErrDir, "r") lines = stdErrFile.readlines() for line in lines: if line.find("ERROR") != -1 or line.find("CRIT") != -1: Utils.Print(" Found ERROR in EOS EVM NODE log: ", line) - foundErr = True + Utils.errorExit("ERROR found in EOS EVM Node log") + Utils.Print("Checking ERROR or CRIT in EOS EVM ROC log") stdErrFile = open(rpcStdErrDir, "r") lines = stdErrFile.readlines() for line in lines: if line.find("ERROR") != -1 or line.find("CRIT") != -1: Utils.Print(" Found ERROR in EOS EVM RPC log: ", line) - foundErr = True + Utils.errorExit("ERROR found in EOS EVM RPC log") + + # Validate all balances are the same on both sides + rows=prodNode.getTable(evmAcc.name, evmAcc.name, "account") + Utils.Print(f"account balances from leap:{rows}") + for row in rows['rows']: + Utils.Print("Checking 0x{0} balance".format(row['eth_address'])) + r = 0 + try: + r = w3.eth.get_balance(Web3.to_checksum_address('0x'+row['eth_address'])) + except: + Utils.Print("ERROR - RPC endpoint not available - Exception thrown - Checking 0x{0} balance".format(row['eth_address'])) + raise + assert r == int(row['balance'],16), f"{row['eth_address']} {r} != {int(row['balance'],16)}" - testSuccessful= not foundErr + Utils.Print("=== nodeos_eos_evm_test successful ===") + testSuccessful=True finally: TestHelper.shutdown(cluster, walletMgr, testSuccessful=testSuccessful, killEosInstances=killEosInstances, killWallet=killEosInstances, keepLogs=keepLogs, cleanRun=killAll, dumpErrorDetails=dumpErrorDetails) if killEosInstances: From 4e49e1d151b4013bb71b74e8ca071fd1b0c1b909 Mon Sep 17 00:00:00 2001 From: kayan Date: Mon, 14 Aug 2023 17:30:26 +0800 Subject: [PATCH 02/15] cleanup logggings --- tests/nodeos_eos_evm_test.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/nodeos_eos_evm_test.py b/tests/nodeos_eos_evm_test.py index 99b23ec..435c6a7 100755 --- a/tests/nodeos_eos_evm_test.py +++ b/tests/nodeos_eos_evm_test.py @@ -694,7 +694,7 @@ def makeReservedEvmAddress(account): actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:]} cmd="push action " + evmAcc.name + " pushtx \"" + json.dumps(actData).replace("\"","\\\"") + "\" --delay-sec 2 -p " + minerAcc.name trans=prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) - Utils.Print(f"trans is {trans}"); + #Utils.Print(f"trans is {trans}"); time.sleep(4) # sleep enough time to get hard fails. row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test Utils.Print("\taccount row4: ", row4) @@ -719,7 +719,7 @@ def makeReservedEvmAddress(account): actData = {"id":1,"account":evmAcc.name,"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:], "rlptx2":""} trans = prodNode.pushMessage(defertestAcc.name, "pushdefer", json.dumps(actData), '-p {0}'.format(defertestAcc.name), silentErrors=False) prodNode.waitForTransBlockIfNeeded(trans[1], True) - Utils.Print(f"trans is {trans}"); + #Utils.Print(f"trans is {trans}"); time.sleep(4) # sleep enough time to get hard fails. row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test Utils.Print("\taccount row4: ", row4) @@ -756,7 +756,7 @@ def makeReservedEvmAddress(account): actData = {"id":2,"account":evmAcc.name,"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:], "rlptx2":Web3.to_hex(signed_trx2.rawTransaction)[2:]} trans = prodNode.pushMessage(defertestAcc.name, "pushdefer", json.dumps(actData), '-p {0}'.format(defertestAcc.name), silentErrors=False) prodNode.waitForTransBlockIfNeeded(trans[1], True) - Utils.Print(f"trans is {trans}"); + #Utils.Print(f"trans is {trans}"); time.sleep(4) # sleep enough time to get soft fails. row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test Utils.Print("\taccount row4: ", row4) @@ -777,7 +777,7 @@ def makeReservedEvmAddress(account): # but evmevmevmevm::pushtx(rlptx1) will be executed before evmevmevmevm::pushtx(miner, rlptx2) amount=2.0000 transferAmount="2.000 {0}".format(CORE_SYMBOL) - Utils.Print("Test action ordering: action1: transfer EVM->EOS funds %s from account %s to %s via inline action" % (transferAmount, evmAcc.name, testAcc.name)) + Utils.Print("Test action ordering: action 1: transfer EVM->EOS funds %s from account %s to %s via inline action" % (transferAmount, evmAcc.name, testAcc.name)) nonce = nonce + 1 gasP = getGasPrice() signed_trx = w3.eth.account.sign_transaction(dict( @@ -809,6 +809,8 @@ def makeReservedEvmAddress(account): row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test Utils.Print("\taccount row4: ", row4) assert(row4["nonce"] == 5) + assert(row4["eth_address"] == "9e126c57330fa71556628e0aabd6b6b6783d99fa") + assert(row4["balance"] == "00000000000000000000000000000000000000000000000080cfc165cc75a000") # Launch eos-evm-node From cee832b199aee71d8cc5b90e4e1b9d81401db73d Mon Sep 17 00:00:00 2001 From: kayan Date: Tue, 15 Aug 2023 11:35:53 +0800 Subject: [PATCH 03/15] change silentErros to False --- tests/nodeos_eos_evm_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/nodeos_eos_evm_test.py b/tests/nodeos_eos_evm_test.py index 435c6a7..f527d38 100755 --- a/tests/nodeos_eos_evm_test.py +++ b/tests/nodeos_eos_evm_test.py @@ -318,7 +318,7 @@ def makeReservedEvmAddress(account): # add eosio.code permission cmd="set account permission evmevmevmevm active --add-code -p evmevmevmevm@active" - prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + prodNode.processCleosCmd(cmd, cmd, silentErrors=False, returnType=ReturnType.raw) # set defertest contract contractDir=eosEvmBuildRoot + "/tests" @@ -329,7 +329,7 @@ def makeReservedEvmAddress(account): # add eosio.code permission to defertest account cmd="set account permission " + defertestAcc.name + " active --add-code -p " + defertestAcc.name + "@active" - prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + prodNode.processCleosCmd(cmd, cmd, silentErrors=False, returnType=ReturnType.raw) # set defertest2 contract contractDir=eosEvmBuildRoot + "/tests" @@ -340,7 +340,7 @@ def makeReservedEvmAddress(account): # add eosio.code permission to defertest2 account cmd="set account permission " + defertest2Acc.name + " active --add-code -p " + defertest2Acc.name + "@active" - prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + prodNode.processCleosCmd(cmd, cmd, silentErrors=False, returnType=ReturnType.raw) trans = prodNode.pushMessage(evmAcc.name, "init", '{{"chainid":15555, "fee_params": {{"gas_price": "10000000000", "miner_cut": 100000, "ingress_bridge_fee": "0.0000 {0}"}}}}'.format(CORE_SYMBOL), '-p evmevmevmevm') prodNode.waitForTransBlockIfNeeded(trans[1], True) @@ -693,7 +693,7 @@ def makeReservedEvmAddress(account): ), evmSendKey) actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:]} cmd="push action " + evmAcc.name + " pushtx \"" + json.dumps(actData).replace("\"","\\\"") + "\" --delay-sec 2 -p " + minerAcc.name - trans=prodNode.processCleosCmd(cmd, cmd, silentErrors=True, returnType=ReturnType.raw) + trans=prodNode.processCleosCmd(cmd, cmd, silentErrors=False, returnType=ReturnType.raw) #Utils.Print(f"trans is {trans}"); time.sleep(4) # sleep enough time to get hard fails. row4=prodNode.getTableRow(evmAcc.name, evmAcc.name, "account", 4) # 4th balance of this integration test From 9b7adc16075c36833d1bc8417b8f5c1d9922c70d Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Thu, 16 Nov 2023 22:24:45 -0300 Subject: [PATCH 04/15] Bump 0.6.2 version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b0e6df..129e67c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ project(eos-evm-node) set(VERSION_MAJOR 0) set(VERSION_MINOR 6) -set(VERSION_PATCH 1) +set(VERSION_PATCH 2) #set(VERSION_SUFFIX stable) if(VERSION_SUFFIX) From 345794ea947751cbc0346781890138cc11421ece Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 28 Nov 2023 09:37:47 +0800 Subject: [PATCH 05/15] Update submodule to contain the fix. --- external/silkworm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/silkworm b/external/silkworm index 440e20a..c4336fc 160000 --- a/external/silkworm +++ b/external/silkworm @@ -1 +1 @@ -Subproject commit 440e20a035e11eb74f6d6a5a79fd3ddc848749ff +Subproject commit c4336fc616730db4ebdfd044863b0618a047a9b4 From e35eb48211cf204c93ede6b43deb1e1473c77ee6 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 28 Nov 2023 13:56:04 +0800 Subject: [PATCH 06/15] Update the submodule to contain the fix for trace quirk mode. --- external/silkworm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/silkworm b/external/silkworm index 4386ac2..134fa6f 160000 --- a/external/silkworm +++ b/external/silkworm @@ -1 +1 @@ -Subproject commit 4386ac20181f8f3b8641166cdf1cac9f884bfe10 +Subproject commit 134fa6ff41e18478bdf4e7c5e1ad09cf57b8a396 From 27f69cfca101091253df7bf3e40c8b31f1d9ff6e Mon Sep 17 00:00:00 2001 From: yarkinwho <99302011+yarkinwho@users.noreply.github.com> Date: Wed, 29 Nov 2023 09:33:54 +0800 Subject: [PATCH 07/15] Update node.yml Try to fix the CI --- .github/workflows/node.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index ea9f89c..4aca308 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -275,7 +275,7 @@ jobs: uses: AntelopeIO/asset-artifact-download-action@v3 with: owner: eosnetworkfoundation - repo: eos-evm + repo: eos-evm-contract target: '${{needs.versions.outputs.eos-evm-contract-target}}' prereleases: ${{fromJSON(needs.versions.outputs.eos-evm-contract-prerelease)}} file: 'contract.tar.gz' From f71c96d9043c6f94ad3143434c546a3b3f64f0c2 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Wed, 29 Nov 2023 00:35:55 -0300 Subject: [PATCH 08/15] Update silkworm with Extend EVMExecutor to have full and a partial reset of the internal state --- external/silkworm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/silkworm b/external/silkworm index c4336fc..4c1596f 160000 --- a/external/silkworm +++ b/external/silkworm @@ -1 +1 @@ -Subproject commit c4336fc616730db4ebdfd044863b0618a047a9b4 +Subproject commit 4c1596fd5ed57454c7b67f280c37ac90e9f04deb From f3116b837b0a0593e7703e4fd077ca89f79b5500 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Wed, 29 Nov 2023 02:49:47 -0300 Subject: [PATCH 09/15] Bump 0.6.3 version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 129e67c..8722e93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ project(eos-evm-node) set(VERSION_MAJOR 0) set(VERSION_MINOR 6) -set(VERSION_PATCH 2) +set(VERSION_PATCH 3) #set(VERSION_SUFFIX stable) if(VERSION_SUFFIX) From 0309ccd443d78690710cf1cfa258d3d0f91cbb7a Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Wed, 29 Nov 2023 12:04:29 -0300 Subject: [PATCH 10/15] Update silkworm --- external/silkworm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/silkworm b/external/silkworm index bc16409..6068526 160000 --- a/external/silkworm +++ b/external/silkworm @@ -1 +1 @@ -Subproject commit bc164091a549092fdac593653253a23c7777993c +Subproject commit 60685260a265fb8ebb2fea2975de42420cbfd87e From b55e375074a46e6058c302fb426c7a8003fe66cd Mon Sep 17 00:00:00 2001 From: yarkin Date: Thu, 30 Nov 2023 16:02:00 +0800 Subject: [PATCH 11/15] Prepare rate limit clauses. Not enabled. --- peripherals/proxy/nginx.conf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/peripherals/proxy/nginx.conf b/peripherals/proxy/nginx.conf index 8811d0f..d0e349e 100644 --- a/peripherals/proxy/nginx.conf +++ b/peripherals/proxy/nginx.conf @@ -44,11 +44,15 @@ http { ~^5 1; } + limit_req_zone $http_x_forwarded_for zone=rate_limit_zone:10m rate=5r/s; + server { listen 80; server_name localhost; - location / { + location / { + limit_req zone=rate_limit_zone burst=25 nodelay; + limit_req_dry_run on; try_files /nonexistent @$http_upgrade; } From 998829c3b2852b09e6e103bbcfb73f73aaf259f2 Mon Sep 17 00:00:00 2001 From: yarkin Date: Fri, 1 Dec 2023 13:08:09 +0800 Subject: [PATCH 12/15] Add limit_conn --- peripherals/proxy/nginx.conf | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/peripherals/proxy/nginx.conf b/peripherals/proxy/nginx.conf index d0e349e..2e648de 100644 --- a/peripherals/proxy/nginx.conf +++ b/peripherals/proxy/nginx.conf @@ -45,6 +45,7 @@ http { } limit_req_zone $http_x_forwarded_for zone=rate_limit_zone:10m rate=5r/s; + limit_conn_zone $http_x_forwarded_for zone=conn_limit_zone:10m; server { listen 80; @@ -56,7 +57,9 @@ http { try_files /nonexistent @$http_upgrade; } - location @websocket { + location @websocket { + limit_conn conn_limit_zone 2; + limit_conn_dry_run on; # websocket related stuff if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; From 9ccb787e8a1a0c70e07234d43d67b5f23e02105b Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Fri, 1 Dec 2023 19:34:24 -0300 Subject: [PATCH 13/15] Fix tests --- tests/nodeos_eos_evm_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/nodeos_eos_evm_test.py b/tests/nodeos_eos_evm_test.py index 72745f4..03a902b 100755 --- a/tests/nodeos_eos_evm_test.py +++ b/tests/nodeos_eos_evm_test.py @@ -280,7 +280,6 @@ def makeReservedEvmAddress(account): minerAcc = accounts[2] defertestAcc = accounts[3] defertest2Acc = accounts[4] - minerAcc = txWrapAcc testWalletName="test" From fc2dfe474311d2605adc6891deb54750231c9f53 Mon Sep 17 00:00:00 2001 From: yarkin Date: Tue, 5 Dec 2023 13:09:28 +0800 Subject: [PATCH 14/15] Update submodule silkworm. --- external/silkworm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/silkworm b/external/silkworm index 6068526..ad3a9dd 160000 --- a/external/silkworm +++ b/external/silkworm @@ -1 +1 @@ -Subproject commit 60685260a265fb8ebb2fea2975de42420cbfd87e +Subproject commit ad3a9dda0395440eb6fd0b71953d12257c12daac From 87bf0299f4d23455dcc5dabfb3703773ee6ca356 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Wed, 6 Dec 2023 16:45:25 -0300 Subject: [PATCH 15/15] Add special signatures handling integration tests --- tests/nodeos_eos_evm_test.py | 76 ++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/tests/nodeos_eos_evm_test.py b/tests/nodeos_eos_evm_test.py index 03a902b..bf4d3aa 100755 --- a/tests/nodeos_eos_evm_test.py +++ b/tests/nodeos_eos_evm_test.py @@ -675,6 +675,73 @@ def makeReservedEvmAddress(account): if testAccActualAmount != expectedAmount: Utils.errorExit("Transfer verification failed. Excepted %s, actual: %s" % (expectedAmount, testAccActualAmount)) + ### Special signature test (begin) + # Increment contract + ''' + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.8.2 <0.9.0; + contract Increment { + mapping (address => uint256) values; + function increment() public { + values[msg.sender]++; + } + function retrieve(address a) public view returns (uint256){ + return values[a]; + } + } + ''' + + accSpecialKey = '344260572d5df010d70597386bfeeaecf863a8dbbe3c9a023f81d7056b28815f' + accSpecialAdd = w3.eth.account.from_key(accSpecialKey).address + + prodNode.transferFunds(testAcc, evmAcc, "10.0000 EOS", "0x0290ffefa58ee84a3641770ab910c48d3441752d", waitForTransBlock=True) + prodNode.transferFunds(testAcc, evmAcc, "1000.0000 EOS", accSpecialAdd, waitForTransBlock=True) + + # Test special signature handling (contract and evm-node) + Print("Test special signature handling (both contract and evm-node)") + special_nonce = 0 + signed_trx = w3.eth.account.sign_transaction(dict( + nonce=special_nonce, + gas=1000000, + gasPrice=getGasPrice(), + data=Web3.to_bytes(hexstr='608060405234801561001057600080fd5b50610284806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630a79309b1461003b578063d09de08a1461006b575b600080fd5b61005560048036038101906100509190610176565b610075565b60405161006291906101bc565b60405180910390f35b6100736100bd565b005b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081548092919061010c90610206565b9190505550565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061014382610118565b9050919050565b61015381610138565b811461015e57600080fd5b50565b6000813590506101708161014a565b92915050565b60006020828403121561018c5761018b610113565b5b600061019a84828501610161565b91505092915050565b6000819050919050565b6101b6816101a3565b82525050565b60006020820190506101d160008301846101ad565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000610211826101a3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610243576102426101d7565b5b60018201905091905056fea264697066735822122026d27f46966ee75c7a8b2a43923c8796438013de730eb9eec6c24ff581913d6864736f6c63430008120033'), + chainId=15555 + ), accSpecialKey) + + # Deploy "Increment" contract + increment_contract = makeContractAddress(accSpecialAdd, special_nonce) + actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:]} + trans = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=True) + prodNode.waitForTransBlockIfNeeded(trans[1], True); + + # Test special signature: Call from `accSpecialAdd` + special_nonce += 1 + signed_trx = w3.eth.account.sign_transaction(dict( + nonce=special_nonce, + gas=1000000, + gasPrice=getGasPrice(), + to=Web3.to_checksum_address(increment_contract), + data=Web3.to_bytes(hexstr='D09DE08A'), # sha3(increment())=0xD09DE08A + chainId=15555 + ), accSpecialKey) + + actData = {"miner":minerAcc.name, "rlptx":Web3.to_hex(signed_trx.rawTransaction)[2:]} + trans = prodNode.pushMessage(evmAcc.name, "pushtx", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=True) + prodNode.waitForTransBlockIfNeeded(trans[1], True); + + # Test special signature: Call from miner account + actData = {"from":minerAcc.name, "to":increment_contract[2:], "value":"0000000000000000000000000000000000000000000000000000000000000000", "data":"d09de08a", "gas_limit":"100000"} + trans = prodNode.pushMessage(evmAcc.name, "call", json.dumps(actData), '-p {0}'.format(minerAcc.name), silentErrors=True) + prodNode.waitForTransBlockIfNeeded(trans[1], True); + + # Test special signature: Call from `0x0290ffefa58ee84a3641770ab910c48d3441752d` + prodNode.transferFunds(testAcc, evmAcc, "10.0000 EOS", "0x0290ffefa58ee84a3641770ab910c48d3441752d", waitForTransBlock=True) + actData = {"from":"0290ffefa58ee84a3641770ab910c48d3441752d", "to":increment_contract[2:], "value":"0000000000000000000000000000000000000000000000000000000000000000", "data":"d09de08a", "gas_limit":"100000"} + trans = prodNode.pushMessage(evmAcc.name, "admincall", json.dumps(actData), '-p {0}'.format(evmAcc.name), silentErrors=True) + prodNode.waitForTransBlockIfNeeded(trans[1], True); + + ### Special signature test (end) + # test hard-failed transaction (with --delay-sec) amount=7.0000 transferAmount="7.000 {0}".format(CORE_SYMBOL) @@ -847,6 +914,15 @@ def makeReservedEvmAddress(account): raise assert r == int(row['balance'],16), f"{row['eth_address']} {r} != {int(row['balance'],16)}" + # Validate special signatures handling + def get_stored_value(address): + result = processUrllibRequest("http://127.0.0.1:8881", payload={"method":"eth_call","params":[{"from":fromAdd, "to":increment_contract, "data":"0x0a79309b000000000000000000000000"+address}, "latest"],"id":1,"jsonrpc":"2.0"}) + return int(result["payload"]["result"], 16) + + assert(get_stored_value(accSpecialAdd[2:]) == 1) #pushtx + assert(get_stored_value(makeReservedEvmAddress(convert_name_to_value(minerAcc.name))[2:]) == 1) #call + assert(get_stored_value('0290ffefa58ee84a3641770ab910c48d3441752d') == 1) #admincall + foundErr = False stdErrFile = open(nodeStdErrDir, "r") lines = stdErrFile.readlines()