Exemple #1
0
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());
}