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 }; }
void fill_fee (Json::Value& jv, ReadView const& view) { if (jv.isMember(jss::Fee)) return; jv[jss::Fee] = std::to_string( view.fees().base); }
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); }
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; }
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; }
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); }
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); }
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; }