From 4b47ac995e772e3a95a84328db48ac86f2fe1e69 Mon Sep 17 00:00:00 2001 From: Vaivaswatha Nagaraj Date: Mon, 2 Aug 2021 22:07:49 +0530 Subject: [PATCH 1/3] Accounting tests https://github.com/Zilliqa/scilla/pull/1032 --- tests/Data/Test_Contract.cpp | 177 ++++++++++++++++++++++++++++++++--- 1 file changed, 166 insertions(+), 11 deletions(-) diff --git a/tests/Data/Test_Contract.cpp b/tests/Data/Test_Contract.cpp index c187539602..512c7b5176 100644 --- a/tests/Data/Test_Contract.cpp +++ b/tests/Data/Test_Contract.cpp @@ -1824,7 +1824,7 @@ BOOST_AUTO_TEST_CASE(testRemoteStateReads) { // ------------- execute transitions ------------------------------------// - for (unsigned i = 1; i <= 11; i++) { + for (unsigned i = 1; i <= 10; i++) { LOG_GENERAL(WARNING, "Executing remote_state_reads_" << i); // Execute message_i ScillaTestUtil::ScillaTest rsr_i; @@ -1875,16 +1875,7 @@ BOOST_AUTO_TEST_CASE(testRemoteStateReads) { BOOST_FAIL("Couldn't convert format of expected Scilla output state" << rsr_i.expOutput["states"].toStyledString()); } - if (i == 9) { - // The 9th test relies on sender (owner above) balance, but cannot - // account for the gas fees paid by the sender. So we just compare - // the required output here and not from the gold file. - BOOST_REQUIRE(outState["sender_balance_pre"].asString() == "950000"); - BOOST_REQUIRE(outState["sender_balance_mid"].asString() == "949900"); - BOOST_REQUIRE(outState["sender_balance_post"].asString() == "949900"); - } else { - BOOST_REQUIRE_EQUAL(expOutput, outState); - } + BOOST_REQUIRE_EQUAL(expOutput, outState); LOG_GENERAL(WARNING, "remote_state_reads_" << i << " succeeded"); Contract::ContractStorage::GetContractStorage().Reset(); } @@ -1958,6 +1949,170 @@ BOOST_AUTO_TEST_CASE(testRemoteStateReads) { depTest("init_balance_and_nonce"); } +BOOST_AUTO_TEST_CASE(accounting_tests) { + INIT_STDOUT_LOGGER(); + LOG_MARKER(); + + // Disable pretty printing of Scilla literals. This will ensure + // that Scilla Lists are not printed using JSON arrays, enabling + // us to ensure that JSON arrays only represent Scilla maps. + SCILLA_PPLIT_FLAG = false; + + setup(); + + PairOfKey owner(priv1, PubKey(priv1)); + + if (SCILLA_ROOT.empty()) { + BOOST_FAIL("SCILLA_ROOT not set to run Test_Contract"); + } + + AccountStore::GetInstance().Init(); + + // Setup all accounts we interact with. + auto ownerAddr = Account::GetAddressFromPublicKey(owner.second); + LOG_GENERAL(INFO, "Owner address: " << ownerAddr); + + uint64_t ownerNonce = 0; + AccountStore::GetInstance().AddAccountTemp(ownerAddr, + {2000000000000000, ownerNonce}); + + auto supportAddr = Account::GetAddressForContract(ownerAddr, ownerNonce); + LOG_GENERAL(INFO, + "Accounting tests support contract will be deployed at address " + << supportAddr); + ownerNonce++; + auto mainAddr = Account::GetAddressForContract(ownerAddr, ownerNonce); + LOG_GENERAL(INFO, + "Accounting tests main contract will be deployed at address " + << mainAddr); + ownerNonce++; + + std::map> state_entries; + std::unordered_map balances; + std::unordered_map nonces; + std::unordered_map> mapdepths; + + // ----------------- map depths ------------------------------------ // + + mapdepths[mainAddr]["test_string_1"] = 0; + mapdepths[mainAddr]["test_string_2"] = 0; + mapdepths[mainAddr]["outgoing_amount"] = 0; + mapdepths[mainAddr]["max_outgoing_msgs"] = 0; + mapdepths[supportAddr]["stored_strings"] = 0; + + // ----------------- map depths ------------------------------------ // + + // ------------------- deploy ---------------------------------------// + + ScillaTestUtil::ScillaTest support_dep; + if (!ScillaTestUtil::GetScillaDeployment( + support_dep, "accounting_tests_support", "", "init.json", + "blockchain_1.json", "init_output.json", "0")) { + BOOST_FAIL("Unable to fetch test accounting_tests_support: deployment."); + } + // and remove _creation_block (automatic insertion later). + ScillaTestUtil::RemoveCreationBlockFromInit(support_dep.init); + ScillaTestUtil::RemoveThisAddressFromInit(support_dep.init); + uint64_t bnum = + ScillaTestUtil::GetBlockNumberFromJson(support_dep.blockchain); + + // Transaction to deploy support contract. + std::string initStr = + JSONUtils::GetInstance().convertJsontoStr(support_dep.init); + bytes data2(initStr.begin(), initStr.end()); + Transaction tx1(1, ownerNonce, NullAddress, owner, 0, PRECISION_MIN_VALUE, + 500000, support_dep.code, data2); + TransactionReceipt tr1; + TxnStatus error_code; + AccountStore::GetInstance().UpdateAccountsTemp(bnum, 1, true, tx1, tr1, + error_code); + ownerNonce++; + + ScillaTestUtil::ScillaTest main_dep; + if (!ScillaTestUtil::GetScillaDeployment(main_dep, "accounting_tests", "", + "init.json", "blockchain_1.json", + "init_output.json", "0")) { + BOOST_FAIL("Unable to fetch test accounting_tests: deployment."); + } + // and remove _creation_block (automatic insertion later). + ScillaTestUtil::RemoveCreationBlockFromInit(main_dep.init); + ScillaTestUtil::RemoveThisAddressFromInit(main_dep.init); + bnum = ScillaTestUtil::GetBlockNumberFromJson(main_dep.blockchain); + + // Transaction to deploy main contract. + initStr = JSONUtils::GetInstance().convertJsontoStr(main_dep.init); + bytes data(initStr.begin(), initStr.end()); + Transaction tx0(1, ownerNonce, NullAddress, owner, 0, PRECISION_MIN_VALUE, + 500000, main_dep.code, data); + TransactionReceipt tr0; + AccountStore::GetInstance().UpdateAccountsTemp(bnum, 1, true, tx0, tr0, + error_code); + ownerNonce++; + + // ------------- execute transitions ------------------------------------// + + // We need some account handle to set the state. The actual account whose + // state is being updated is passed as an argument to UpdateStates. + Account* account = AccountStore::GetInstance().GetAccountTemp(ownerAddr); + // Test numbers that invoke Test_Send_i + int tests[] = {2, 4, 6, 9, 10, 11, 12, 14, 15, 17, 18, 19, 20, 21}; + + for (auto i : tests) { + LOG_GENERAL(WARNING, "Executing accounting_tests_" << i); + // Execute message_i + ScillaTestUtil::ScillaTest at_i; + if (!ScillaTestUtil::GetScillaTest(at_i, "accounting_tests", i)) { + BOOST_FAIL("Unable to fetch test accounting_tests_" << i); + } + // remove _creation_block (automatic insertion later). + ScillaTestUtil::RemoveCreationBlockFromInit(at_i.init); + ScillaTestUtil::RemoveThisAddressFromInit(at_i.init); + bnum = ScillaTestUtil::GetBlockNumberFromJson(at_i.blockchain); + + state_entries.clear(); + balances.clear(); + nonces.clear(); + if (!ScillaTestUtil::parseStateJSON(mainAddr, at_i.state, mapdepths, + state_entries, balances, nonces)) { + BOOST_FAIL("parseStateJSON failed"); + } + // Set state_i. + for (const auto& itr : state_entries) { + account->UpdateStates(itr.first, itr.second, {}, true); + } + for (const auto& addrBal : balances) { + if (addrBal.first != ownerAddr) { + account = AccountStore::GetInstance().GetAccountTemp(addrBal.first); + account->SetBalance(addrBal.second); + } + } + for (const auto& addrNonce : nonces) { + if (addrNonce.first != ownerAddr) { + account = AccountStore::GetInstance().GetAccountTemp(addrNonce.first); + account->SetNonce(addrNonce.second); + } + } + + uint64_t amount = ScillaTestUtil::PrepareMessageData(at_i.message, data); + Transaction tx_i(DataConversion::Pack(CHAIN_ID, 1), ownerNonce, mainAddr, + owner, amount, PRECISION_MIN_VALUE, 5000, {}, data); + TransactionReceipt tr4; + if (AccountStore::GetInstance().UpdateAccountsTemp(bnum, 1, true, tx_i, tr4, + error_code)) { + ownerNonce++; + } + tr4.InstallError(); + if (tr4.GetJsonValue().get("errors", Json::arrayValue).size() > 0) { + BOOST_ERROR("Encountered error in account_tests_" << i); + } + // We don't compare the outputs because the tests are designed to fail + // if something goes wrong. Outputs can't be compared due to complex + // chain calls involved. Each Scilla test is only an intermediate step. + LOG_GENERAL(WARNING, "accounting_tests_" << i << " succeeded"); + Contract::ContractStorage::GetContractStorage().Reset(); + } +} + // BOOST_AUTO_TEST_CASE(testDEX) { // INIT_STDOUT_LOGGER(); // LOG_MARKER(); From 50307ede172b665a637ec8a347c411201efa050e Mon Sep 17 00:00:00 2001 From: Vaivaswatha Nagaraj Date: Tue, 3 Aug 2021 09:37:38 +0530 Subject: [PATCH 2/3] Add test that asserts amount removed from sender balance. Fails --- tests/Data/Test_Contract.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Data/Test_Contract.cpp b/tests/Data/Test_Contract.cpp index 512c7b5176..c9fd8e2862 100644 --- a/tests/Data/Test_Contract.cpp +++ b/tests/Data/Test_Contract.cpp @@ -2055,7 +2055,7 @@ BOOST_AUTO_TEST_CASE(accounting_tests) { // state is being updated is passed as an argument to UpdateStates. Account* account = AccountStore::GetInstance().GetAccountTemp(ownerAddr); // Test numbers that invoke Test_Send_i - int tests[] = {2, 4, 6, 9, 10, 11, 12, 14, 15, 17, 18, 19, 20, 21}; + int tests[] = {2, 4, 6, 9, 10, 11, 12, 14, 15, 17, 18, 19, 20, 21, 22}; for (auto i : tests) { LOG_GENERAL(WARNING, "Executing accounting_tests_" << i); From a531b610fa2c748b583bec4069791f8101e4877c Mon Sep 17 00:00:00 2001 From: KaustubhShamshery Date: Tue, 7 Dec 2021 18:57:39 +0530 Subject: [PATCH 3/3] Change balance view given to scilla --- src/libData/AccountData/AccountStoreSC.tpp | 8 +++++++- tests/Data/Test_Contract.cpp | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libData/AccountData/AccountStoreSC.tpp b/src/libData/AccountData/AccountStoreSC.tpp index 331d66c1f0..a11f028cc3 100644 --- a/src/libData/AccountData/AccountStoreSC.tpp +++ b/src/libData/AccountData/AccountStoreSC.tpp @@ -588,6 +588,8 @@ bool AccountStoreSC::UpdateAccounts(const uint64_t& blockNum, std::string runnerPrint; bool ret = true; + auto senderAccount = m_accountStoreAtomic->GetAccount(fromAddr); + senderAccount->DecreaseBalance(m_curAmount); InvokeInterpreter(RUNNER_CALL, runnerPrint, scilla_version, is_library, gasRemained, this->GetBalance(toAddr), ret, receipt); @@ -595,6 +597,7 @@ bool AccountStoreSC::UpdateAccounts(const uint64_t& blockNum, LOG_GENERAL(INFO, "Executed root transition in " << r_timer_end(tpStart) << " microseconds"); } + senderAccount->IncreaseBalance(m_curAmount); uint32_t tree_depth = 0; @@ -1468,7 +1471,7 @@ bool AccountStoreSC::ParseCallContractJsonOutput( account->GetStorageRoot()); std::string runnerPrint; bool result = true; - + contractAccount->DecreaseBalance(m_curAmount); InvokeInterpreter(RUNNER_CALL, runnerPrint, scilla_version, is_library, gasRemained, account->GetBalance(), result, receipt); @@ -1478,12 +1481,15 @@ bool AccountStoreSC::ParseCallContractJsonOutput( << " microseconds"); } + contractAccount->IncreaseBalance(m_curAmount); + if (!result) { return false; } m_curSenderAddr = curContractAddr; m_curContractAddr = recipient; + if (!ParseCallContract(gasRemained, runnerPrint, receipt, tree_depth + 1, scilla_version)) { LOG_GENERAL(WARNING, "ParseCallContract failed of calling contract: " diff --git a/tests/Data/Test_Contract.cpp b/tests/Data/Test_Contract.cpp index c9fd8e2862..aa28f437c7 100644 --- a/tests/Data/Test_Contract.cpp +++ b/tests/Data/Test_Contract.cpp @@ -2101,6 +2101,8 @@ BOOST_AUTO_TEST_CASE(accounting_tests) { error_code)) { ownerNonce++; } + account = AccountStore::GetInstance().GetAccountTemp(mainAddr); + LOG_GENERAL(INFO, "Balance: " << account->GetBalance()); tr4.InstallError(); if (tr4.GetJsonValue().get("errors", Json::arrayValue).size() > 0) { BOOST_ERROR("Encountered error in account_tests_" << i);