20#include <xrpld/app/consensus/RCLConsensus.h>
21#include <xrpld/app/consensus/RCLValidations.h>
22#include <xrpld/app/ledger/AcceptedLedger.h>
23#include <xrpld/app/ledger/InboundLedgers.h>
24#include <xrpld/app/ledger/LedgerMaster.h>
25#include <xrpld/app/ledger/LedgerToJson.h>
26#include <xrpld/app/ledger/LocalTxs.h>
27#include <xrpld/app/ledger/OpenLedger.h>
28#include <xrpld/app/ledger/OrderBookDB.h>
29#include <xrpld/app/ledger/TransactionMaster.h>
30#include <xrpld/app/main/LoadManager.h>
31#include <xrpld/app/misc/AmendmentTable.h>
32#include <xrpld/app/misc/DeliverMax.h>
33#include <xrpld/app/misc/HashRouter.h>
34#include <xrpld/app/misc/LoadFeeTrack.h>
35#include <xrpld/app/misc/NetworkOPs.h>
36#include <xrpld/app/misc/Transaction.h>
37#include <xrpld/app/misc/TxQ.h>
38#include <xrpld/app/misc/ValidatorList.h>
39#include <xrpld/app/misc/detail/AccountTxPaging.h>
40#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
41#include <xrpld/app/tx/apply.h>
42#include <xrpld/consensus/Consensus.h>
43#include <xrpld/consensus/ConsensusParms.h>
44#include <xrpld/overlay/Cluster.h>
45#include <xrpld/overlay/Overlay.h>
46#include <xrpld/overlay/predicates.h>
47#include <xrpld/perflog/PerfLog.h>
48#include <xrpld/rpc/BookChanges.h>
49#include <xrpld/rpc/DeliveredAmount.h>
50#include <xrpld/rpc/MPTokenIssuanceID.h>
51#include <xrpld/rpc/ServerHandler.h>
53#include <xrpl/basics/UptimeClock.h>
54#include <xrpl/basics/mulDiv.h>
55#include <xrpl/basics/safe_cast.h>
56#include <xrpl/basics/scope.h>
57#include <xrpl/beast/utility/rngfill.h>
58#include <xrpl/crypto/RFC1751.h>
59#include <xrpl/crypto/csprng.h>
60#include <xrpl/protocol/BuildInfo.h>
61#include <xrpl/protocol/Feature.h>
62#include <xrpl/protocol/MultiApiJson.h>
63#include <xrpl/protocol/RPCErr.h>
64#include <xrpl/protocol/jss.h>
65#include <xrpl/resource/Fees.h>
66#include <xrpl/resource/ResourceManager.h>
68#include <boost/asio/ip/host_name.hpp>
69#include <boost/asio/steady_timer.hpp>
108 "ripple::NetworkOPsImp::TransactionStatus::TransactionStatus : "
151 std::chrono::steady_clock::time_point
start_ =
212 return !(*
this != b);
231 boost::asio::io_service& io_svc,
245 app_.logs().journal(
"FeeVote")),
248 app.getInboundTransactions(),
249 beast::get_abstract_clock<
std::chrono::steady_clock>(),
251 app_.logs().journal(
"LedgerConsensus"))
432 getServerInfo(
bool human,
bool admin,
bool counters)
override;
459 TER result)
override;
493 bool historyOnly)
override;
499 bool historyOnly)
override;
567 boost::system::error_code ec;
572 <<
"NetworkOPs: heartbeatTimer cancel error: "
581 <<
"NetworkOPs: clusterTimer cancel error: "
590 <<
"NetworkOPs: accountHistoryTxTimer cancel error: "
595 using namespace std::chrono_literals;
605 boost::asio::steady_timer& timer,
785 template <
class Handler>
787 Handler
const& handler,
789 :
hook(collector->make_hook(handler))
792 "Disconnected_duration"))
795 "Connected_duration"))
797 collector->make_gauge(
"State_Accounting",
"Syncing_duration"))
800 "Tracking_duration"))
802 collector->make_gauge(
"State_Accounting",
"Full_duration"))
805 "Disconnected_transitions"))
808 "Connected_transitions"))
811 "Syncing_transitions"))
814 "Tracking_transitions"))
816 collector->make_gauge(
"State_Accounting",
"Full_transitions"))
845 {
"disconnected",
"connected",
"syncing",
"tracking",
"full"}};
907 static std::string const hostname = boost::asio::ip::host_name();
914 static std::string const shroudedHostId = [
this]() {
920 return shroudedHostId;
935 boost::asio::steady_timer& timer,
942 [
this, onExpire, onError](boost::system::error_code
const& e) {
943 if ((e.value() == boost::system::errc::success) &&
944 (!m_job_queue.isStopped()))
949 if (e.value() != boost::system::errc::success &&
950 e.value() != boost::asio::error::operation_aborted)
953 JLOG(m_journal.error())
954 <<
"Timer got error '" << e.message()
955 <<
"'. Restarting timer.";
960 timer.expires_from_now(expiry_time);
961 timer.async_wait(std::move(*optionalCountedHandler));
966NetworkOPsImp::setHeartbeatTimer()
970 mConsensus.parms().ledgerGRANULARITY,
972 m_job_queue.addJob(jtNETOP_TIMER,
"NetOPs.heartbeat", [this]() {
973 processHeartbeatTimer();
976 [
this]() { setHeartbeatTimer(); });
980NetworkOPsImp::setClusterTimer()
982 using namespace std::chrono_literals;
989 processClusterTimer();
992 [
this]() { setClusterTimer(); });
998 JLOG(m_journal.debug()) <<
"Scheduling AccountHistory job for account "
1000 using namespace std::chrono_literals;
1002 accountHistoryTxTimer_,
1004 [
this, subInfo]() { addAccountHistoryJob(subInfo); },
1005 [
this, subInfo]() { setAccountHistoryJobTimer(subInfo); });
1009NetworkOPsImp::processHeartbeatTimer()
1012 "Heartbeat Timer", mConsensus.validating(), m_journal);
1020 std::size_t const numPeers = app_.overlay().size();
1023 if (numPeers < minPeerCount_)
1025 if (mMode != OperatingMode::DISCONNECTED)
1027 setMode(OperatingMode::DISCONNECTED);
1029 ss <<
"Node count (" << numPeers <<
") has fallen "
1030 <<
"below required minimum (" << minPeerCount_ <<
").";
1031 JLOG(m_journal.warn()) << ss.
str();
1032 CLOG(clog.
ss()) <<
"set mode to DISCONNECTED: " << ss.
str();
1037 <<
"already DISCONNECTED. too few peers (" << numPeers
1038 <<
"), need at least " << minPeerCount_;
1045 setHeartbeatTimer();
1050 if (mMode == OperatingMode::DISCONNECTED)
1052 setMode(OperatingMode::CONNECTED);
1053 JLOG(m_journal.info())
1054 <<
"Node count (" << numPeers <<
") is sufficient.";
1055 CLOG(clog.
ss()) <<
"setting mode to CONNECTED based on " << numPeers
1061 auto origMode = mMode.load();
1062 CLOG(clog.
ss()) <<
"mode: " << strOperatingMode(origMode,
true);
1063 if (mMode == OperatingMode::SYNCING)
1064 setMode(OperatingMode::SYNCING);
1065 else if (mMode == OperatingMode::CONNECTED)
1066 setMode(OperatingMode::CONNECTED);
1067 auto newMode = mMode.load();
1068 if (origMode != newMode)
1071 <<
", changing to " << strOperatingMode(newMode,
true);
1073 CLOG(clog.
ss()) <<
". ";
1076 mConsensus.timerEntry(app_.timeKeeper().closeTime(), clog.
ss());
1078 CLOG(clog.
ss()) <<
"consensus phase " << to_string(mLastConsensusPhase);
1080 if (mLastConsensusPhase != currPhase)
1082 reportConsensusStateChange(currPhase);
1083 mLastConsensusPhase = currPhase;
1084 CLOG(clog.
ss()) <<
" changed to " << to_string(mLastConsensusPhase);
1086 CLOG(clog.
ss()) <<
". ";
1088 setHeartbeatTimer();
1092NetworkOPsImp::processClusterTimer()
1094 if (app_.cluster().size() == 0)
1097 using namespace std::chrono_literals;
1099 bool const update = app_.cluster().update(
1100 app_.nodeIdentity().first,
1102 (m_ledgerMaster.getValidatedLedgerAge() <= 4min)
1103 ? app_.getFeeTrack().getLocalFee()
1105 app_.timeKeeper().now());
1109 JLOG(m_journal.debug()) <<
"Too soon to send cluster update";
1114 protocol::TMCluster cluster;
1115 app_.cluster().for_each([&cluster](
ClusterNode const& node) {
1116 protocol::TMClusterNode& n = *cluster.add_clusternodes();
1121 n.set_nodename(node.
name());
1125 for (
auto& item : gossip.
items)
1127 protocol::TMLoadSource& node = *cluster.add_loadsources();
1128 node.set_name(to_string(item.address));
1129 node.set_cost(item.balance);
1131 app_.overlay().foreach(
send_if(
1132 std::make_shared<Message>(cluster, protocol::mtCLUSTER),
1143 if (mode == OperatingMode::FULL && admin)
1145 auto const consensusMode = mConsensus.mode();
1146 if (consensusMode != ConsensusMode::wrongLedger)
1148 if (consensusMode == ConsensusMode::proposing)
1151 if (mConsensus.validating())
1152 return "validating";
1162 if (isNeedNetworkLedger())
1171 auto const txid = trans->getTransactionID();
1172 auto const flags = app_.getHashRouter().getFlags(txid);
1174 if ((flags & SF_BAD) != 0)
1176 JLOG(m_journal.warn()) <<
"Submitted transaction cached bad";
1183 app_.getHashRouter(),
1185 m_ledgerMaster.getValidatedRules(),
1188 if (validity != Validity::Valid)
1190 JLOG(m_journal.warn())
1191 <<
"Submitted transaction invalid: " << reason;
1197 JLOG(m_journal.warn())
1198 <<
"Exception checking transaction " << txid <<
": " << ex.
what();
1205 auto tx = std::make_shared<Transaction>(trans, reason, app_);
1207 m_job_queue.addJob(
jtTRANSACTION,
"submitTxn", [
this, tx]() {
1209 processTransaction(t,
false,
false, FailHard::no);
1214NetworkOPsImp::processTransaction(
1220 auto ev = m_job_queue.makeLoadEvent(
jtTXN_PROC,
"ProcessTXN");
1221 auto const newFlags = app_.getHashRouter().getFlags(transaction->getID());
1223 if ((newFlags & SF_BAD) != 0)
1226 JLOG(m_journal.warn()) << transaction->getID() <<
": cached bad!\n";
1227 transaction->setStatus(
INVALID);
1235 auto const view = m_ledgerMaster.getCurrentLedger();
1237 app_.getHashRouter(),
1238 *transaction->getSTransaction(),
1242 validity == Validity::Valid,
1243 "ripple::NetworkOPsImp::processTransaction : valid validity");
1246 if (validity == Validity::SigBad)
1248 JLOG(m_journal.info()) <<
"Transaction has bad signature: " << reason;
1249 transaction->setStatus(
INVALID);
1251 app_.getHashRouter().setFlags(transaction->getID(), SF_BAD);
1256 app_.getMasterTransaction().canonicalize(&transaction);
1259 doTransactionSync(transaction, bUnlimited, failType);
1261 doTransactionAsync(transaction, bUnlimited, failType);
1265NetworkOPsImp::doTransactionAsync(
1272 if (transaction->getApplying())
1275 mTransactions.push_back(
1277 transaction->setApplying();
1279 if (mDispatchState == DispatchState::none)
1281 if (m_job_queue.addJob(
1282 jtBATCH,
"transactionBatch", [
this]() { transactionBatch(); }))
1284 mDispatchState = DispatchState::scheduled;
1290NetworkOPsImp::doTransactionSync(
1297 if (!transaction->getApplying())
1299 mTransactions.push_back(
1301 transaction->setApplying();
1306 if (mDispatchState == DispatchState::running)
1315 if (mTransactions.size())
1318 if (m_job_queue.addJob(
jtBATCH,
"transactionBatch", [
this]() {
1322 mDispatchState = DispatchState::scheduled;
1326 }
while (transaction->getApplying());
1330NetworkOPsImp::transactionBatch()
1334 if (mDispatchState == DispatchState::running)
1337 while (mTransactions.size())
1348 mTransactions.
swap(transactions);
1350 !transactions.
empty(),
1351 "ripple::NetworkOPsImp::apply : non-empty transactions");
1353 mDispatchState != DispatchState::running,
1354 "ripple::NetworkOPsImp::apply : is not running");
1356 mDispatchState = DispatchState::running;
1362 bool changed =
false;
1365 m_ledgerMaster.peekMutex(), std::defer_lock};
1376 if (e.failType == FailHard::yes)
1379 auto const result = app_.getTxQ().apply(
1380 app_, view, e.transaction->getSTransaction(), flags, j);
1381 e.result = result.ter;
1382 e.applied = result.applied;
1383 changed = changed || result.applied;
1392 if (
auto const l = m_ledgerMaster.getValidatedLedger())
1393 validatedLedgerIndex = l->info().seq;
1395 auto newOL = app_.openLedger().current();
1398 e.transaction->clearSubmitResult();
1402 pubProposedTransaction(
1403 newOL, e.transaction->getSTransaction(), e.result);
1404 e.transaction->setApplied();
1407 e.transaction->setResult(e.result);
1410 app_.getHashRouter().setFlags(e.transaction->getID(), SF_BAD);
1419 JLOG(m_journal.info())
1420 <<
"TransactionResult: " << token <<
": " << human;
1425 bool addLocal = e.local;
1429 JLOG(m_journal.debug())
1430 <<
"Transaction is now included in open ledger";
1431 e.transaction->setStatus(
INCLUDED);
1433 auto const& txCur = e.transaction->getSTransaction();
1434 auto const txNext = m_ledgerMaster.popAcctTransaction(txCur);
1439 auto t = std::make_shared<Transaction>(trans, reason, app_);
1440 submit_held.
emplace_back(t,
false,
false, FailHard::no);
1447 JLOG(m_journal.info()) <<
"Transaction is obsolete";
1448 e.transaction->setStatus(
OBSOLETE);
1452 JLOG(m_journal.debug())
1453 <<
"Transaction is likely to claim a"
1454 <<
" fee, but is queued until fee drops";
1456 e.transaction->setStatus(
HELD);
1460 m_ledgerMaster.addHeldTransaction(e.transaction);
1461 e.transaction->setQueued();
1462 e.transaction->setKept();
1466 if (e.failType != FailHard::yes)
1469 JLOG(m_journal.debug())
1470 <<
"Transaction should be held: " << e.result;
1471 e.transaction->setStatus(
HELD);
1472 m_ledgerMaster.addHeldTransaction(e.transaction);
1473 e.transaction->setKept();
1478 JLOG(m_journal.debug())
1479 <<
"Status other than success " << e.result;
1480 e.transaction->setStatus(
INVALID);
1483 auto const enforceFailHard =
1484 e.failType == FailHard::yes && !
isTesSuccess(e.result);
1486 if (addLocal && !enforceFailHard)
1488 m_localTX->push_back(
1489 m_ledgerMaster.getCurrentLedgerIndex(),
1490 e.transaction->getSTransaction());
1491 e.transaction->setKept();
1495 ((mMode != OperatingMode::FULL) &&
1496 (e.failType != FailHard::yes) && e.local) ||
1501 app_.getHashRouter().shouldRelay(e.transaction->getID());
1505 protocol::TMTransaction tx;
1508 e.transaction->getSTransaction()->add(s);
1509 tx.set_rawtransaction(s.
data(), s.
size());
1510 tx.set_status(protocol::tsCURRENT);
1511 tx.set_receivetimestamp(
1512 app_.timeKeeper().now().time_since_epoch().count());
1515 app_.overlay().relay(e.transaction->getID(), tx, *toSkip);
1516 e.transaction->setBroadcast();
1520 if (validatedLedgerIndex)
1522 auto [fee, accountSeq, availableSeq] =
1523 app_.getTxQ().getTxRequiredFeeAndSeq(
1524 *newOL, e.transaction->getSTransaction());
1525 e.transaction->setCurrentLedgerState(
1526 *validatedLedgerIndex, fee, accountSeq, availableSeq);
1534 e.transaction->clearApplying();
1536 if (!submit_held.
empty())
1538 if (mTransactions.empty())
1539 mTransactions.swap(submit_held);
1541 for (
auto& e : submit_held)
1542 mTransactions.push_back(std::move(e));
1547 mDispatchState = DispatchState::none;
1555NetworkOPsImp::getOwnerInfo(
1560 auto root = keylet::ownerDir(account);
1561 auto sleNode = lpLedger->read(keylet::page(
root));
1568 for (
auto const& uDirEntry : sleNode->getFieldV256(sfIndexes))
1570 auto sleCur = lpLedger->read(keylet::child(uDirEntry));
1573 "ripple::NetworkOPsImp::getOwnerInfo : non-null child SLE");
1575 switch (sleCur->getType())
1578 if (!jvObjects.
isMember(jss::offers))
1579 jvObjects[jss::offers] =
1582 jvObjects[jss::offers].
append(
1583 sleCur->getJson(JsonOptions::none));
1586 case ltRIPPLE_STATE:
1587 if (!jvObjects.
isMember(jss::ripple_lines))
1589 jvObjects[jss::ripple_lines] =
1593 jvObjects[jss::ripple_lines].
append(
1594 sleCur->getJson(JsonOptions::none));
1597 case ltACCOUNT_ROOT:
1601 "ripple::NetworkOPsImp::getOwnerInfo : invalid "
1607 uNodeDir = sleNode->getFieldU64(sfIndexNext);
1611 sleNode = lpLedger->read(keylet::page(
root, uNodeDir));
1614 "ripple::NetworkOPsImp::getOwnerInfo : read next page");
1627NetworkOPsImp::isBlocked()
1629 return isAmendmentBlocked() || isUNLBlocked();
1633NetworkOPsImp::isAmendmentBlocked()
1635 return amendmentBlocked_;
1639NetworkOPsImp::setAmendmentBlocked()
1641 amendmentBlocked_ =
true;
1642 setMode(OperatingMode::CONNECTED);
1646NetworkOPsImp::isAmendmentWarned()
1648 return !amendmentBlocked_ && amendmentWarned_;
1652NetworkOPsImp::setAmendmentWarned()
1654 amendmentWarned_ =
true;
1658NetworkOPsImp::clearAmendmentWarned()
1660 amendmentWarned_ =
false;
1664NetworkOPsImp::isUNLBlocked()
1670NetworkOPsImp::setUNLBlocked()
1673 setMode(OperatingMode::CONNECTED);
1677NetworkOPsImp::clearUNLBlocked()
1679 unlBlocked_ =
false;
1683NetworkOPsImp::checkLastClosedLedger(
1692 JLOG(m_journal.trace()) <<
"NetworkOPsImp::checkLastClosedLedger";
1694 auto const ourClosed = m_ledgerMaster.getClosedLedger();
1699 uint256 closedLedger = ourClosed->info().hash;
1700 uint256 prevClosedLedger = ourClosed->info().parentHash;
1701 JLOG(m_journal.trace()) <<
"OurClosed: " << closedLedger;
1702 JLOG(m_journal.trace()) <<
"PrevClosed: " << prevClosedLedger;
1707 auto& validations = app_.getValidations();
1708 JLOG(m_journal.debug())
1709 <<
"ValidationTrie " <<
Json::Compact(validations.getJsonTrie());
1713 peerCounts[closedLedger] = 0;
1714 if (mMode >= OperatingMode::TRACKING)
1715 peerCounts[closedLedger]++;
1717 for (
auto& peer : peerList)
1719 uint256 peerLedger = peer->getClosedLedgerHash();
1722 ++peerCounts[peerLedger];
1725 for (
auto const& it : peerCounts)
1726 JLOG(m_journal.debug()) <<
"L: " << it.first <<
" n=" << it.second;
1728 uint256 preferredLCL = validations.getPreferredLCL(
1730 m_ledgerMaster.getValidLedgerIndex(),
1733 bool switchLedgers = preferredLCL != closedLedger;
1735 closedLedger = preferredLCL;
1737 if (switchLedgers && (closedLedger == prevClosedLedger))
1740 JLOG(m_journal.info()) <<
"We won't switch to our own previous ledger";
1741 networkClosed = ourClosed->info().hash;
1742 switchLedgers =
false;
1745 networkClosed = closedLedger;
1750 auto consensus = m_ledgerMaster.getLedgerByHash(closedLedger);
1753 consensus = app_.getInboundLedgers().acquire(
1754 closedLedger, 0, InboundLedger::Reason::CONSENSUS);
1757 (!m_ledgerMaster.canBeCurrent(consensus) ||
1758 !m_ledgerMaster.isCompatible(
1759 *consensus, m_journal.debug(),
"Not switching")))
1763 networkClosed = ourClosed->info().hash;
1767 JLOG(m_journal.warn()) <<
"We are not running on the consensus ledger";
1768 JLOG(m_journal.info()) <<
"Our LCL: " << ourClosed->info().hash
1770 JLOG(m_journal.info()) <<
"Net LCL " << closedLedger;
1772 if ((mMode == OperatingMode::TRACKING) || (mMode == OperatingMode::FULL))
1774 setMode(OperatingMode::CONNECTED);
1782 switchLastClosedLedger(consensus);
1789NetworkOPsImp::switchLastClosedLedger(
1793 JLOG(m_journal.error())
1794 <<
"JUMP last closed ledger to " << newLCL->info().hash;
1796 clearNeedNetworkLedger();
1799 app_.getTxQ().processClosedLedger(app_, *newLCL,
true);
1806 auto retries = m_localTX->getTxSet();
1807 auto const lastVal = app_.getLedgerMaster().getValidatedLedger();
1812 rules.
emplace(app_.config().features);
1813 app_.openLedger().accept(
1824 return app_.getTxQ().accept(app_, view);
1828 m_ledgerMaster.switchLCL(newLCL);
1830 protocol::TMStatusChange s;
1831 s.set_newevent(protocol::neSWITCHED_LEDGER);
1832 s.set_ledgerseq(newLCL->info().seq);
1833 s.set_networktime(app_.timeKeeper().now().time_since_epoch().count());
1834 s.set_ledgerhashprevious(
1835 newLCL->info().parentHash.begin(), newLCL->info().parentHash.size());
1836 s.set_ledgerhash(newLCL->info().hash.begin(), newLCL->info().hash.size());
1838 app_.overlay().foreach(
1839 send_always(std::make_shared<Message>(s, protocol::mtSTATUS_CHANGE)));
1843NetworkOPsImp::beginConsensus(
1849 "ripple::NetworkOPsImp::beginConsensus : nonzero input");
1851 auto closingInfo = m_ledgerMaster.getCurrentLedger()->info();
1853 JLOG(m_journal.info()) <<
"Consensus time for #" << closingInfo.seq
1854 <<
" with LCL " << closingInfo.parentHash;
1856 auto prevLedger = m_ledgerMaster.getLedgerByHash(closingInfo.parentHash);
1861 if (mMode == OperatingMode::FULL)
1863 JLOG(m_journal.warn()) <<
"Don't have LCL, going to tracking";
1864 setMode(OperatingMode::TRACKING);
1865 CLOG(clog) <<
"beginConsensus Don't have LCL, going to tracking. ";
1868 CLOG(clog) <<
"beginConsensus no previous ledger. ";
1873 prevLedger->info().hash == closingInfo.parentHash,
1874 "ripple::NetworkOPsImp::beginConsensus : prevLedger hash matches "
1877 closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->info().hash,
1878 "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches "
1881 if (prevLedger->rules().enabled(featureNegativeUNL))
1882 app_.validators().setNegativeUNL(prevLedger->negativeUNL());
1883 TrustChanges const changes = app_.validators().updateTrusted(
1884 app_.getValidations().getCurrentNodeIDs(),
1885 closingInfo.parentCloseTime,
1888 app_.getHashRouter());
1890 if (!changes.
added.empty() || !changes.
removed.empty())
1892 app_.getValidations().trustChanged(changes.
added, changes.
removed);
1894 app_.getAmendmentTable().trustChanged(
1895 app_.validators().getQuorumKeys().second);
1898 mConsensus.startRound(
1899 app_.timeKeeper().closeTime(),
1907 if (mLastConsensusPhase != currPhase)
1909 reportConsensusStateChange(currPhase);
1910 mLastConsensusPhase = currPhase;
1913 JLOG(m_journal.debug()) <<
"Initiating consensus engine";
1920 return mConsensus.peerProposal(app_.timeKeeper().closeTime(), peerPos);
1931 protocol::TMHaveTransactionSet msg;
1932 msg.set_hash(map->getHash().as_uint256().begin(), 256 / 8);
1933 msg.set_status(protocol::tsHAVE);
1934 app_.overlay().foreach(
1935 send_always(std::make_shared<Message>(msg, protocol::mtHAVE_SET)));
1939 mConsensus.gotTxSet(app_.timeKeeper().closeTime(),
RCLTxSet{map});
1945 uint256 deadLedger = m_ledgerMaster.getClosedLedger()->info().parentHash;
1947 for (
auto const& it : app_.overlay().getActivePeers())
1949 if (it && (it->getClosedLedgerHash() == deadLedger))
1951 JLOG(m_journal.trace()) <<
"Killing obsolete peer status";
1958 checkLastClosedLedger(app_.overlay().getActivePeers(), networkClosed);
1960 if (networkClosed.
isZero())
1962 CLOG(clog) <<
"endConsensus last closed ledger is zero. ";
1972 if (((mMode == OperatingMode::CONNECTED) ||
1973 (mMode == OperatingMode::SYNCING)) &&
1979 if (!needNetworkLedger_)
1980 setMode(OperatingMode::TRACKING);
1983 if (((mMode == OperatingMode::CONNECTED) ||
1984 (mMode == OperatingMode::TRACKING)) &&
1990 auto current = m_ledgerMaster.getCurrentLedger();
1991 if (app_.timeKeeper().now() < (
current->info().parentCloseTime +
1992 2 *
current->info().closeTimeResolution))
1994 setMode(OperatingMode::FULL);
1998 beginConsensus(networkClosed, clog);
2002NetworkOPsImp::consensusViewChange()
2004 if ((mMode == OperatingMode::FULL) || (mMode == OperatingMode::TRACKING))
2006 setMode(OperatingMode::CONNECTED);
2016 if (!mStreamMaps[sManifests].empty())
2020 jvObj[jss::type] =
"manifestReceived";
2023 jvObj[jss::signing_key] =
2027 jvObj[jss::signature] =
strHex(*sig);
2030 jvObj[jss::domain] = mo.
domain;
2033 for (
auto i = mStreamMaps[sManifests].begin();
2034 i != mStreamMaps[sManifests].end();)
2036 if (
auto p = i->second.lock())
2038 p->send(jvObj,
true);
2043 i = mStreamMaps[sManifests].erase(i);
2049NetworkOPsImp::ServerFeeSummary::ServerFeeSummary(
2053 : loadFactorServer{loadFeeTrack.getLoadFactor()}
2054 , loadBaseServer{loadFeeTrack.getLoadBase()}
2056 , em{
std::move(escalationMetrics)}
2066 em.has_value() != b.
em.has_value())
2072 em->minProcessingFeeLevel != b.
em->minProcessingFeeLevel ||
2073 em->openLedgerFeeLevel != b.
em->openLedgerFeeLevel ||
2074 em->referenceFeeLevel != b.
em->referenceFeeLevel);
2107 jvObj[jss::type] =
"serverStatus";
2109 jvObj[jss::load_base] = f.loadBaseServer;
2110 jvObj[jss::load_factor_server] = f.loadFactorServer;
2111 jvObj[jss::base_fee] = f.baseFee.jsonClipped();
2116 safe_cast<std::uint64_t>(f.loadFactorServer),
2118 f.em->openLedgerFeeLevel,
2120 f.em->referenceFeeLevel)
2123 jvObj[jss::load_factor] =
trunc32(loadFactor);
2124 jvObj[jss::load_factor_fee_escalation] =
2125 f.em->openLedgerFeeLevel.jsonClipped();
2126 jvObj[jss::load_factor_fee_queue] =
2127 f.em->minProcessingFeeLevel.jsonClipped();
2128 jvObj[jss::load_factor_fee_reference] =
2129 f.em->referenceFeeLevel.jsonClipped();
2132 jvObj[jss::load_factor] = f.loadFactorServer;
2146 p->send(jvObj,
true);
2163 if (!streamMap.empty())
2166 jvObj[jss::type] =
"consensusPhase";
2167 jvObj[jss::consensus] =
to_string(phase);
2169 for (
auto i = streamMap.begin(); i != streamMap.end();)
2171 if (
auto p = i->second.lock())
2173 p->send(jvObj,
true);
2178 i = streamMap.erase(i);
2194 auto const signerPublic = val->getSignerPublic();
2196 jvObj[jss::type] =
"validationReceived";
2197 jvObj[jss::validation_public_key] =
2199 jvObj[jss::ledger_hash] =
to_string(val->getLedgerHash());
2200 jvObj[jss::signature] =
strHex(val->getSignature());
2201 jvObj[jss::full] = val->isFull();
2202 jvObj[jss::flags] = val->getFlags();
2203 jvObj[jss::signing_time] = *(*val)[~sfSigningTime];
2204 jvObj[jss::data] =
strHex(val->getSerializer().slice());
2206 if (
auto version = (*val)[~sfServerVersion])
2209 if (
auto cookie = (*val)[~sfCookie])
2212 if (
auto hash = (*val)[~sfValidatedHash])
2213 jvObj[jss::validated_hash] =
strHex(*hash);
2215 auto const masterKey =
2218 if (masterKey != signerPublic)
2223 if (
auto const seq = (*val)[~sfLedgerSequence])
2224 jvObj[jss::ledger_index] = *seq;
2226 if (val->isFieldPresent(sfAmendments))
2229 for (
auto const& amendment : val->getFieldV256(sfAmendments))
2233 if (
auto const closeTime = (*val)[~sfCloseTime])
2234 jvObj[jss::close_time] = *closeTime;
2236 if (
auto const loadFee = (*val)[~sfLoadFee])
2237 jvObj[jss::load_fee] = *loadFee;
2239 if (
auto const baseFee = val->at(~sfBaseFee))
2240 jvObj[jss::base_fee] =
static_cast<double>(*baseFee);
2242 if (
auto const reserveBase = val->at(~sfReserveBase))
2243 jvObj[jss::reserve_base] = *reserveBase;
2245 if (
auto const reserveInc = val->at(~sfReserveIncrement))
2246 jvObj[jss::reserve_inc] = *reserveInc;
2250 if (
auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops);
2251 baseFeeXRP && baseFeeXRP->native())
2252 jvObj[jss::base_fee] = baseFeeXRP->xrp().jsonClipped();
2254 if (
auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops);
2255 reserveBaseXRP && reserveBaseXRP->native())
2256 jvObj[jss::reserve_base] = reserveBaseXRP->xrp().jsonClipped();
2258 if (
auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops);
2259 reserveIncXRP && reserveIncXRP->native())
2260 jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped();
2269 if (jvTx.
isMember(jss::ledger_index))
2271 jvTx[jss::ledger_index] =
2272 std::to_string(jvTx[jss::ledger_index].asUInt());
2279 if (
auto p = i->second.lock())
2283 [&](
Json::Value const& jv) { p->send(jv, true); });
2303 jvObj[jss::type] =
"peerStatusChange";
2312 p->send(jvObj,
true);
2326 using namespace std::chrono_literals;
2358 <<
"recvValidation " << val->getLedgerHash() <<
" from " << source;
2374 <<
"Exception thrown for handling new validation "
2375 << val->getLedgerHash() <<
": " << e.
what();
2380 <<
"Unknown exception thrown for handling new validation "
2381 << val->getLedgerHash();
2393 ss <<
"VALIDATION: " << val->render() <<
" master_key: ";
2430 "This server is amendment blocked, and must be updated to be "
2431 "able to stay in sync with the network.";
2438 "This server has an expired validator list. validators.txt "
2439 "may be incorrectly configured or some [validator_list_sites] "
2440 "may be unreachable.";
2447 "One or more unsupported amendments have reached majority. "
2448 "Upgrade to the latest version before they are activated "
2449 "to avoid being amendment blocked.";
2450 if (
auto const expected =
2454 d[jss::expected_date] = expected->time_since_epoch().count();
2455 d[jss::expected_date_UTC] =
to_string(*expected);
2459 if (warnings.size())
2460 info[jss::warnings] = std::move(warnings);
2475 info[jss::time] =
to_string(std::chrono::floor<std::chrono::microseconds>(
2479 info[jss::network_ledger] =
"waiting";
2481 info[jss::validation_quorum] =
2489 info[jss::node_size] =
"tiny";
2492 info[jss::node_size] =
"small";
2495 info[jss::node_size] =
"medium";
2498 info[jss::node_size] =
"large";
2501 info[jss::node_size] =
"huge";
2510 info[jss::validator_list_expires] =
2511 safe_cast<Json::UInt>(when->time_since_epoch().count());
2513 info[jss::validator_list_expires] = 0;
2523 if (*when == TimeKeeper::time_point::max())
2525 x[jss::expiration] =
"never";
2526 x[jss::status] =
"active";
2533 x[jss::status] =
"active";
2535 x[jss::status] =
"expired";
2540 x[jss::status] =
"unknown";
2541 x[jss::expiration] =
"unknown";
2545#if defined(GIT_COMMIT_HASH) || defined(GIT_BRANCH)
2548#ifdef GIT_COMMIT_HASH
2549 x[jss::hash] = GIT_COMMIT_HASH;
2552 x[jss::branch] = GIT_BRANCH;
2557 info[jss::io_latency_ms] =
2565 info[jss::pubkey_validator] =
2570 info[jss::pubkey_validator] =
"none";
2580 info[jss::counters][jss::nodestore] = nodestore;
2584 info[jss::pubkey_node] =
2590 info[jss::amendment_blocked] =
true;
2604 lastClose[jss::converge_time_s] =
2609 lastClose[jss::converge_time] =
2613 info[jss::last_close] = lastClose;
2621 info[jss::network_id] =
static_cast<Json::UInt>(*netid);
2623 auto const escalationMetrics =
2631 auto const loadFactorFeeEscalation =
2633 escalationMetrics.openLedgerFeeLevel,
2635 escalationMetrics.referenceFeeLevel)
2639 safe_cast<std::uint64_t>(loadFactorServer), loadFactorFeeEscalation);
2643 info[jss::load_base] = loadBaseServer;
2644 info[jss::load_factor] =
trunc32(loadFactor);
2645 info[jss::load_factor_server] = loadFactorServer;
2652 info[jss::load_factor_fee_escalation] =
2653 escalationMetrics.openLedgerFeeLevel.jsonClipped();
2654 info[jss::load_factor_fee_queue] =
2655 escalationMetrics.minProcessingFeeLevel.jsonClipped();
2656 info[jss::load_factor_fee_reference] =
2657 escalationMetrics.referenceFeeLevel.jsonClipped();
2661 info[jss::load_factor] =
2662 static_cast<double>(loadFactor) / loadBaseServer;
2664 if (loadFactorServer != loadFactor)
2665 info[jss::load_factor_server] =
2666 static_cast<double>(loadFactorServer) / loadBaseServer;
2671 if (fee != loadBaseServer)
2672 info[jss::load_factor_local] =
2673 static_cast<double>(fee) / loadBaseServer;
2675 if (fee != loadBaseServer)
2676 info[jss::load_factor_net] =
2677 static_cast<double>(fee) / loadBaseServer;
2679 if (fee != loadBaseServer)
2680 info[jss::load_factor_cluster] =
2681 static_cast<double>(fee) / loadBaseServer;
2683 if (escalationMetrics.openLedgerFeeLevel !=
2684 escalationMetrics.referenceFeeLevel &&
2685 (admin || loadFactorFeeEscalation != loadFactor))
2686 info[jss::load_factor_fee_escalation] =
2687 escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2688 escalationMetrics.referenceFeeLevel);
2689 if (escalationMetrics.minProcessingFeeLevel !=
2690 escalationMetrics.referenceFeeLevel)
2691 info[jss::load_factor_fee_queue] =
2692 escalationMetrics.minProcessingFeeLevel.decimalFromReference(
2693 escalationMetrics.referenceFeeLevel);
2706 XRPAmount const baseFee = lpClosed->fees().base;
2708 l[jss::seq] =
Json::UInt(lpClosed->info().seq);
2709 l[jss::hash] =
to_string(lpClosed->info().hash);
2714 l[jss::reserve_base] =
2715 lpClosed->fees().accountReserve(0).jsonClipped();
2716 l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2718 lpClosed->info().closeTime.time_since_epoch().count());
2723 l[jss::reserve_base_xrp] =
2724 lpClosed->fees().accountReserve(0).decimalXRP();
2725 l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2728 std::abs(closeOffset.count()) >= 60)
2729 l[jss::close_time_offset] =
2737 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2741 auto lCloseTime = lpClosed->info().closeTime;
2743 if (lCloseTime <= closeTime)
2745 using namespace std::chrono_literals;
2746 auto age = closeTime - lCloseTime;
2748 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2754 info[jss::validated_ledger] = l;
2756 info[jss::closed_ledger] = l;
2760 info[jss::published_ledger] =
"none";
2761 else if (lpPublished->info().seq != lpClosed->info().seq)
2762 info[jss::published_ledger] = lpPublished->info().seq;
2767 info[jss::jq_trans_overflow] =
2769 info[jss::peer_disconnects] =
2771 info[jss::peer_disconnects_resources] =
2776 "http",
"https",
"peer",
"ws",
"ws2",
"wss",
"wss2"};
2784 !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() &&
2785 port.admin_user.empty() && port.admin_password.empty()))
2799 for (
auto const& p : proto)
2800 jv[jss::protocol].append(p);
2807 auto const optPort = grpcSection.
get(
"port");
2808 if (optPort && grpcSection.get(
"ip"))
2811 jv[jss::port] = *optPort;
2813 jv[jss::protocol].append(
"grpc");
2816 info[jss::ports] = std::move(ports);
2841 transJson(transaction, result,
false, ledger, std::nullopt);
2855 [&](
Json::Value const& jv) { p->send(jv, true); });
2878 alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted,
app_);
2880 lpAccepted->info().hash, alpAccepted);
2884 alpAccepted->getLedger().
get() == lpAccepted.
get(),
2885 "ripple::NetworkOPsImp::pubLedger : accepted input");
2889 <<
"Publishing ledger " << lpAccepted->info().seq <<
" "
2890 << lpAccepted->info().hash;
2898 jvObj[jss::type] =
"ledgerClosed";
2899 jvObj[jss::ledger_index] = lpAccepted->info().seq;
2900 jvObj[jss::ledger_hash] =
to_string(lpAccepted->info().hash);
2902 lpAccepted->info().closeTime.time_since_epoch().count());
2904 if (!lpAccepted->rules().enabled(featureXRPFees))
2906 jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2907 jvObj[jss::reserve_base] =
2908 lpAccepted->fees().accountReserve(0).jsonClipped();
2909 jvObj[jss::reserve_inc] =
2910 lpAccepted->fees().increment.jsonClipped();
2912 jvObj[jss::txn_count] =
Json::UInt(alpAccepted->size());
2916 jvObj[jss::validated_ledgers] =
2926 p->send(jvObj,
true);
2944 p->send(jvObj,
true);
2953 static bool firstTime =
true;
2960 for (
auto& inner : outer.second)
2962 auto& subInfo = inner.second;
2963 if (subInfo.index_->separationLedgerSeq_ == 0)
2966 alpAccepted->getLedger(), subInfo);
2975 for (
auto const& accTx : *alpAccepted)
2979 lpAccepted, *accTx, accTx == *(--alpAccepted->end()));
3006 "reportConsensusStateChange->pubConsensus",
3037 jvObj[jss::type] =
"transaction";
3041 jvObj[jss::transaction] =
3048 jvObj[jss::meta], *ledger, transaction, meta->
get());
3050 jvObj[jss::meta], transaction, meta->
get());
3053 if (!ledger->open())
3054 jvObj[jss::ledger_hash] =
to_string(ledger->info().hash);
3058 jvObj[jss::ledger_index] = ledger->info().seq;
3059 jvObj[jss::transaction][jss::date] =
3060 ledger->info().closeTime.time_since_epoch().count();
3061 jvObj[jss::validated] =
true;
3062 jvObj[jss::close_time_iso] =
to_string_iso(ledger->info().closeTime);
3068 jvObj[jss::validated] =
false;
3069 jvObj[jss::ledger_current_index] = ledger->info().seq;
3072 jvObj[jss::status] = validated ?
"closed" :
"proposed";
3073 jvObj[jss::engine_result] = sToken;
3074 jvObj[jss::engine_result_code] = result;
3075 jvObj[jss::engine_result_message] = sHuman;
3077 if (transaction->getTxnType() == ttOFFER_CREATE)
3079 auto const account = transaction->getAccountID(sfAccount);
3080 auto const amount = transaction->getFieldAmount(sfTakerGets);
3083 if (account != amount.issue().account)
3091 jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3099 [&]<
unsigned Version>(
3101 RPC::insertDeliverMax(
3102 jvTx[jss::transaction], transaction->getTxnType(), Version);
3104 if constexpr (Version > 1)
3106 jvTx[jss::tx_json] = jvTx.removeMember(jss::transaction);
3107 jvTx[jss::hash] = hash;
3111 jvTx[jss::transaction][jss::hash] = hash;
3124 auto const& stTxn = transaction.
getTxn();
3128 auto const trResult = transaction.
getResult();
3143 [&](
Json::Value const& jv) { p->send(jv, true); });
3160 [&](
Json::Value const& jv) { p->send(jv, true); });
3185 auto const currLedgerSeq = ledger->seq();
3192 for (
auto const& affectedAccount : transaction.
getAffected())
3197 auto it = simiIt->second.begin();
3199 while (it != simiIt->second.end())
3210 it = simiIt->second.erase(it);
3217 auto it = simiIt->second.begin();
3218 while (it != simiIt->second.end())
3229 it = simiIt->second.erase(it);
3236 auto& subs = histoIt->second;
3237 auto it = subs.begin();
3238 while (it != subs.end())
3241 if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3255 it = subs.erase(it);
3266 <<
"pubAccountTransaction: " <<
"proposed=" << iProposed
3267 <<
", accepted=" << iAccepted;
3269 if (!notify.
empty() || !accountHistoryNotify.
empty())
3271 auto const& stTxn = transaction.
getTxn();
3275 auto const trResult = transaction.
getResult();
3281 isrListener->getApiVersion(),
3282 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3286 jvObj.
set(jss::account_history_boundary,
true);
3289 jvObj.
isMember(jss::account_history_tx_stream) ==
3291 "ripple::NetworkOPsImp::pubAccountTransaction : "
3292 "account_history_tx_stream not set");
3293 for (
auto& info : accountHistoryNotify)
3295 auto& index = info.index_;
3296 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3297 jvObj.
set(jss::account_history_tx_first,
true);
3299 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3302 info.sink_->getApiVersion(),
3303 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3328 for (
auto const& affectedAccount : tx->getMentionedAccounts())
3333 auto it = simiIt->second.begin();
3335 while (it != simiIt->second.end())
3346 it = simiIt->second.erase(it);
3353 JLOG(
m_journal.
trace()) <<
"pubProposedAccountTransaction: " << iProposed;
3355 if (!notify.
empty() || !accountHistoryNotify.
empty())
3362 isrListener->getApiVersion(),
3363 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3366 jvObj.
isMember(jss::account_history_tx_stream) ==
3368 "ripple::NetworkOPs::pubProposedAccountTransaction : "
3369 "account_history_tx_stream not set");
3370 for (
auto& info : accountHistoryNotify)
3372 auto& index = info.index_;
3373 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3374 jvObj.
set(jss::account_history_tx_first,
true);
3375 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3377 info.sink_->getApiVersion(),
3378 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3395 for (
auto const& naAccountID : vnaAccountIDs)
3398 <<
"subAccount: account: " <<
toBase58(naAccountID);
3400 isrListener->insertSubAccountInfo(naAccountID, rt);
3405 for (
auto const& naAccountID : vnaAccountIDs)
3407 auto simIterator = subMap.
find(naAccountID);
3408 if (simIterator == subMap.
end())
3412 usisElement[isrListener->getSeq()] = isrListener;
3414 subMap.
insert(simIterator, make_pair(naAccountID, usisElement));
3419 simIterator->second[isrListener->getSeq()] = isrListener;
3430 for (
auto const& naAccountID : vnaAccountIDs)
3433 isrListener->deleteSubAccountInfo(naAccountID, rt);
3450 for (
auto const& naAccountID : vnaAccountIDs)
3452 auto simIterator = subMap.
find(naAccountID);
3454 if (simIterator != subMap.
end())
3457 simIterator->second.erase(uSeq);
3459 if (simIterator->second.empty())
3462 subMap.
erase(simIterator);
3471 enum DatabaseType { Sqlite,
None };
3472 static const auto databaseType = [&]() -> DatabaseType {
3477 return DatabaseType::Sqlite;
3479 return DatabaseType::None;
3482 if (databaseType == DatabaseType::None)
3485 <<
"AccountHistory job for account "
3497 "AccountHistoryTxStream",
3498 [
this, dbType = databaseType, subInfo]() {
3499 auto const& accountId = subInfo.
index_->accountId_;
3500 auto& lastLedgerSeq = subInfo.
index_->historyLastLedgerSeq_;
3501 auto& txHistoryIndex = subInfo.
index_->historyTxIndex_;
3504 <<
"AccountHistory job for account " <<
toBase58(accountId)
3505 <<
" started. lastLedgerSeq=" << lastLedgerSeq;
3515 auto stx = tx->getSTransaction();
3516 if (stx->getAccountID(sfAccount) == accountId &&
3517 stx->getSeqProxy().value() == 1)
3521 for (
auto& node : meta->getNodes())
3523 if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3526 if (node.isFieldPresent(sfNewFields))
3528 if (
auto inner =
dynamic_cast<const STObject*
>(
3529 node.peekAtPField(sfNewFields));
3532 if (inner->isFieldPresent(sfAccount) &&
3533 inner->getAccountID(sfAccount) == accountId)
3545 bool unsubscribe) ->
bool {
3548 sptr->send(jvObj,
true);
3558 bool unsubscribe) ->
bool {
3562 sptr->getApiVersion(),
3563 [&](
Json::Value const& jv) { sptr->send(jv,
true); });
3586 accountId, minLedger, maxLedger, marker, 0,
true};
3587 return db->newestAccountTxPage(options);
3591 "ripple::NetworkOPsImp::addAccountHistoryJob::"
3592 "getMoreTxns : invalid database type");
3601 while (lastLedgerSeq >= 2 && !subInfo.
index_->stopHistorical_)
3603 int feeChargeCount = 0;
3612 <<
"AccountHistory job for account "
3613 <<
toBase58(accountId) <<
" no InfoSub. Fee charged "
3614 << feeChargeCount <<
" times.";
3619 auto startLedgerSeq =
3620 (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3622 <<
"AccountHistory job for account " <<
toBase58(accountId)
3623 <<
", working on ledger range [" << startLedgerSeq <<
","
3624 << lastLedgerSeq <<
"]";
3626 auto haveRange = [&]() ->
bool {
3629 auto haveSomeValidatedLedgers =
3631 validatedMin, validatedMax);
3633 return haveSomeValidatedLedgers &&
3634 validatedMin <= startLedgerSeq &&
3635 lastLedgerSeq <= validatedMax;
3641 <<
"AccountHistory reschedule job for account "
3642 <<
toBase58(accountId) <<
", incomplete ledger range ["
3643 << startLedgerSeq <<
"," << lastLedgerSeq <<
"]";
3649 while (!subInfo.
index_->stopHistorical_)
3652 getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3656 <<
"AccountHistory job for account "
3657 <<
toBase58(accountId) <<
" getMoreTxns failed.";
3662 auto const& txns = dbResult->first;
3663 marker = dbResult->second;
3664 size_t num_txns = txns.size();
3665 for (
size_t i = 0; i < num_txns; ++i)
3667 auto const& [tx, meta] = txns[i];
3672 <<
"AccountHistory job for account "
3673 <<
toBase58(accountId) <<
" empty tx or meta.";
3683 <<
"AccountHistory job for account "
3684 <<
toBase58(accountId) <<
" no ledger.";
3689 tx->getSTransaction();
3693 <<
"AccountHistory job for account "
3695 <<
" getSTransaction failed.";
3701 auto const trR = meta->getResultTER();
3703 transJson(stTxn, trR,
true, curTxLedger, mRef);
3706 jss::account_history_tx_index, txHistoryIndex--);
3707 if (i + 1 == num_txns ||
3708 txns[i + 1].first->getLedger() != tx->getLedger())
3709 jvTx.
set(jss::account_history_boundary,
true);
3711 if (isFirstTx(tx, meta))
3713 jvTx.
set(jss::account_history_tx_first,
true);
3714 sendMultiApiJson(jvTx,
false);
3717 <<
"AccountHistory job for account "
3719 <<
" done, found last tx.";
3724 sendMultiApiJson(jvTx,
false);
3731 <<
"AccountHistory job for account "
3733 <<
" paging, marker=" << marker->ledgerSeq <<
":"
3742 if (!subInfo.
index_->stopHistorical_)
3744 lastLedgerSeq = startLedgerSeq - 1;
3745 if (lastLedgerSeq <= 1)
3748 <<
"AccountHistory job for account "
3750 <<
" done, reached genesis ledger.";
3763 subInfo.
index_->separationLedgerSeq_ = ledger->seq();
3764 auto const& accountId = subInfo.
index_->accountId_;
3766 if (!ledger->exists(accountKeylet))
3769 <<
"subAccountHistoryStart, no account " <<
toBase58(accountId)
3770 <<
", no need to add AccountHistory job.";
3775 if (
auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3777 if (sleAcct->getFieldU32(sfSequence) == 1)
3780 <<
"subAccountHistoryStart, genesis account "
3782 <<
" does not have tx, no need to add AccountHistory job.";
3789 "ripple::NetworkOPsImp::subAccountHistoryStart : failed to "
3790 "access genesis account");
3794 subInfo.
index_->historyLastLedgerSeq_ = ledger->seq();
3795 subInfo.
index_->haveHistorical_ =
true;
3798 <<
"subAccountHistoryStart, add AccountHistory job: accountId="
3799 <<
toBase58(accountId) <<
", currentLedgerSeq=" << ledger->seq();
3809 if (!isrListener->insertSubAccountHistory(accountId))
3812 <<
"subAccountHistory, already subscribed to account "
3819 isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3824 inner.
emplace(isrListener->getSeq(), ahi);
3830 simIterator->second.emplace(isrListener->getSeq(), ahi);
3844 <<
"subAccountHistory, no validated ledger yet, delay start";
3857 isrListener->deleteSubAccountHistory(account);
3871 auto& subInfoMap = simIterator->second;
3872 auto subInfoIter = subInfoMap.find(seq);
3873 if (subInfoIter != subInfoMap.end())
3875 subInfoIter->second.index_->stopHistorical_ =
true;
3880 simIterator->second.erase(seq);
3881 if (simIterator->second.empty())
3887 <<
"unsubAccountHistory, account " <<
toBase58(account)
3888 <<
", historyOnly = " << (historyOnly ?
"true" :
"false");
3896 listeners->addSubscriber(isrListener);
3898 UNREACHABLE(
"ripple::NetworkOPsImp::subBook : null book listeners");
3906 listeners->removeSubscriber(uSeq);
3918 m_standalone,
"ripple::NetworkOPsImp::acceptLedger : is standalone");
3921 Throw<std::runtime_error>(
3922 "Operation only possible in STANDALONE mode.");
3937 jvResult[jss::ledger_index] = lpClosed->info().seq;
3938 jvResult[jss::ledger_hash] =
to_string(lpClosed->info().hash);
3940 lpClosed->info().closeTime.time_since_epoch().count());
3941 if (!lpClosed->rules().enabled(featureXRPFees))
3943 jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
3944 jvResult[jss::reserve_base] =
3945 lpClosed->fees().accountReserve(0).jsonClipped();
3946 jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
3951 jvResult[jss::validated_ledgers] =
3957 .emplace(isrListener->getSeq(), isrListener)
3967 .emplace(isrListener->getSeq(), isrListener)
3993 .emplace(isrListener->getSeq(), isrListener)
4021 jvResult[jss::random] =
to_string(uRandom);
4023 jvResult[jss::load_base] = feeTrack.getLoadBase();
4024 jvResult[jss::load_factor] = feeTrack.getLoadFactor();
4025 jvResult[jss::hostid] =
getHostId(admin);
4026 jvResult[jss::pubkey_node] =
4031 .emplace(isrListener->getSeq(), isrListener)
4049 .emplace(isrListener->getSeq(), isrListener)
4067 .emplace(isrListener->getSeq(), isrListener)
4085 .emplace(isrListener->getSeq(), isrListener)
4109 .emplace(isrListener->getSeq(), isrListener)
4127 .emplace(isrListener->getSeq(), isrListener)
4175 if (map.find(pInfo->getSeq()) != map.end())
4182#ifndef USE_NEW_BOOK_PAGE
4193 unsigned int iLimit,
4203 uint256 uTipIndex = uBookBase;
4207 stream <<
"getBookPage:" << book;
4208 stream <<
"getBookPage: uBookBase=" << uBookBase;
4209 stream <<
"getBookPage: uBookEnd=" << uBookEnd;
4210 stream <<
"getBookPage: uTipIndex=" << uTipIndex;
4219 bool bDirectAdvance =
true;
4223 unsigned int uBookEntry;
4229 while (!bDone && iLimit-- > 0)
4233 bDirectAdvance =
false;
4237 auto const ledgerIndex = view.
succ(uTipIndex, uBookEnd);
4241 sleOfferDir.
reset();
4250 uTipIndex = sleOfferDir->key();
4253 cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4256 <<
"getBookPage: uTipIndex=" << uTipIndex;
4258 <<
"getBookPage: offerIndex=" << offerIndex;
4268 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4269 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4270 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4272 bool firstOwnerOffer(
true);
4278 saOwnerFunds = saTakerGets;
4280 else if (bGlobalFreeze)
4288 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4289 if (umBalanceEntry != umBalance.
end())
4293 saOwnerFunds = umBalanceEntry->second;
4294 firstOwnerOffer =
false;
4308 if (saOwnerFunds < beast::zero)
4312 saOwnerFunds.
clear();
4320 STAmount saOwnerFundsLimit = saOwnerFunds;
4332 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4335 if (saOwnerFundsLimit >= saTakerGets)
4338 saTakerGetsFunded = saTakerGets;
4344 saTakerGetsFunded = saOwnerFundsLimit;
4346 saTakerGetsFunded.
setJson(jvOffer[jss::taker_gets_funded]);
4350 saTakerGetsFunded, saDirRate, saTakerPays.
issue()))
4351 .setJson(jvOffer[jss::taker_pays_funded]);
4357 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4359 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4363 jvOf[jss::quality] = saDirRate.
getText();
4365 if (firstOwnerOffer)
4366 jvOf[jss::owner_funds] = saOwnerFunds.
getText();
4373 if (!
cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4375 bDirectAdvance =
true;
4380 <<
"getBookPage: offerIndex=" << offerIndex;
4400 unsigned int iLimit,
4408 MetaView lesActive(lpLedger,
tapNONE,
true);
4409 OrderBookIterator obIterator(lesActive, book);
4413 const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.
out.
account) ||
4414 lesActive.isGlobalFrozen(book.
in.
account);
4416 while (iLimit-- > 0 && obIterator.nextOffer())
4421 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4422 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4423 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4424 STAmount saDirRate = obIterator.getCurrentRate();
4430 saOwnerFunds = saTakerGets;
4432 else if (bGlobalFreeze)
4440 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4442 if (umBalanceEntry != umBalance.
end())
4446 saOwnerFunds = umBalanceEntry->second;
4452 saOwnerFunds = lesActive.accountHolds(
4458 if (saOwnerFunds.isNegative())
4462 saOwnerFunds.zero();
4469 STAmount saTakerGetsFunded;
4470 STAmount saOwnerFundsLimit = saOwnerFunds;
4482 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4485 if (saOwnerFundsLimit >= saTakerGets)
4488 saTakerGetsFunded = saTakerGets;
4493 saTakerGetsFunded = saOwnerFundsLimit;
4495 saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4501 multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4502 .setJson(jvOffer[jss::taker_pays_funded]);
4505 STAmount saOwnerPays = (
parityRate == offerRate)
4508 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4510 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4512 if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4516 jvOf[jss::quality] = saDirRate.
getText();
4531 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4571 ++counters_[
static_cast<std::size_t>(om)].transitions;
4573 counters_[
static_cast<std::size_t>(om)].transitions == 1)
4575 initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4576 now - processStart_)
4580 std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4589 auto [counters, mode, start, initialSync] = getCounterData();
4590 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4600 auto& state = obj[jss::state_accounting][
states_[i]];
4601 state[jss::transitions] =
std::to_string(counters[i].transitions);
4602 state[jss::duration_us] =
std::to_string(counters[i].dur.count());
4606 obj[jss::initial_sync_duration_us] =
std::to_string(initialSync);
4621 boost::asio::io_service& io_svc,
4625 return std::make_unique<NetworkOPsImp>(
T back_inserter(T... args)
Decorator for streaming out compact json.
Lightweight wrapper to tag static string.
Value get(UInt index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
Value & append(const Value &value)
Append value to array at the end.
bool isMember(const char *key) const
Return true if the object has a member named key.
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
A metric for measuring an integral value.
void set(value_type value) const
Set the value on the gauge.
A reference to a handler for performing polled collection.
A transaction that is in a closed ledger.
boost::container::flat_set< AccountID > const & getAffected() const
std::shared_ptr< STTx const > const & getTxn() const
TxMeta const & getMeta() const
virtual std::optional< NetClock::time_point > firstUnsupportedExpected() const =0
virtual Config & config()=0
virtual Overlay & overlay()=0
virtual LoadFeeTrack & getFeeTrack()=0
virtual OpenLedger & openLedger()=0
virtual beast::Journal journal(std::string const &name)=0
virtual NodeStore::Database & getNodeStore()=0
virtual ServerHandler & getServerHandler()=0
virtual std::chrono::milliseconds getIOLatency()=0
virtual OrderBookDB & getOrderBookDB()=0
virtual TimeKeeper & timeKeeper()=0
virtual TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache()=0
virtual JobQueue & getJobQueue()=0
virtual InboundLedgers & getInboundLedgers()=0
virtual ValidatorList & validators()=0
virtual std::optional< PublicKey const > getValidationPublicKey() const =0
virtual LedgerMaster & getLedgerMaster()=0
virtual RelationalDatabase & getRelationalDatabase()=0
virtual ManifestCache & validatorManifests()=0
virtual perf::PerfLog & getPerfLog()=0
virtual Cluster & cluster()=0
virtual AmendmentTable & getAmendmentTable()=0
virtual std::pair< PublicKey, SecretKey > const & nodeIdentity()=0
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
Section & section(std::string const &name)
Returns the section with the given name.
Holds transactions which were deferred to the next pass of consensus.
The role of a ClosureCounter is to assist in shutdown by letting callers wait for the completion of c...
std::string const & name() const
std::uint32_t getLoadFee() const
NetClock::time_point getReportTime() const
PublicKey const & identity() const
std::size_t size() const
The number of nodes in the cluster list.
std::string SERVER_DOMAIN
static constexpr std::uint32_t FEE_UNITS_DEPRECATED
int RELAY_UNTRUSTED_VALIDATIONS
virtual void clearFailures()=0
virtual Json::Value getInfo()=0
std::shared_ptr< InfoSub > pointer
A pool of threads to perform work.
Json::Value getJson(int c=0)
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
std::shared_ptr< Ledger const > getValidatedLedger()
bool haveValidated()
Whether we have ever fully validated a ledger.
std::shared_ptr< ReadView const > getCurrentLedger()
bool getValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
std::shared_ptr< Ledger const > getClosedLedger()
std::string getCompleteLedgers()
std::size_t getFetchPackCacheSize() const
std::shared_ptr< ReadView const > getPublishedLedger()
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
std::chrono::seconds getValidatedLedgerAge()
Manages the current fee schedule.
std::uint32_t getClusterFee() const
std::uint32_t getLocalFee() const
std::uint32_t getLoadBase() const
std::uint32_t getRemoteFee() const
std::uint32_t getLoadFactor() const
void heartbeat()
Reset the stall detection timer.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
State accounting records two attributes for each possible server state: 1) Amount of time spent in ea...
void mode(OperatingMode om)
Record state transition.
void json(Json::Value &obj) const
Output state counters in JSON format.
std::array< Counters, 5 > counters_
std::uint64_t initialSyncUs_
CounterData getCounterData() const
std::chrono::steady_clock::time_point start_
static std::array< Json::StaticString const, 5 > const states_
std::chrono::steady_clock::time_point const processStart_
Transaction with input flags and results to be applied in batches.
TransactionStatus(std::shared_ptr< Transaction > t, bool a, bool l, FailHard f)
std::shared_ptr< Transaction > const transaction
void processClusterTimer()
boost::asio::steady_timer accountHistoryTxTimer_
void pubProposedTransaction(std::shared_ptr< ReadView const > const &ledger, std::shared_ptr< STTx const > const &transaction, TER result) override
OperatingMode getOperatingMode() const override
std::string strOperatingMode(OperatingMode const mode, bool const admin) const override
std::vector< TransactionStatus > mTransactions
bool unsubBookChanges(std::uint64_t uListener) override
std::atomic< OperatingMode > mMode
Json::Value getLedgerFetchInfo() override
bool isUNLBlocked() override
void unsubAccount(InfoSub::ref ispListener, hash_set< AccountID > const &vnaAccountIDs, bool rt) override
Json::Value getOwnerInfo(std::shared_ptr< ReadView const > lpLedger, AccountID const &account) override
void setNeedNetworkLedger() override
void setUNLBlocked() override
void pubConsensus(ConsensusPhase phase)
void transactionBatch()
Apply transactions in batches.
void apply(std::unique_lock< std::mutex > &batchLock)
Attempt to apply transactions and post-process based on the results.
void setAmendmentBlocked() override
void processTransaction(std::shared_ptr< Transaction > &transaction, bool bUnlimited, bool bLocal, FailHard failType) override
Process transactions as they arrive from the network or which are submitted by clients.
void clearUNLBlocked() override
boost::asio::steady_timer heartbeatTimer_
void updateLocalTx(ReadView const &view) override
bool unsubManifests(std::uint64_t uListener) override
DispatchState
Synchronization states for transaction batches.
bool unsubTransactions(std::uint64_t uListener) override
void clearAmendmentWarned() override
std::size_t getLocalTxCount() override
std::unique_ptr< LocalTxs > m_localTX
bool subValidations(InfoSub::ref ispListener) override
bool subLedger(InfoSub::ref ispListener, Json::Value &jvResult) override
~NetworkOPsImp() override
bool isAmendmentBlocked() override
void unsubAccountHistoryInternal(std::uint64_t seq, AccountID const &account, bool historyOnly) override
SubAccountHistoryMapType mSubAccountHistory
void getBookPage(std::shared_ptr< ReadView const > &lpLedger, Book const &, AccountID const &uTakerID, const bool bProof, unsigned int iLimit, Json::Value const &jvMarker, Json::Value &jvResult) override
Json::Value getServerInfo(bool human, bool admin, bool counters) override
InfoSub::pointer addRpcSub(std::string const &strUrl, InfoSub::ref) override
boost::asio::steady_timer clusterTimer_
bool isAmendmentWarned() override
static std::array< char const *, 5 > const states_
bool subServer(InfoSub::ref ispListener, Json::Value &jvResult, bool admin) override
NetworkOPsImp(Application &app, NetworkOPs::clock_type &clock, bool standalone, std::size_t minPeerCount, bool start_valid, JobQueue &job_queue, LedgerMaster &ledgerMaster, ValidatorKeys const &validatorKeys, boost::asio::io_service &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
void unsubAccountInternal(std::uint64_t seq, hash_set< AccountID > const &vnaAccountIDs, bool rt) override
std::atomic< bool > amendmentBlocked_
SubInfoMapType mSubAccount
void unsubAccountHistory(InfoSub::ref ispListener, AccountID const &account, bool historyOnly) override
unsubscribe an account's transactions
std::set< uint256 > pendingValidations_
bool beginConsensus(uint256 const &networkClosed, std::unique_ptr< std::stringstream > const &clog) override
void doTransactionAsync(std::shared_ptr< Transaction > transaction, bool bUnlimited, FailHard failtype)
For transactions not submitted by a locally connected client, fire and forget.
void setAccountHistoryJobTimer(SubAccountHistoryInfoWeak subInfo)
bool unsubValidations(std::uint64_t uListener) override
void endConsensus(std::unique_ptr< std::stringstream > const &clog) override
ClosureCounter< void, boost::system::error_code const & > waitHandlerCounter_
void pubLedger(std::shared_ptr< ReadView const > const &lpAccepted) override
void addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
void doTransactionSync(std::shared_ptr< Transaction > transaction, bool bUnlimited, FailHard failType)
For transactions submitted directly by a client, apply batch of transactions and wait for this transa...
void setTimer(boost::asio::steady_timer &timer, std::chrono::milliseconds const &expiry_time, std::function< void()> onExpire, std::function< void()> onError)
std::array< SubMapType, SubTypes::sLastEntry > mStreamMaps
bool unsubPeerStatus(std::uint64_t uListener) override
void pubValidation(std::shared_ptr< STValidation > const &val) override
std::size_t const minPeerCount_
std::atomic< bool > unlBlocked_
bool subBook(InfoSub::ref ispListener, Book const &) override
std::uint32_t acceptLedger(std::optional< std::chrono::milliseconds > consensusDelay) override
Accepts the current transaction tree, return the new ledger's sequence.
void stateAccounting(Json::Value &obj) override
void submitTransaction(std::shared_ptr< STTx const > const &) override
bool unsubRTTransactions(std::uint64_t uListener) override
Json::Value getConsensusInfo() override
std::recursive_mutex mSubLock
std::atomic< bool > needNetworkLedger_
bool recvValidation(std::shared_ptr< STValidation > const &val, std::string const &source) override
void switchLastClosedLedger(std::shared_ptr< Ledger const > const &newLCL)
StateAccounting accounting_
void reportConsensusStateChange(ConsensusPhase phase)
bool subConsensus(InfoSub::ref ispListener) override
bool isNeedNetworkLedger() override
void setAmendmentWarned() override
bool processTrustedProposal(RCLCxPeerPos proposal) override
bool subPeerStatus(InfoSub::ref ispListener) override
void mapComplete(std::shared_ptr< SHAMap > const &map, bool fromAcquire) override
bool tryRemoveRpcSub(std::string const &strUrl) override
void pubAccountTransaction(std::shared_ptr< ReadView const > const &ledger, AcceptedLedgerTx const &transaction, bool last)
LedgerMaster & m_ledgerMaster
void clearLedgerFetch() override
bool isBlocked() override
void consensusViewChange() override
void setStateTimer() override
Called to initially start our timers.
bool subManifests(InfoSub::ref ispListener) override
void pubValidatedTransaction(std::shared_ptr< ReadView const > const &ledger, AcceptedLedgerTx const &transaction, bool last)
void subAccount(InfoSub::ref ispListener, hash_set< AccountID > const &vnaAccountIDs, bool rt) override
bool unsubServer(std::uint64_t uListener) override
MultiApiJson transJson(std::shared_ptr< STTx const > const &transaction, TER result, bool validated, std::shared_ptr< ReadView const > const &ledger, std::optional< std::reference_wrapper< TxMeta const > > meta)
ServerFeeSummary mLastFeeSummary
void pubPeerStatus(std::function< Json::Value(void)> const &) override
void setStandAlone() override
bool subRTTransactions(InfoSub::ref ispListener) override
void pubProposedAccountTransaction(std::shared_ptr< ReadView const > const &ledger, std::shared_ptr< STTx const > const &transaction, TER result)
std::condition_variable mCond
void setMode(OperatingMode om) override
void clearNeedNetworkLedger() override
DispatchState mDispatchState
bool subBookChanges(InfoSub::ref ispListener) override
SubInfoMapType mSubRTAccount
bool checkLastClosedLedger(const Overlay::PeerSequence &, uint256 &networkClosed)
void reportFeeChange() override
void processHeartbeatTimer()
bool unsubBook(std::uint64_t uListener, Book const &) override
void subAccountHistoryStart(std::shared_ptr< ReadView const > const &ledger, SubAccountHistoryInfoWeak &subInfo)
error_code_i subAccountHistory(InfoSub::ref ispListener, AccountID const &account) override
subscribe an account's new transactions and retrieve the account's historical transactions
std::mutex validationsMutex_
void pubManifest(Manifest const &) override
ConsensusPhase mLastConsensusPhase
bool subTransactions(InfoSub::ref ispListener) override
std::atomic< bool > amendmentWarned_
InfoSub::pointer findRpcSub(std::string const &strUrl) override
bool unsubLedger(std::uint64_t uListener) override
std::string getHostId(bool forAdmin)
bool unsubConsensus(std::uint64_t uListener) override
Provides server functionality for clients.
void getCountsJson(Json::Value &obj)
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Writable ledger view that accumulates state and tx changes.
BookListeners::pointer getBookListeners(Book const &)
BookListeners::pointer makeBookListeners(Book const &)
void processTxn(std::shared_ptr< ReadView const > const &ledger, const AcceptedLedgerTx &alTx, MultiApiJson const &jvObj)
virtual std::optional< std::uint32_t > networkID() const =0
Returns the ID of the network this server is configured for, if any.
virtual std::uint64_t getPeerDisconnect() const =0
virtual std::size_t size() const =0
Returns the number of active peers.
virtual std::uint64_t getJqTransOverflow() const =0
virtual std::uint64_t getPeerDisconnectCharges() const =0
Manages the generic consensus algorithm for use by the RCL.
std::size_t prevProposers() const
Get the number of proposing peers that participated in the previous round.
void simulate(NetClock::time_point const &now, std::optional< std::chrono::milliseconds > consensusDelay)
std::chrono::milliseconds prevRoundTime() const
Get duration of the previous round.
Json::Value getJson(bool full) const
A peer's signed, proposed position for use in RCLConsensus.
Represents a set of transactions in RCLConsensus.
Wraps a ledger instance for use in generic Validations LedgerTrie.
static std::string getWordFromBlob(void const *blob, size_t bytes)
Chooses a single dictionary word from the data.
Collects logging information.
std::unique_ptr< std::stringstream > const & ss()
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
virtual std::optional< key_type > succ(key_type const &key, std::optional< key_type > const &last=std::nullopt) const =0
Return the key of the next state item.
void setJson(Json::Value &) const
std::string getText() const override
Issue const & issue() const
std::optional< T > get(std::string const &name) const
std::size_t size() const noexcept
void const * data() const noexcept
void setup(Setup const &setup, beast::Journal journal)
time_point now() const override
Returns the current time, using the server's clock.
std::chrono::seconds closeOffset() const
time_point closeTime() const
Returns the predicted close time, in network time.
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
Validator keys and manifest as set in configuration file.
std::size_t count() const
Return the number of configured validator list sites.
std::optional< PublicKey > getTrustedKey(PublicKey const &identity) const
Returns master public key if public key is trusted.
std::optional< PublicKey > localPublicKey() const
This function returns the local validator public key or a std::nullopt.
std::optional< TimeKeeper::time_point > expires() const
Return the time when the validator list will expire.
std::size_t quorum() const
Get quorum value for current trusted key set.
constexpr double decimalXRP() const
Json::Value jsonClipped() const
static constexpr std::size_t size()
virtual Json::Value currentJson() const =0
Render currently executing jobs and RPC calls and durations in Json.
virtual Json::Value countersJson() const =0
Render performance counters in Json.
Automatically unlocks and re-locks a unique_lock object.
T emplace_back(T... args)
@ arrayValue
array value (ordered list)
@ objectValue
object value (collection of name/value pairs).
void rngfill(void *buffer, std::size_t bytes, Generator &g)
std::string const & getVersionString()
Server version.
Json::Value computeBookChanges(std::shared_ptr< L const > const &lpAccepted)
void insertMPTokenIssuanceID(Json::Value &response, std::shared_ptr< STTx const > const &transaction, TxMeta const &transactionMeta)
void insertDeliveredAmount(Json::Value &meta, ReadView const &, std::shared_ptr< STTx const > const &serializedTx, TxMeta const &)
Add a delivered_amount field to the meta input/output parameter.
Charge const feeMediumBurdenRPC
TER valid(PreclaimContext const &ctx, AccountID const &src)
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
STAmount divide(STAmount const &amount, Rate const &rate)
std::shared_ptr< STTx const > sterilize(STTx const &stx)
Sterilize a transaction.
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
bool cdirFirst(ReadView const &view, uint256 const &root, std::shared_ptr< SLE const > &page, unsigned int &index, uint256 &entry)
Returns the first entry in the directory, advancing the index.
std::uint64_t getQuality(uint256 const &uBase)
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
auto constexpr muldiv_max
std::unique_ptr< LocalTxs > make_LocalTxs()
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
STAmount amountFromQuality(std::uint64_t rate)
void handleNewValidation(Application &app, std::shared_ptr< STValidation > const &val, std::string const &source, BypassAccept const bypassAccept, std::optional< beast::Journal > j)
Handle a new validation.
std::unique_ptr< NetworkOPs > make_NetworkOPs(Application &app, NetworkOPs::clock_type &clock, bool standalone, std::size_t minPeerCount, bool startvalid, JobQueue &job_queue, LedgerMaster &ledgerMaster, ValidatorKeys const &validatorKeys, boost::asio::io_service &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
@ warnRPC_EXPIRED_VALIDATOR_LIST
@ warnRPC_UNSUPPORTED_MAJORITY
@ warnRPC_AMENDMENT_BLOCKED
std::unique_ptr< FeeVote > make_FeeVote(FeeSetup const &setup, beast::Journal journal)
Create an instance of the FeeVote logic.
OperatingMode
Specifies the mode under which the server believes it's operating.
@ TRACKING
convinced we agree with the network
@ DISCONNECTED
not ready to process requests
@ CONNECTED
convinced we are talking to the network
@ FULL
we have the ledger and can even validate
@ SYNCING
fallen slightly behind
STAmount multiply(STAmount const &amount, Rate const &rate)
AccountID calcAccountID(PublicKey const &pk)
@ current
This was a new validation and was added.
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
Json::Value rpcError(int iError)
ConsensusPhase
Phases of consensus for a single ledger round.
static std::array< char const *, 5 > const stateNames
std::string strHex(FwdIt begin, FwdIt end)
bool isTemMalformed(TER x)
bool cdirNext(ReadView const &view, uint256 const &root, std::shared_ptr< SLE const > &page, unsigned int &index, uint256 &entry)
Returns the next entry in the directory, advancing the index.
void forAllApiVersions(Fn const &fn, Args &&... args)
send_if_pred< Predicate > send_if(std::shared_ptr< Message > const &m, Predicate const &f)
Helper function to aid in type deduction.
uint256 getQualityNext(uint256 const &uBase)
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Rules makeRulesGivenLedger(DigestAwareReadView const &ledger, Rules const ¤t)
std::string to_string_iso(date::sys_time< Duration > tp)
std::string to_string(base_uint< Bits, Tag > const &a)
FeeSetup setup_FeeVote(Section const §ion)
Number root(Number f, unsigned d)
std::optional< std::uint64_t > mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
Return value*mul/div accurately.
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
@ ledgerMaster
ledger master data for signing
@ proposal
proposal for signing
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules, Config const &config)
Checks transaction signature and local checks.
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
bool transResultInfo(TER code, std::string &token, std::string &text)
uint256 getBookBase(Book const &book)
Rate const parityRate
A transfer rate signifying a 1:1 exchange.
bool isGlobalFrozen(ReadView const &view, AccountID const &issuer)
static std::uint32_t trunc32(std::uint64_t v)
static auto const genesisAccountId
T set_intersection(T... args)
std::string serialized
The manifest in serialized form.
std::uint32_t sequence
The sequence number of this manifest.
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
std::optional< Blob > getSignature() const
Returns manifest signature.
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Blob getMasterSignature() const
Returns manifest master key signature.
PublicKey masterKey
The master key associated with this manifest.
Server fees published on server subscription.
bool operator!=(ServerFeeSummary const &b) const
ServerFeeSummary()=default
std::optional< TxQ::Metrics > em
std::uint32_t loadFactorServer
bool operator==(ServerFeeSummary const &b) const
std::uint32_t loadBaseServer
decltype(initialSyncUs_) initialSyncUs
decltype(counters_) counters
std::uint64_t transitions
std::chrono::microseconds dur
beast::insight::Gauge full_transitions
Stats(Handler const &handler, beast::insight::Collector::ptr const &collector)
beast::insight::Hook hook
beast::insight::Gauge connected_duration
beast::insight::Gauge tracking_duration
beast::insight::Gauge connected_transitions
beast::insight::Gauge disconnected_transitions
beast::insight::Gauge syncing_duration
beast::insight::Gauge tracking_transitions
beast::insight::Gauge full_duration
beast::insight::Gauge disconnected_duration
beast::insight::Gauge syncing_transitions
std::uint32_t historyLastLedgerSeq_
std::uint32_t separationLedgerSeq_
AccountID const accountId_
std::uint32_t forwardTxIndex_
std::atomic< bool > stopHistorical_
std::int32_t historyTxIndex_
SubAccountHistoryIndex(AccountID const &accountId)
std::shared_ptr< SubAccountHistoryIndex > index_
std::shared_ptr< SubAccountHistoryIndex > index_
Represents a transfer rate.
Data format for exchanging consumption information across peers.
std::vector< Item > items
Changes in trusted nodes after updating validator list.
hash_set< NodeID > removed
Structure returned by TxQ::getMetrics, expressed in reference fee level units.
void set(const char *key, auto const &v)
IsMemberResult isMember(const char *key) const
Select all peers (except optional excluded) that are in our cluster.
Sends a message to all peers.
T time_since_epoch(T... args)