uint64_t getAccountBalance(SecretKey const& k, Application& app) { AccountFrame account; REQUIRE(AccountFrame::loadAccount(k.getPublicKey(), account, app.getDatabase())); return account.getBalance(); }
vector<Simulation::AccountInfoPtr> Simulation::accountsOutOfSyncWithDb() { vector<AccountInfoPtr> result; int iApp = 0; int64_t totalOffsets = 0; for (auto pair : mNodes) { iApp++; auto app = pair.second; for (auto accountIt = mAccounts.begin() + 1; accountIt != mAccounts.end(); accountIt++) { auto account = *accountIt; AccountFrame accountFrame; bool res = AccountFrame::loadAccount( account->mKey.getPublicKey(), accountFrame, app->getDatabase()); int64_t offset; if (res) { offset = accountFrame.getBalance() - static_cast<int64_t>(account->mBalance); account->mSeq = accountFrame.getSeqNum(); } else { offset = -1; } if (offset != 0) { LOG(DEBUG) << "On node " << iApp << ", account " << account->mId << " is off by " << (offset) << "\t(has " << accountFrame.getBalance() << " should have " << account->mBalance << ")"; totalOffsets += abs(offset); result.push_back(account); } } } LOG(INFO) << "Ledger has not yet caught up to the simulation. totalOffsets: " << totalOffsets; return result; }
bool Simulation::loadAccount(AccountInfo& account) { // assumes all nodes are in sync auto app = mNodes.begin()->second; AccountFrame ret; if (!AccountFrame::loadAccount(account.mKey.getPublicKey(), ret, app->getDatabase())) { return false; } account.mBalance = ret.getBalance(); account.mSeq = ret.getSeqNum(); return true; }
static void doInflation(Application& app, int nbAccounts, std::function<int64(int)> getBalance, std::function<int(int)> getVote, int expectedWinnerCount) { // simulate the expected inflation based off the current ledger state std::map<int, int64> balances; // load account balances for (int i = 0; i < nbAccounts; i++) { AccountFrame act; if (getBalance(i) < 0) { balances[i] = -1; REQUIRE(!AccountFrame::loadAccount(getTestAccount(i).getPublicKey(), act, app.getDatabase())); } else { REQUIRE(AccountFrame::loadAccount(getTestAccount(i).getPublicKey(), act, app.getDatabase())); balances[i] = act.getBalance(); // double check that inflationDest is setup properly if (act.getAccount().inflationDest) { REQUIRE(getTestAccount(getVote(i)).getPublicKey() == *act.getAccount().inflationDest); } else { REQUIRE(getVote(i) < 0); } } } LedgerManager& lm = app.getLedgerManager(); LedgerHeader& cur = lm.getCurrentLedgerHeader(); cur.feePool = 10000; int64 expectedTotcoins = cur.totalCoins; int64 expectedFees = cur.feePool; std::vector<int64> expectedBalances; auto root = getRoot(); TransactionFramePtr txFrame = createInflation(root, getAccountSeqNum(root, app) + 1); expectedFees += txFrame->getFee(app); expectedBalances = simulateInflation(nbAccounts, expectedTotcoins, expectedFees, [&](int i) { return balances[i]; }, getVote); // perform actual inflation { LedgerDelta delta(lm.getCurrentLedgerHeader()); REQUIRE(txFrame->apply(delta, app)); delta.commit(); } // verify ledger state LedgerHeader& cur2 = lm.getCurrentLedgerHeader(); REQUIRE(cur2.totalCoins == expectedTotcoins); REQUIRE(cur2.feePool == expectedFees); // verify balances InflationResult const& infResult = getFirstResult(*txFrame).tr().inflationResult(); auto const& payouts = infResult.payouts(); int actualChanges = 0; for (int i = 0; i < nbAccounts; i++) { AccountFrame act; auto const& pk = getTestAccount(i).getPublicKey(); if (expectedBalances[i] < 0) { REQUIRE(!AccountFrame::loadAccount(pk, act, app.getDatabase())); REQUIRE(balances[i] < 0); // account didn't get deleted } else { REQUIRE(AccountFrame::loadAccount(pk, act, app.getDatabase())); REQUIRE(expectedBalances[i] == act.getBalance()); if (expectedBalances[i] != balances[i]) { REQUIRE(balances[i] >= 0); actualChanges++; bool found = false; for (auto const& p : payouts) { if (p.destination == pk) { int64 computedFromResult = balances[i] + p.amount; REQUIRE(computedFromResult == expectedBalances[i]); found = true; break; } } REQUIRE(found); } } } REQUIRE(actualChanges == expectedWinnerCount); REQUIRE(expectedWinnerCount == payouts.size()); }