Beispiel #1
0
static
Rate
rippleQuality (
    ReadView const& view,
    AccountID const& destination,
    AccountID const& source,
    Currency const& currency,
    SField const& sfLow,
    SField const& sfHigh)
{
    if (destination == source)
        return parityRate;

    auto const& sfField = destination < source ? sfLow : sfHigh;

    auto const sle = view.read(
        keylet::line(destination, source, currency));

    if (!sle || !sle->isFieldPresent (sfField))
        return parityRate;

    auto quality = sle->getFieldU32 (sfField);

    // Avoid divide by zero. NIKB CHECKME: if we
    // allow zero qualities now, then we shouldn't.
    if (quality == 0)
        quality = 1;

    return Rate{ quality };
}
Beispiel #2
0
void
fill_fee (Json::Value& jv,
    ReadView const& view)
{
    if (jv.isMember(jss::Fee))
        return;
    jv[jss::Fee] = std::to_string(
        view.fees().base);
}
Beispiel #3
0
void
fill_fee (Json::Value& jv,
    ReadView const& view)
{
    if (jv.isMember(jss::Fee))
        return;
    auto fee = view.fees().base;
    if (jv.isMember (jss::TransactionType) &&
        (jv[jss::TransactionType].asString () == "Payment" ||
         jv[jss::TransactionType].asString () == "ActiveAccount"))
    {
        if (jv.isMember (jss::Amount))
        {
            STAmount amount;
            amountFromJsonNoThrow (amount, jv[jss::Amount]);
            if (amount.native ())
                fee = std::max (multiply (amount, amountFromRate (Config ().FEE_DEFAULT_RATE_NATIVE),
                                          amount.issue ())
                                    .mantissa (),
                                Config ().FEE_DEFAULT_MIN_NATIVE);
        }
        if (jv.isMember (jv[jss::TransactionType].asString () == "ActiveAccount" ?
                             jss::Reference :
                             jss::Destination))
        {
            auto const account =
                parseBase58<AccountID> (
                    jv[jv[jss::TransactionType].asString () == "ActiveAccount" ?
                           jss::Reference :
                           jss::Destination]
                        .asString ());
            if (!account)
                throw parse_error (
                    "unexpected invalid Destination");
            if (!view.exists (keylet::account (*account)))
                fee += Config ().FEE_DEFAULT_CREATE;
        }
    }
    jv[jss::Fee] = std::to_string(
        fee);
}
Beispiel #4
0
bool
RawStateTable::exists (ReadView const& base,
    Keylet const& k) const
{
    assert(k.key.isNonZero());
    auto const iter = items_.find(k.key);
    if (iter == items_.end())
        return base.exists(k);
    auto const& item = iter->second;
    if (item.first == Action::erase)
        return false;
    if (! k.check(*item.second))
        return false;
    return true;
}
Beispiel #5
0
std::shared_ptr<SLE const>
RawStateTable::read (ReadView const& base,
    Keylet const& k) const
{
    auto const iter =
        items_.find(k.key);
    if (iter == items_.end())
        return base.read(k);
    auto const& item = iter->second;
    if (item.first == Action::erase)
        return nullptr;
    // Convert to SLE const
    std::shared_ptr<
        SLE const> sle = item.second;
    if (! k.check(*sle))
        return nullptr;
    return sle;
}
Beispiel #6
0
std::uint64_t Transactor::calculateBaseFee (
    ReadView const& view,
    STTx const& tx)
{
    // Returns the fee in fee units.

    // The computation has two parts:
    //  * The base fee, which is the same for most transactions.
    //  * The additional cost of each multisignature on the transaction.
    std::uint64_t baseFee = view.fees().units;

    // Each signer adds one more baseFee to the minimum required fee
    // for the transaction.
    std::uint32_t signerCount = 0;
    if (tx.isFieldPresent (sfSigners))
        signerCount = tx.getFieldArray (sfSigners).size();

    return baseFee + (signerCount * baseFee);
}
Beispiel #7
0
void
fill_seq (Json::Value& jv,
    ReadView const& view)
{
    if (jv.isMember(jss::Sequence))
        return;
    auto const account =
        parseBase58<AccountID>(
            jv[jss::Account].asString());
    if (! account)
        Throw<parse_error> (
            "unexpected invalid Account");
    auto const ar = view.read(
        keylet::account(*account));
    if (! ar)
        Throw<parse_error> (
            "unexpected missing account root");
    jv[jss::Sequence] =
        ar->getFieldU32(sfSequence);
}
Beispiel #8
0
std::size_t
FeeMetrics::updateFeeMetrics(Application& app,
    ReadView const& view, bool timeLeap)
{
    std::vector<uint64_t> feeLevels;
    std::size_t txnsExpected;
    std::size_t mimimumTx;
    std::uint32_t escalationMultiplier;
    {
        std::lock_guard <std::mutex> sl(lock_);
        feeLevels.reserve(txnsExpected_);
        txnsExpected = txnsExpected_;
        mimimumTx = minimumTxnCount_;
        escalationMultiplier = escalationMultiplier_;
    }
    for (auto const& tx : view.txs)
    {
        auto const baseFee = calculateBaseFee(app, view,
            *tx.first, j_);
        feeLevels.push_back(getFeeLevelPaid(*tx.first,
            baseLevel, baseFee));
    }
    std::sort(feeLevels.begin(), feeLevels.end());
    auto const size = feeLevels.size();

    JLOG(j_.debug) << "Ledger " << view.info().seq <<
        " has " << size << " transactions. " <<
        "Ledgers are processing " <<
        (timeLeap ? "slowly" : "as expected") <<
        ". Expected transactions is currently " <<
        txnsExpected << " and multiplier is " <<
        escalationMultiplier;

    if (timeLeap)
    {
        // Ledgers are taking to long to process,
        // so clamp down on limits.
        txnsExpected = boost::algorithm::clamp(feeLevels.size(),
            mimimumTx, targetTxnCount_ - 1);
    }
    else if (feeLevels.size() > txnsExpected ||
        feeLevels.size() > targetTxnCount_)
    {
        // Ledgers are processing in a timely manner,
        // so keep the limit high, but don't let it
        // grow without bound.
        txnsExpected = feeLevels.size();
    }

    if (feeLevels.empty())
    {
        escalationMultiplier = minimumMultiplier_;
    }
    else
    {
        // In the case of an odd number of elements, this
        // evaluates to the middle element; for an even
        // number of elements, it will add the two elements
        // on either side of the "middle" and average them.
        escalationMultiplier = (feeLevels[size / 2] +
            feeLevels[(size - 1) / 2] + 1) / 2;
        escalationMultiplier = std::max(escalationMultiplier,
            minimumMultiplier_);
    }
    JLOG(j_.debug) << "Expected transactions updated to " <<
        txnsExpected << " and multiplier updated to " <<
        escalationMultiplier;

    std::lock_guard <std::mutex> sl(lock_);
    txnsExpected_ = txnsExpected;
    escalationMultiplier_ = escalationMultiplier;

    return size;
}