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/ValidatorKeys.h>
39#include <xrpld/app/misc/ValidatorList.h>
40#include <xrpld/app/misc/detail/AccountTxPaging.h>
41#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
42#include <xrpld/app/tx/apply.h>
43#include <xrpld/consensus/Consensus.h>
44#include <xrpld/consensus/ConsensusParms.h>
45#include <xrpld/overlay/Cluster.h>
46#include <xrpld/overlay/Overlay.h>
47#include <xrpld/overlay/predicates.h>
48#include <xrpld/perflog/PerfLog.h>
49#include <xrpld/rpc/BookChanges.h>
50#include <xrpld/rpc/DeliveredAmount.h>
51#include <xrpld/rpc/MPTokenIssuanceID.h>
52#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/rfc2616.h>
58#include <xrpl/beast/utility/rngfill.h>
59#include <xrpl/crypto/RFC1751.h>
60#include <xrpl/crypto/csprng.h>
61#include <xrpl/json/to_string.h>
62#include <xrpl/protocol/BuildInfo.h>
63#include <xrpl/protocol/Feature.h>
64#include <xrpl/protocol/MultiApiJson.h>
65#include <xrpl/protocol/RPCErr.h>
66#include <xrpl/protocol/STParsedJSON.h>
67#include <xrpl/protocol/jss.h>
68#include <xrpl/resource/Fees.h>
69#include <xrpl/resource/ResourceManager.h>
70#include <boost/asio/ip/host_name.hpp>
71#include <boost/asio/steady_timer.hpp>
111 "ripple::NetworkOPsImp::TransactionStatus::TransactionStatus : "
154 std::chrono::steady_clock::time_point
start_ =
215 return !(*
this != b);
234 boost::asio::io_service& io_svc,
248 app_.logs().journal(
"FeeVote")),
251 app.getInboundTransactions(),
252 beast::get_abstract_clock<
std::chrono::steady_clock>(),
254 app_.logs().journal(
"LedgerConsensus"))
435 getServerInfo(
bool human,
bool admin,
bool counters)
override;
462 TER result)
override;
496 bool historyOnly)
override;
502 bool historyOnly)
override;
570 boost::system::error_code ec;
575 <<
"NetworkOPs: heartbeatTimer cancel error: "
584 <<
"NetworkOPs: clusterTimer cancel error: "
593 <<
"NetworkOPs: accountHistoryTxTimer cancel error: "
598 using namespace std::chrono_literals;
608 boost::asio::steady_timer& timer,
788 template <
class Handler>
790 Handler
const& handler,
792 :
hook(collector->make_hook(handler))
795 "Disconnected_duration"))
798 "Connected_duration"))
800 collector->make_gauge(
"State_Accounting",
"Syncing_duration"))
803 "Tracking_duration"))
805 collector->make_gauge(
"State_Accounting",
"Full_duration"))
808 "Disconnected_transitions"))
811 "Connected_transitions"))
814 "Syncing_transitions"))
817 "Tracking_transitions"))
819 collector->make_gauge(
"State_Accounting",
"Full_transitions"))
848 {
"disconnected",
"connected",
"syncing",
"tracking",
"full"}};
910 static std::string const hostname = boost::asio::ip::host_name();
917 static std::string const shroudedHostId = [
this]() {
923 return shroudedHostId;
938 boost::asio::steady_timer& timer,
945 [
this, onExpire, onError](boost::system::error_code
const& e) {
946 if ((e.value() == boost::system::errc::success) &&
947 (!m_job_queue.isStopped()))
952 if (e.value() != boost::system::errc::success &&
953 e.value() != boost::asio::error::operation_aborted)
956 JLOG(m_journal.error())
957 <<
"Timer got error '" << e.message()
958 <<
"'. Restarting timer.";
963 timer.expires_from_now(expiry_time);
964 timer.async_wait(std::move(*optionalCountedHandler));
969NetworkOPsImp::setHeartbeatTimer()
973 mConsensus.parms().ledgerGRANULARITY,
975 m_job_queue.addJob(jtNETOP_TIMER,
"NetOPs.heartbeat", [this]() {
976 processHeartbeatTimer();
979 [
this]() { setHeartbeatTimer(); });
983NetworkOPsImp::setClusterTimer()
985 using namespace std::chrono_literals;
992 processClusterTimer();
995 [
this]() { setClusterTimer(); });
1001 JLOG(m_journal.debug()) <<
"Scheduling AccountHistory job for account "
1003 using namespace std::chrono_literals;
1005 accountHistoryTxTimer_,
1007 [
this, subInfo]() { addAccountHistoryJob(subInfo); },
1008 [
this, subInfo]() { setAccountHistoryJobTimer(subInfo); });
1012NetworkOPsImp::processHeartbeatTimer()
1015 "Heartbeat Timer", mConsensus.validating(), m_journal);
1023 std::size_t const numPeers = app_.overlay().size();
1026 if (numPeers < minPeerCount_)
1028 if (mMode != OperatingMode::DISCONNECTED)
1030 setMode(OperatingMode::DISCONNECTED);
1032 ss <<
"Node count (" << numPeers <<
") has fallen "
1033 <<
"below required minimum (" << minPeerCount_ <<
").";
1034 JLOG(m_journal.warn()) << ss.
str();
1035 CLOG(clog.
ss()) <<
"set mode to DISCONNECTED: " << ss.
str();
1040 <<
"already DISCONNECTED. too few peers (" << numPeers
1041 <<
"), need at least " << minPeerCount_;
1048 setHeartbeatTimer();
1053 if (mMode == OperatingMode::DISCONNECTED)
1055 setMode(OperatingMode::CONNECTED);
1056 JLOG(m_journal.info())
1057 <<
"Node count (" << numPeers <<
") is sufficient.";
1058 CLOG(clog.
ss()) <<
"setting mode to CONNECTED based on " << numPeers
1064 auto origMode = mMode.load();
1065 CLOG(clog.
ss()) <<
"mode: " << strOperatingMode(origMode,
true);
1066 if (mMode == OperatingMode::SYNCING)
1067 setMode(OperatingMode::SYNCING);
1068 else if (mMode == OperatingMode::CONNECTED)
1069 setMode(OperatingMode::CONNECTED);
1070 auto newMode = mMode.load();
1071 if (origMode != newMode)
1074 <<
", changing to " << strOperatingMode(newMode,
true);
1076 CLOG(clog.
ss()) <<
". ";
1079 mConsensus.timerEntry(app_.timeKeeper().closeTime(), clog.
ss());
1081 CLOG(clog.
ss()) <<
"consensus phase " << to_string(mLastConsensusPhase);
1083 if (mLastConsensusPhase != currPhase)
1085 reportConsensusStateChange(currPhase);
1086 mLastConsensusPhase = currPhase;
1087 CLOG(clog.
ss()) <<
" changed to " << to_string(mLastConsensusPhase);
1089 CLOG(clog.
ss()) <<
". ";
1091 setHeartbeatTimer();
1095NetworkOPsImp::processClusterTimer()
1097 if (app_.cluster().size() == 0)
1100 using namespace std::chrono_literals;
1102 bool const update = app_.cluster().update(
1103 app_.nodeIdentity().first,
1105 (m_ledgerMaster.getValidatedLedgerAge() <= 4min)
1106 ? app_.getFeeTrack().getLocalFee()
1108 app_.timeKeeper().now());
1112 JLOG(m_journal.debug()) <<
"Too soon to send cluster update";
1117 protocol::TMCluster cluster;
1118 app_.cluster().for_each([&cluster](
ClusterNode const& node) {
1119 protocol::TMClusterNode& n = *cluster.add_clusternodes();
1124 n.set_nodename(node.
name());
1128 for (
auto& item : gossip.
items)
1130 protocol::TMLoadSource& node = *cluster.add_loadsources();
1131 node.set_name(to_string(item.address));
1132 node.set_cost(item.balance);
1134 app_.overlay().foreach(
send_if(
1135 std::make_shared<Message>(cluster, protocol::mtCLUSTER),
1146 if (mode == OperatingMode::FULL && admin)
1148 auto const consensusMode = mConsensus.mode();
1149 if (consensusMode != ConsensusMode::wrongLedger)
1151 if (consensusMode == ConsensusMode::proposing)
1154 if (mConsensus.validating())
1155 return "validating";
1165 if (isNeedNetworkLedger())
1174 auto const txid = trans->getTransactionID();
1175 auto const flags = app_.getHashRouter().getFlags(txid);
1177 if ((flags & SF_BAD) != 0)
1179 JLOG(m_journal.warn()) <<
"Submitted transaction cached bad";
1186 app_.getHashRouter(),
1188 m_ledgerMaster.getValidatedRules(),
1191 if (validity != Validity::Valid)
1193 JLOG(m_journal.warn())
1194 <<
"Submitted transaction invalid: " << reason;
1200 JLOG(m_journal.warn())
1201 <<
"Exception checking transaction " << txid <<
": " << ex.
what();
1208 auto tx = std::make_shared<Transaction>(trans, reason, app_);
1210 m_job_queue.addJob(
jtTRANSACTION,
"submitTxn", [
this, tx]() {
1212 processTransaction(t,
false,
false, FailHard::no);
1217NetworkOPsImp::processTransaction(
1223 auto ev = m_job_queue.makeLoadEvent(
jtTXN_PROC,
"ProcessTXN");
1224 auto const newFlags = app_.getHashRouter().getFlags(transaction->getID());
1226 if ((newFlags & SF_BAD) != 0)
1229 JLOG(m_journal.warn()) << transaction->getID() <<
": cached bad!\n";
1230 transaction->setStatus(
INVALID);
1238 auto const view = m_ledgerMaster.getCurrentLedger();
1240 app_.getHashRouter(),
1241 *transaction->getSTransaction(),
1245 validity == Validity::Valid,
1246 "ripple::NetworkOPsImp::processTransaction : valid validity");
1249 if (validity == Validity::SigBad)
1251 JLOG(m_journal.info()) <<
"Transaction has bad signature: " << reason;
1252 transaction->setStatus(
INVALID);
1254 app_.getHashRouter().setFlags(transaction->getID(), SF_BAD);
1259 app_.getMasterTransaction().canonicalize(&transaction);
1262 doTransactionSync(transaction, bUnlimited, failType);
1264 doTransactionAsync(transaction, bUnlimited, failType);
1268NetworkOPsImp::doTransactionAsync(
1275 if (transaction->getApplying())
1278 mTransactions.push_back(
1280 transaction->setApplying();
1282 if (mDispatchState == DispatchState::none)
1284 if (m_job_queue.addJob(
1285 jtBATCH,
"transactionBatch", [
this]() { transactionBatch(); }))
1287 mDispatchState = DispatchState::scheduled;
1293NetworkOPsImp::doTransactionSync(
1300 if (!transaction->getApplying())
1302 mTransactions.push_back(
1304 transaction->setApplying();
1309 if (mDispatchState == DispatchState::running)
1318 if (mTransactions.size())
1321 if (m_job_queue.addJob(
jtBATCH,
"transactionBatch", [
this]() {
1325 mDispatchState = DispatchState::scheduled;
1329 }
while (transaction->getApplying());
1333NetworkOPsImp::transactionBatch()
1337 if (mDispatchState == DispatchState::running)
1340 while (mTransactions.size())
1351 mTransactions.
swap(transactions);
1353 !transactions.
empty(),
1354 "ripple::NetworkOPsImp::apply : non-empty transactions");
1356 mDispatchState != DispatchState::running,
1357 "ripple::NetworkOPsImp::apply : is not running");
1359 mDispatchState = DispatchState::running;
1365 bool changed =
false;
1368 m_ledgerMaster.peekMutex(), std::defer_lock};
1379 if (e.failType == FailHard::yes)
1382 auto const result = app_.getTxQ().apply(
1383 app_, view, e.transaction->getSTransaction(), flags, j);
1384 e.result = result.ter;
1385 e.applied = result.applied;
1386 changed = changed || result.applied;
1395 if (
auto const l = m_ledgerMaster.getValidatedLedger())
1396 validatedLedgerIndex = l->info().seq;
1398 auto newOL = app_.openLedger().current();
1401 e.transaction->clearSubmitResult();
1405 pubProposedTransaction(
1406 newOL, e.transaction->getSTransaction(), e.result);
1407 e.transaction->setApplied();
1410 e.transaction->setResult(e.result);
1413 app_.getHashRouter().setFlags(e.transaction->getID(), SF_BAD);
1422 JLOG(m_journal.info())
1423 <<
"TransactionResult: " << token <<
": " << human;
1428 bool addLocal = e.local;
1432 JLOG(m_journal.debug())
1433 <<
"Transaction is now included in open ledger";
1434 e.transaction->setStatus(
INCLUDED);
1436 auto const& txCur = e.transaction->getSTransaction();
1437 auto const txNext = m_ledgerMaster.popAcctTransaction(txCur);
1442 auto t = std::make_shared<Transaction>(trans, reason, app_);
1443 submit_held.
emplace_back(t,
false,
false, FailHard::no);
1450 JLOG(m_journal.info()) <<
"Transaction is obsolete";
1451 e.transaction->setStatus(
OBSOLETE);
1455 JLOG(m_journal.debug())
1456 <<
"Transaction is likely to claim a"
1457 <<
" fee, but is queued until fee drops";
1459 e.transaction->setStatus(
HELD);
1463 m_ledgerMaster.addHeldTransaction(e.transaction);
1464 e.transaction->setQueued();
1465 e.transaction->setKept();
1469 if (e.failType != FailHard::yes)
1472 JLOG(m_journal.debug())
1473 <<
"Transaction should be held: " << e.result;
1474 e.transaction->setStatus(
HELD);
1475 m_ledgerMaster.addHeldTransaction(e.transaction);
1476 e.transaction->setKept();
1481 JLOG(m_journal.debug())
1482 <<
"Status other than success " << e.result;
1483 e.transaction->setStatus(
INVALID);
1486 auto const enforceFailHard =
1487 e.failType == FailHard::yes && !
isTesSuccess(e.result);
1489 if (addLocal && !enforceFailHard)
1491 m_localTX->push_back(
1492 m_ledgerMaster.getCurrentLedgerIndex(),
1493 e.transaction->getSTransaction());
1494 e.transaction->setKept();
1498 ((mMode != OperatingMode::FULL) &&
1499 (e.failType != FailHard::yes) && e.local) ||
1504 app_.getHashRouter().shouldRelay(e.transaction->getID());
1508 protocol::TMTransaction tx;
1511 e.transaction->getSTransaction()->add(s);
1512 tx.set_rawtransaction(s.
data(), s.
size());
1513 tx.set_status(protocol::tsCURRENT);
1514 tx.set_receivetimestamp(
1515 app_.timeKeeper().now().time_since_epoch().count());
1518 app_.overlay().relay(e.transaction->getID(), tx, *toSkip);
1519 e.transaction->setBroadcast();
1523 if (validatedLedgerIndex)
1525 auto [fee, accountSeq, availableSeq] =
1526 app_.getTxQ().getTxRequiredFeeAndSeq(
1527 *newOL, e.transaction->getSTransaction());
1528 e.transaction->setCurrentLedgerState(
1529 *validatedLedgerIndex, fee, accountSeq, availableSeq);
1537 e.transaction->clearApplying();
1539 if (!submit_held.
empty())
1541 if (mTransactions.empty())
1542 mTransactions.swap(submit_held);
1544 for (
auto& e : submit_held)
1545 mTransactions.push_back(std::move(e));
1550 mDispatchState = DispatchState::none;
1558NetworkOPsImp::getOwnerInfo(
1563 auto root = keylet::ownerDir(account);
1564 auto sleNode = lpLedger->read(keylet::page(
root));
1571 for (
auto const& uDirEntry : sleNode->getFieldV256(sfIndexes))
1573 auto sleCur = lpLedger->read(keylet::child(uDirEntry));
1576 "ripple::NetworkOPsImp::getOwnerInfo : non-null child SLE");
1578 switch (sleCur->getType())
1581 if (!jvObjects.
isMember(jss::offers))
1582 jvObjects[jss::offers] =
1585 jvObjects[jss::offers].
append(
1586 sleCur->getJson(JsonOptions::none));
1589 case ltRIPPLE_STATE:
1590 if (!jvObjects.
isMember(jss::ripple_lines))
1592 jvObjects[jss::ripple_lines] =
1596 jvObjects[jss::ripple_lines].
append(
1597 sleCur->getJson(JsonOptions::none));
1600 case ltACCOUNT_ROOT:
1604 "ripple::NetworkOPsImp::getOwnerInfo : invalid "
1610 uNodeDir = sleNode->getFieldU64(sfIndexNext);
1614 sleNode = lpLedger->read(keylet::page(
root, uNodeDir));
1617 "ripple::NetworkOPsImp::getOwnerInfo : read next page");
1630NetworkOPsImp::isBlocked()
1632 return isAmendmentBlocked() || isUNLBlocked();
1636NetworkOPsImp::isAmendmentBlocked()
1638 return amendmentBlocked_;
1642NetworkOPsImp::setAmendmentBlocked()
1644 amendmentBlocked_ =
true;
1645 setMode(OperatingMode::CONNECTED);
1649NetworkOPsImp::isAmendmentWarned()
1651 return !amendmentBlocked_ && amendmentWarned_;
1655NetworkOPsImp::setAmendmentWarned()
1657 amendmentWarned_ =
true;
1661NetworkOPsImp::clearAmendmentWarned()
1663 amendmentWarned_ =
false;
1667NetworkOPsImp::isUNLBlocked()
1673NetworkOPsImp::setUNLBlocked()
1676 setMode(OperatingMode::CONNECTED);
1680NetworkOPsImp::clearUNLBlocked()
1682 unlBlocked_ =
false;
1686NetworkOPsImp::checkLastClosedLedger(
1695 JLOG(m_journal.trace()) <<
"NetworkOPsImp::checkLastClosedLedger";
1697 auto const ourClosed = m_ledgerMaster.getClosedLedger();
1702 uint256 closedLedger = ourClosed->info().hash;
1703 uint256 prevClosedLedger = ourClosed->info().parentHash;
1704 JLOG(m_journal.trace()) <<
"OurClosed: " << closedLedger;
1705 JLOG(m_journal.trace()) <<
"PrevClosed: " << prevClosedLedger;
1710 auto& validations = app_.getValidations();
1711 JLOG(m_journal.debug())
1712 <<
"ValidationTrie " <<
Json::Compact(validations.getJsonTrie());
1716 peerCounts[closedLedger] = 0;
1717 if (mMode >= OperatingMode::TRACKING)
1718 peerCounts[closedLedger]++;
1720 for (
auto& peer : peerList)
1722 uint256 peerLedger = peer->getClosedLedgerHash();
1725 ++peerCounts[peerLedger];
1728 for (
auto const& it : peerCounts)
1729 JLOG(m_journal.debug()) <<
"L: " << it.first <<
" n=" << it.second;
1731 uint256 preferredLCL = validations.getPreferredLCL(
1733 m_ledgerMaster.getValidLedgerIndex(),
1736 bool switchLedgers = preferredLCL != closedLedger;
1738 closedLedger = preferredLCL;
1740 if (switchLedgers && (closedLedger == prevClosedLedger))
1743 JLOG(m_journal.info()) <<
"We won't switch to our own previous ledger";
1744 networkClosed = ourClosed->info().hash;
1745 switchLedgers =
false;
1748 networkClosed = closedLedger;
1753 auto consensus = m_ledgerMaster.getLedgerByHash(closedLedger);
1756 consensus = app_.getInboundLedgers().acquire(
1757 closedLedger, 0, InboundLedger::Reason::CONSENSUS);
1760 (!m_ledgerMaster.canBeCurrent(consensus) ||
1761 !m_ledgerMaster.isCompatible(
1762 *consensus, m_journal.debug(),
"Not switching")))
1766 networkClosed = ourClosed->info().hash;
1770 JLOG(m_journal.warn()) <<
"We are not running on the consensus ledger";
1771 JLOG(m_journal.info()) <<
"Our LCL: " << ourClosed->info().hash
1773 JLOG(m_journal.info()) <<
"Net LCL " << closedLedger;
1775 if ((mMode == OperatingMode::TRACKING) || (mMode == OperatingMode::FULL))
1777 setMode(OperatingMode::CONNECTED);
1785 switchLastClosedLedger(consensus);
1792NetworkOPsImp::switchLastClosedLedger(
1796 JLOG(m_journal.error())
1797 <<
"JUMP last closed ledger to " << newLCL->info().hash;
1799 clearNeedNetworkLedger();
1802 app_.getTxQ().processClosedLedger(app_, *newLCL,
true);
1809 auto retries = m_localTX->getTxSet();
1810 auto const lastVal = app_.getLedgerMaster().getValidatedLedger();
1815 rules.
emplace(app_.config().features);
1816 app_.openLedger().accept(
1827 return app_.getTxQ().accept(app_, view);
1831 m_ledgerMaster.switchLCL(newLCL);
1833 protocol::TMStatusChange s;
1834 s.set_newevent(protocol::neSWITCHED_LEDGER);
1835 s.set_ledgerseq(newLCL->info().seq);
1836 s.set_networktime(app_.timeKeeper().now().time_since_epoch().count());
1837 s.set_ledgerhashprevious(
1838 newLCL->info().parentHash.begin(), newLCL->info().parentHash.size());
1839 s.set_ledgerhash(newLCL->info().hash.begin(), newLCL->info().hash.size());
1841 app_.overlay().foreach(
1842 send_always(std::make_shared<Message>(s, protocol::mtSTATUS_CHANGE)));
1846NetworkOPsImp::beginConsensus(
1852 "ripple::NetworkOPsImp::beginConsensus : nonzero input");
1854 auto closingInfo = m_ledgerMaster.getCurrentLedger()->info();
1856 JLOG(m_journal.info()) <<
"Consensus time for #" << closingInfo.seq
1857 <<
" with LCL " << closingInfo.parentHash;
1859 auto prevLedger = m_ledgerMaster.getLedgerByHash(closingInfo.parentHash);
1864 if (mMode == OperatingMode::FULL)
1866 JLOG(m_journal.warn()) <<
"Don't have LCL, going to tracking";
1867 setMode(OperatingMode::TRACKING);
1868 CLOG(clog) <<
"beginConsensus Don't have LCL, going to tracking. ";
1871 CLOG(clog) <<
"beginConsensus no previous ledger. ";
1876 prevLedger->info().hash == closingInfo.parentHash,
1877 "ripple::NetworkOPsImp::beginConsensus : prevLedger hash matches "
1880 closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->info().hash,
1881 "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches "
1884 if (prevLedger->rules().enabled(featureNegativeUNL))
1885 app_.validators().setNegativeUNL(prevLedger->negativeUNL());
1886 TrustChanges const changes = app_.validators().updateTrusted(
1887 app_.getValidations().getCurrentNodeIDs(),
1888 closingInfo.parentCloseTime,
1891 app_.getHashRouter());
1893 if (!changes.
added.empty() || !changes.
removed.empty())
1895 app_.getValidations().trustChanged(changes.
added, changes.
removed);
1897 app_.getAmendmentTable().trustChanged(
1898 app_.validators().getQuorumKeys().second);
1901 mConsensus.startRound(
1902 app_.timeKeeper().closeTime(),
1910 if (mLastConsensusPhase != currPhase)
1912 reportConsensusStateChange(currPhase);
1913 mLastConsensusPhase = currPhase;
1916 JLOG(m_journal.debug()) <<
"Initiating consensus engine";
1923 return mConsensus.peerProposal(app_.timeKeeper().closeTime(), peerPos);
1934 protocol::TMHaveTransactionSet msg;
1935 msg.set_hash(map->getHash().as_uint256().begin(), 256 / 8);
1936 msg.set_status(protocol::tsHAVE);
1937 app_.overlay().foreach(
1938 send_always(std::make_shared<Message>(msg, protocol::mtHAVE_SET)));
1942 mConsensus.gotTxSet(app_.timeKeeper().closeTime(),
RCLTxSet{map});
1948 uint256 deadLedger = m_ledgerMaster.getClosedLedger()->info().parentHash;
1950 for (
auto const& it : app_.overlay().getActivePeers())
1952 if (it && (it->getClosedLedgerHash() == deadLedger))
1954 JLOG(m_journal.trace()) <<
"Killing obsolete peer status";
1961 checkLastClosedLedger(app_.overlay().getActivePeers(), networkClosed);
1963 if (networkClosed.
isZero())
1965 CLOG(clog) <<
"endConsensus last closed ledger is zero. ";
1975 if (((mMode == OperatingMode::CONNECTED) ||
1976 (mMode == OperatingMode::SYNCING)) &&
1982 if (!needNetworkLedger_)
1983 setMode(OperatingMode::TRACKING);
1986 if (((mMode == OperatingMode::CONNECTED) ||
1987 (mMode == OperatingMode::TRACKING)) &&
1993 auto current = m_ledgerMaster.getCurrentLedger();
1994 if (app_.timeKeeper().now() < (
current->info().parentCloseTime +
1995 2 *
current->info().closeTimeResolution))
1997 setMode(OperatingMode::FULL);
2001 beginConsensus(networkClosed, clog);
2005NetworkOPsImp::consensusViewChange()
2007 if ((mMode == OperatingMode::FULL) || (mMode == OperatingMode::TRACKING))
2009 setMode(OperatingMode::CONNECTED);
2019 if (!mStreamMaps[sManifests].empty())
2023 jvObj[jss::type] =
"manifestReceived";
2026 jvObj[jss::signing_key] =
2030 jvObj[jss::signature] =
strHex(*sig);
2033 jvObj[jss::domain] = mo.
domain;
2036 for (
auto i = mStreamMaps[sManifests].begin();
2037 i != mStreamMaps[sManifests].end();)
2039 if (
auto p = i->second.lock())
2041 p->send(jvObj,
true);
2046 i = mStreamMaps[sManifests].erase(i);
2052NetworkOPsImp::ServerFeeSummary::ServerFeeSummary(
2056 : loadFactorServer{loadFeeTrack.getLoadFactor()}
2057 , loadBaseServer{loadFeeTrack.getLoadBase()}
2059 , em{
std::move(escalationMetrics)}
2069 em.has_value() != b.
em.has_value())
2075 em->minProcessingFeeLevel != b.
em->minProcessingFeeLevel ||
2076 em->openLedgerFeeLevel != b.
em->openLedgerFeeLevel ||
2077 em->referenceFeeLevel != b.
em->referenceFeeLevel);
2110 jvObj[jss::type] =
"serverStatus";
2112 jvObj[jss::load_base] = f.loadBaseServer;
2113 jvObj[jss::load_factor_server] = f.loadFactorServer;
2114 jvObj[jss::base_fee] = f.baseFee.jsonClipped();
2119 safe_cast<std::uint64_t>(f.loadFactorServer),
2121 f.em->openLedgerFeeLevel,
2123 f.em->referenceFeeLevel)
2126 jvObj[jss::load_factor] =
trunc32(loadFactor);
2127 jvObj[jss::load_factor_fee_escalation] =
2128 f.em->openLedgerFeeLevel.jsonClipped();
2129 jvObj[jss::load_factor_fee_queue] =
2130 f.em->minProcessingFeeLevel.jsonClipped();
2131 jvObj[jss::load_factor_fee_reference] =
2132 f.em->referenceFeeLevel.jsonClipped();
2135 jvObj[jss::load_factor] = f.loadFactorServer;
2149 p->send(jvObj,
true);
2166 if (!streamMap.empty())
2169 jvObj[jss::type] =
"consensusPhase";
2170 jvObj[jss::consensus] =
to_string(phase);
2172 for (
auto i = streamMap.begin(); i != streamMap.end();)
2174 if (
auto p = i->second.lock())
2176 p->send(jvObj,
true);
2181 i = streamMap.erase(i);
2197 auto const signerPublic = val->getSignerPublic();
2199 jvObj[jss::type] =
"validationReceived";
2200 jvObj[jss::validation_public_key] =
2202 jvObj[jss::ledger_hash] =
to_string(val->getLedgerHash());
2203 jvObj[jss::signature] =
strHex(val->getSignature());
2204 jvObj[jss::full] = val->isFull();
2205 jvObj[jss::flags] = val->getFlags();
2206 jvObj[jss::signing_time] = *(*val)[~sfSigningTime];
2207 jvObj[jss::data] =
strHex(val->getSerializer().slice());
2209 if (
auto version = (*val)[~sfServerVersion])
2212 if (
auto cookie = (*val)[~sfCookie])
2215 if (
auto hash = (*val)[~sfValidatedHash])
2216 jvObj[jss::validated_hash] =
strHex(*hash);
2218 auto const masterKey =
2221 if (masterKey != signerPublic)
2226 if (
auto const seq = (*val)[~sfLedgerSequence])
2227 jvObj[jss::ledger_index] = *seq;
2229 if (val->isFieldPresent(sfAmendments))
2232 for (
auto const& amendment : val->getFieldV256(sfAmendments))
2236 if (
auto const closeTime = (*val)[~sfCloseTime])
2237 jvObj[jss::close_time] = *closeTime;
2239 if (
auto const loadFee = (*val)[~sfLoadFee])
2240 jvObj[jss::load_fee] = *loadFee;
2242 if (
auto const baseFee = val->at(~sfBaseFee))
2243 jvObj[jss::base_fee] =
static_cast<double>(*baseFee);
2245 if (
auto const reserveBase = val->at(~sfReserveBase))
2246 jvObj[jss::reserve_base] = *reserveBase;
2248 if (
auto const reserveInc = val->at(~sfReserveIncrement))
2249 jvObj[jss::reserve_inc] = *reserveInc;
2253 if (
auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops);
2254 baseFeeXRP && baseFeeXRP->native())
2255 jvObj[jss::base_fee] = baseFeeXRP->xrp().jsonClipped();
2257 if (
auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops);
2258 reserveBaseXRP && reserveBaseXRP->native())
2259 jvObj[jss::reserve_base] = reserveBaseXRP->xrp().jsonClipped();
2261 if (
auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops);
2262 reserveIncXRP && reserveIncXRP->native())
2263 jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped();
2272 if (jvTx.
isMember(jss::ledger_index))
2274 jvTx[jss::ledger_index] =
2275 std::to_string(jvTx[jss::ledger_index].asUInt());
2282 if (
auto p = i->second.lock())
2286 [&](
Json::Value const& jv) { p->send(jv, true); });
2306 jvObj[jss::type] =
"peerStatusChange";
2315 p->send(jvObj,
true);
2329 using namespace std::chrono_literals;
2361 <<
"recvValidation " << val->getLedgerHash() <<
" from " << source;
2377 <<
"Exception thrown for handling new validation "
2378 << val->getLedgerHash() <<
": " << e.
what();
2383 <<
"Unknown exception thrown for handling new validation "
2384 << val->getLedgerHash();
2396 ss <<
"VALIDATION: " << val->render() <<
" master_key: ";
2433 "This server is amendment blocked, and must be updated to be "
2434 "able to stay in sync with the network.";
2441 "This server has an expired validator list. validators.txt "
2442 "may be incorrectly configured or some [validator_list_sites] "
2443 "may be unreachable.";
2450 "One or more unsupported amendments have reached majority. "
2451 "Upgrade to the latest version before they are activated "
2452 "to avoid being amendment blocked.";
2453 if (
auto const expected =
2457 d[jss::expected_date] = expected->time_since_epoch().count();
2458 d[jss::expected_date_UTC] =
to_string(*expected);
2462 if (warnings.size())
2463 info[jss::warnings] = std::move(warnings);
2478 info[jss::time] =
to_string(std::chrono::floor<std::chrono::microseconds>(
2482 info[jss::network_ledger] =
"waiting";
2484 info[jss::validation_quorum] =
2492 info[jss::node_size] =
"tiny";
2495 info[jss::node_size] =
"small";
2498 info[jss::node_size] =
"medium";
2501 info[jss::node_size] =
"large";
2504 info[jss::node_size] =
"huge";
2513 info[jss::validator_list_expires] =
2514 safe_cast<Json::UInt>(when->time_since_epoch().count());
2516 info[jss::validator_list_expires] = 0;
2526 if (*when == TimeKeeper::time_point::max())
2528 x[jss::expiration] =
"never";
2529 x[jss::status] =
"active";
2536 x[jss::status] =
"active";
2538 x[jss::status] =
"expired";
2543 x[jss::status] =
"unknown";
2544 x[jss::expiration] =
"unknown";
2548#if defined(GIT_COMMIT_HASH) || defined(GIT_BRANCH)
2551#ifdef GIT_COMMIT_HASH
2552 x[jss::hash] = GIT_COMMIT_HASH;
2555 x[jss::branch] = GIT_BRANCH;
2560 info[jss::io_latency_ms] =
2568 info[jss::pubkey_validator] =
2573 info[jss::pubkey_validator] =
"none";
2583 info[jss::counters][jss::nodestore] = nodestore;
2587 info[jss::pubkey_node] =
2593 info[jss::amendment_blocked] =
true;
2607 lastClose[jss::converge_time_s] =
2612 lastClose[jss::converge_time] =
2616 info[jss::last_close] = lastClose;
2624 info[jss::network_id] =
static_cast<Json::UInt>(*netid);
2626 auto const escalationMetrics =
2634 auto const loadFactorFeeEscalation =
2636 escalationMetrics.openLedgerFeeLevel,
2638 escalationMetrics.referenceFeeLevel)
2642 safe_cast<std::uint64_t>(loadFactorServer), loadFactorFeeEscalation);
2646 info[jss::load_base] = loadBaseServer;
2647 info[jss::load_factor] =
trunc32(loadFactor);
2648 info[jss::load_factor_server] = loadFactorServer;
2655 info[jss::load_factor_fee_escalation] =
2656 escalationMetrics.openLedgerFeeLevel.jsonClipped();
2657 info[jss::load_factor_fee_queue] =
2658 escalationMetrics.minProcessingFeeLevel.jsonClipped();
2659 info[jss::load_factor_fee_reference] =
2660 escalationMetrics.referenceFeeLevel.jsonClipped();
2664 info[jss::load_factor] =
2665 static_cast<double>(loadFactor) / loadBaseServer;
2667 if (loadFactorServer != loadFactor)
2668 info[jss::load_factor_server] =
2669 static_cast<double>(loadFactorServer) / loadBaseServer;
2674 if (fee != loadBaseServer)
2675 info[jss::load_factor_local] =
2676 static_cast<double>(fee) / loadBaseServer;
2678 if (fee != loadBaseServer)
2679 info[jss::load_factor_net] =
2680 static_cast<double>(fee) / loadBaseServer;
2682 if (fee != loadBaseServer)
2683 info[jss::load_factor_cluster] =
2684 static_cast<double>(fee) / loadBaseServer;
2686 if (escalationMetrics.openLedgerFeeLevel !=
2687 escalationMetrics.referenceFeeLevel &&
2688 (admin || loadFactorFeeEscalation != loadFactor))
2689 info[jss::load_factor_fee_escalation] =
2690 escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2691 escalationMetrics.referenceFeeLevel);
2692 if (escalationMetrics.minProcessingFeeLevel !=
2693 escalationMetrics.referenceFeeLevel)
2694 info[jss::load_factor_fee_queue] =
2695 escalationMetrics.minProcessingFeeLevel.decimalFromReference(
2696 escalationMetrics.referenceFeeLevel);
2709 XRPAmount const baseFee = lpClosed->fees().base;
2711 l[jss::seq] =
Json::UInt(lpClosed->info().seq);
2712 l[jss::hash] =
to_string(lpClosed->info().hash);
2717 l[jss::reserve_base] =
2718 lpClosed->fees().accountReserve(0).jsonClipped();
2719 l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2721 lpClosed->info().closeTime.time_since_epoch().count());
2726 l[jss::reserve_base_xrp] =
2727 lpClosed->fees().accountReserve(0).decimalXRP();
2728 l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2731 std::abs(closeOffset.count()) >= 60)
2732 l[jss::close_time_offset] =
2740 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2744 auto lCloseTime = lpClosed->info().closeTime;
2746 if (lCloseTime <= closeTime)
2748 using namespace std::chrono_literals;
2749 auto age = closeTime - lCloseTime;
2751 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2757 info[jss::validated_ledger] = l;
2759 info[jss::closed_ledger] = l;
2763 info[jss::published_ledger] =
"none";
2764 else if (lpPublished->info().seq != lpClosed->info().seq)
2765 info[jss::published_ledger] = lpPublished->info().seq;
2770 info[jss::jq_trans_overflow] =
2772 info[jss::peer_disconnects] =
2774 info[jss::peer_disconnects_resources] =
2779 "http",
"https",
"peer",
"ws",
"ws2",
"wss",
"wss2"};
2787 !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() &&
2788 port.admin_user.empty() && port.admin_password.empty()))
2802 for (
auto const& p : proto)
2803 jv[jss::protocol].append(p);
2810 auto const optPort = grpcSection.
get(
"port");
2811 if (optPort && grpcSection.get(
"ip"))
2814 jv[jss::port] = *optPort;
2816 jv[jss::protocol].append(
"grpc");
2819 info[jss::ports] = std::move(ports);
2844 transJson(transaction, result,
false, ledger, std::nullopt);
2858 [&](
Json::Value const& jv) { p->send(jv, true); });
2881 alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted,
app_);
2883 lpAccepted->info().hash, alpAccepted);
2887 alpAccepted->getLedger().
get() == lpAccepted.
get(),
2888 "ripple::NetworkOPsImp::pubLedger : accepted input");
2892 <<
"Publishing ledger " << lpAccepted->info().seq <<
" "
2893 << lpAccepted->info().hash;
2901 jvObj[jss::type] =
"ledgerClosed";
2902 jvObj[jss::ledger_index] = lpAccepted->info().seq;
2903 jvObj[jss::ledger_hash] =
to_string(lpAccepted->info().hash);
2905 lpAccepted->info().closeTime.time_since_epoch().count());
2907 if (!lpAccepted->rules().enabled(featureXRPFees))
2909 jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2910 jvObj[jss::reserve_base] =
2911 lpAccepted->fees().accountReserve(0).jsonClipped();
2912 jvObj[jss::reserve_inc] =
2913 lpAccepted->fees().increment.jsonClipped();
2915 jvObj[jss::txn_count] =
Json::UInt(alpAccepted->size());
2919 jvObj[jss::validated_ledgers] =
2929 p->send(jvObj,
true);
2947 p->send(jvObj,
true);
2956 static bool firstTime =
true;
2963 for (
auto& inner : outer.second)
2965 auto& subInfo = inner.second;
2966 if (subInfo.index_->separationLedgerSeq_ == 0)
2969 alpAccepted->getLedger(), subInfo);
2978 for (
auto const& accTx : *alpAccepted)
2982 lpAccepted, *accTx, accTx == *(--alpAccepted->end()));
3009 "reportConsensusStateChange->pubConsensus",
3040 jvObj[jss::type] =
"transaction";
3044 jvObj[jss::transaction] =
3051 jvObj[jss::meta], *ledger, transaction, meta->
get());
3053 jvObj[jss::meta], transaction, meta->
get());
3056 if (!ledger->open())
3057 jvObj[jss::ledger_hash] =
to_string(ledger->info().hash);
3061 jvObj[jss::ledger_index] = ledger->info().seq;
3062 jvObj[jss::transaction][jss::date] =
3063 ledger->info().closeTime.time_since_epoch().count();
3064 jvObj[jss::validated] =
true;
3065 jvObj[jss::close_time_iso] =
to_string_iso(ledger->info().closeTime);
3071 jvObj[jss::validated] =
false;
3072 jvObj[jss::ledger_current_index] = ledger->info().seq;
3075 jvObj[jss::status] = validated ?
"closed" :
"proposed";
3076 jvObj[jss::engine_result] = sToken;
3077 jvObj[jss::engine_result_code] = result;
3078 jvObj[jss::engine_result_message] = sHuman;
3080 if (transaction->getTxnType() == ttOFFER_CREATE)
3082 auto const account = transaction->getAccountID(sfAccount);
3083 auto const amount = transaction->getFieldAmount(sfTakerGets);
3086 if (account != amount.issue().account)
3094 jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3102 [&]<
unsigned Version>(
3104 RPC::insertDeliverMax(
3105 jvTx[jss::transaction], transaction->getTxnType(), Version);
3107 if constexpr (Version > 1)
3109 jvTx[jss::tx_json] = jvTx.removeMember(jss::transaction);
3110 jvTx[jss::hash] = hash;
3114 jvTx[jss::transaction][jss::hash] = hash;
3127 auto const& stTxn = transaction.
getTxn();
3131 auto const trResult = transaction.
getResult();
3146 [&](
Json::Value const& jv) { p->send(jv, true); });
3163 [&](
Json::Value const& jv) { p->send(jv, true); });
3188 auto const currLedgerSeq = ledger->seq();
3195 for (
auto const& affectedAccount : transaction.
getAffected())
3200 auto it = simiIt->second.begin();
3202 while (it != simiIt->second.end())
3213 it = simiIt->second.erase(it);
3220 auto it = simiIt->second.begin();
3221 while (it != simiIt->second.end())
3232 it = simiIt->second.erase(it);
3239 auto& subs = histoIt->second;
3240 auto it = subs.begin();
3241 while (it != subs.end())
3244 if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3258 it = subs.erase(it);
3269 <<
"pubAccountTransaction: " <<
"proposed=" << iProposed
3270 <<
", accepted=" << iAccepted;
3272 if (!notify.
empty() || !accountHistoryNotify.
empty())
3274 auto const& stTxn = transaction.
getTxn();
3278 auto const trResult = transaction.
getResult();
3284 isrListener->getApiVersion(),
3285 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3289 jvObj.
set(jss::account_history_boundary,
true);
3292 jvObj.
isMember(jss::account_history_tx_stream) ==
3294 "ripple::NetworkOPsImp::pubAccountTransaction : "
3295 "account_history_tx_stream not set");
3296 for (
auto& info : accountHistoryNotify)
3298 auto& index = info.index_;
3299 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3300 jvObj.
set(jss::account_history_tx_first,
true);
3302 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3305 info.sink_->getApiVersion(),
3306 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3331 for (
auto const& affectedAccount : tx->getMentionedAccounts())
3336 auto it = simiIt->second.begin();
3338 while (it != simiIt->second.end())
3349 it = simiIt->second.erase(it);
3356 JLOG(
m_journal.
trace()) <<
"pubProposedAccountTransaction: " << iProposed;
3358 if (!notify.
empty() || !accountHistoryNotify.
empty())
3365 isrListener->getApiVersion(),
3366 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3369 jvObj.
isMember(jss::account_history_tx_stream) ==
3371 "ripple::NetworkOPs::pubProposedAccountTransaction : "
3372 "account_history_tx_stream not set");
3373 for (
auto& info : accountHistoryNotify)
3375 auto& index = info.index_;
3376 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3377 jvObj.
set(jss::account_history_tx_first,
true);
3378 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3380 info.sink_->getApiVersion(),
3381 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3398 for (
auto const& naAccountID : vnaAccountIDs)
3401 <<
"subAccount: account: " <<
toBase58(naAccountID);
3403 isrListener->insertSubAccountInfo(naAccountID, rt);
3408 for (
auto const& naAccountID : vnaAccountIDs)
3410 auto simIterator = subMap.
find(naAccountID);
3411 if (simIterator == subMap.
end())
3415 usisElement[isrListener->getSeq()] = isrListener;
3417 subMap.
insert(simIterator, make_pair(naAccountID, usisElement));
3422 simIterator->second[isrListener->getSeq()] = isrListener;
3433 for (
auto const& naAccountID : vnaAccountIDs)
3436 isrListener->deleteSubAccountInfo(naAccountID, rt);
3453 for (
auto const& naAccountID : vnaAccountIDs)
3455 auto simIterator = subMap.
find(naAccountID);
3457 if (simIterator != subMap.
end())
3460 simIterator->second.erase(uSeq);
3462 if (simIterator->second.empty())
3465 subMap.
erase(simIterator);
3474 enum DatabaseType { Sqlite,
None };
3475 static const auto databaseType = [&]() -> DatabaseType {
3480 return DatabaseType::Sqlite;
3482 return DatabaseType::None;
3485 if (databaseType == DatabaseType::None)
3488 <<
"AccountHistory job for account "
3500 "AccountHistoryTxStream",
3501 [
this, dbType = databaseType, subInfo]() {
3502 auto const& accountId = subInfo.
index_->accountId_;
3503 auto& lastLedgerSeq = subInfo.
index_->historyLastLedgerSeq_;
3504 auto& txHistoryIndex = subInfo.
index_->historyTxIndex_;
3507 <<
"AccountHistory job for account " <<
toBase58(accountId)
3508 <<
" started. lastLedgerSeq=" << lastLedgerSeq;
3518 auto stx = tx->getSTransaction();
3519 if (stx->getAccountID(sfAccount) == accountId &&
3520 stx->getSeqProxy().value() == 1)
3524 for (
auto& node : meta->getNodes())
3526 if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3529 if (node.isFieldPresent(sfNewFields))
3531 if (
auto inner =
dynamic_cast<const STObject*
>(
3532 node.peekAtPField(sfNewFields));
3535 if (inner->isFieldPresent(sfAccount) &&
3536 inner->getAccountID(sfAccount) == accountId)
3548 bool unsubscribe) ->
bool {
3551 sptr->send(jvObj,
true);
3561 bool unsubscribe) ->
bool {
3565 sptr->getApiVersion(),
3566 [&](
Json::Value const& jv) { sptr->send(jv,
true); });
3589 accountId, minLedger, maxLedger, marker, 0,
true};
3590 return db->newestAccountTxPage(options);
3594 "ripple::NetworkOPsImp::addAccountHistoryJob::"
3595 "getMoreTxns : invalid database type");
3604 while (lastLedgerSeq >= 2 && !subInfo.
index_->stopHistorical_)
3606 int feeChargeCount = 0;
3615 <<
"AccountHistory job for account "
3616 <<
toBase58(accountId) <<
" no InfoSub. Fee charged "
3617 << feeChargeCount <<
" times.";
3622 auto startLedgerSeq =
3623 (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3625 <<
"AccountHistory job for account " <<
toBase58(accountId)
3626 <<
", working on ledger range [" << startLedgerSeq <<
","
3627 << lastLedgerSeq <<
"]";
3629 auto haveRange = [&]() ->
bool {
3632 auto haveSomeValidatedLedgers =
3634 validatedMin, validatedMax);
3636 return haveSomeValidatedLedgers &&
3637 validatedMin <= startLedgerSeq &&
3638 lastLedgerSeq <= validatedMax;
3644 <<
"AccountHistory reschedule job for account "
3645 <<
toBase58(accountId) <<
", incomplete ledger range ["
3646 << startLedgerSeq <<
"," << lastLedgerSeq <<
"]";
3652 while (!subInfo.
index_->stopHistorical_)
3655 getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3659 <<
"AccountHistory job for account "
3660 <<
toBase58(accountId) <<
" getMoreTxns failed.";
3665 auto const& txns = dbResult->first;
3666 marker = dbResult->second;
3667 size_t num_txns = txns.size();
3668 for (
size_t i = 0; i < num_txns; ++i)
3670 auto const& [tx, meta] = txns[i];
3675 <<
"AccountHistory job for account "
3676 <<
toBase58(accountId) <<
" empty tx or meta.";
3686 <<
"AccountHistory job for account "
3687 <<
toBase58(accountId) <<
" no ledger.";
3692 tx->getSTransaction();
3696 <<
"AccountHistory job for account "
3698 <<
" getSTransaction failed.";
3704 auto const trR = meta->getResultTER();
3706 transJson(stTxn, trR,
true, curTxLedger, mRef);
3709 jss::account_history_tx_index, txHistoryIndex--);
3710 if (i + 1 == num_txns ||
3711 txns[i + 1].first->getLedger() != tx->getLedger())
3712 jvTx.
set(jss::account_history_boundary,
true);
3714 if (isFirstTx(tx, meta))
3716 jvTx.
set(jss::account_history_tx_first,
true);
3717 sendMultiApiJson(jvTx,
false);
3720 <<
"AccountHistory job for account "
3722 <<
" done, found last tx.";
3727 sendMultiApiJson(jvTx,
false);
3734 <<
"AccountHistory job for account "
3736 <<
" paging, marker=" << marker->ledgerSeq <<
":"
3745 if (!subInfo.
index_->stopHistorical_)
3747 lastLedgerSeq = startLedgerSeq - 1;
3748 if (lastLedgerSeq <= 1)
3751 <<
"AccountHistory job for account "
3753 <<
" done, reached genesis ledger.";
3766 subInfo.
index_->separationLedgerSeq_ = ledger->seq();
3767 auto const& accountId = subInfo.
index_->accountId_;
3769 if (!ledger->exists(accountKeylet))
3772 <<
"subAccountHistoryStart, no account " <<
toBase58(accountId)
3773 <<
", no need to add AccountHistory job.";
3778 if (
auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3780 if (sleAcct->getFieldU32(sfSequence) == 1)
3783 <<
"subAccountHistoryStart, genesis account "
3785 <<
" does not have tx, no need to add AccountHistory job.";
3792 "ripple::NetworkOPsImp::subAccountHistoryStart : failed to "
3793 "access genesis account");
3797 subInfo.
index_->historyLastLedgerSeq_ = ledger->seq();
3798 subInfo.
index_->haveHistorical_ =
true;
3801 <<
"subAccountHistoryStart, add AccountHistory job: accountId="
3802 <<
toBase58(accountId) <<
", currentLedgerSeq=" << ledger->seq();
3812 if (!isrListener->insertSubAccountHistory(accountId))
3815 <<
"subAccountHistory, already subscribed to account "
3822 isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3827 inner.
emplace(isrListener->getSeq(), ahi);
3833 simIterator->second.emplace(isrListener->getSeq(), ahi);
3847 <<
"subAccountHistory, no validated ledger yet, delay start";
3860 isrListener->deleteSubAccountHistory(account);
3874 auto& subInfoMap = simIterator->second;
3875 auto subInfoIter = subInfoMap.find(seq);
3876 if (subInfoIter != subInfoMap.end())
3878 subInfoIter->second.index_->stopHistorical_ =
true;
3883 simIterator->second.erase(seq);
3884 if (simIterator->second.empty())
3890 <<
"unsubAccountHistory, account " <<
toBase58(account)
3891 <<
", historyOnly = " << (historyOnly ?
"true" :
"false");
3899 listeners->addSubscriber(isrListener);
3901 UNREACHABLE(
"ripple::NetworkOPsImp::subBook : null book listeners");
3909 listeners->removeSubscriber(uSeq);
3921 m_standalone,
"ripple::NetworkOPsImp::acceptLedger : is standalone");
3924 Throw<std::runtime_error>(
3925 "Operation only possible in STANDALONE mode.");
3940 jvResult[jss::ledger_index] = lpClosed->info().seq;
3941 jvResult[jss::ledger_hash] =
to_string(lpClosed->info().hash);
3943 lpClosed->info().closeTime.time_since_epoch().count());
3944 if (!lpClosed->rules().enabled(featureXRPFees))
3946 jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
3947 jvResult[jss::reserve_base] =
3948 lpClosed->fees().accountReserve(0).jsonClipped();
3949 jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
3954 jvResult[jss::validated_ledgers] =
3960 .emplace(isrListener->getSeq(), isrListener)
3970 .emplace(isrListener->getSeq(), isrListener)
3996 .emplace(isrListener->getSeq(), isrListener)
4024 jvResult[jss::random] =
to_string(uRandom);
4026 jvResult[jss::load_base] = feeTrack.getLoadBase();
4027 jvResult[jss::load_factor] = feeTrack.getLoadFactor();
4028 jvResult[jss::hostid] =
getHostId(admin);
4029 jvResult[jss::pubkey_node] =
4034 .emplace(isrListener->getSeq(), isrListener)
4052 .emplace(isrListener->getSeq(), isrListener)
4070 .emplace(isrListener->getSeq(), isrListener)
4088 .emplace(isrListener->getSeq(), isrListener)
4112 .emplace(isrListener->getSeq(), isrListener)
4130 .emplace(isrListener->getSeq(), isrListener)
4178 if (map.find(pInfo->getSeq()) != map.end())
4185#ifndef USE_NEW_BOOK_PAGE
4196 unsigned int iLimit,
4206 uint256 uTipIndex = uBookBase;
4210 stream <<
"getBookPage:" << book;
4211 stream <<
"getBookPage: uBookBase=" << uBookBase;
4212 stream <<
"getBookPage: uBookEnd=" << uBookEnd;
4213 stream <<
"getBookPage: uTipIndex=" << uTipIndex;
4222 bool bDirectAdvance =
true;
4226 unsigned int uBookEntry;
4232 while (!bDone && iLimit-- > 0)
4236 bDirectAdvance =
false;
4240 auto const ledgerIndex = view.
succ(uTipIndex, uBookEnd);
4244 sleOfferDir.
reset();
4253 uTipIndex = sleOfferDir->key();
4256 cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4259 <<
"getBookPage: uTipIndex=" << uTipIndex;
4261 <<
"getBookPage: offerIndex=" << offerIndex;
4271 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4272 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4273 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4275 bool firstOwnerOffer(
true);
4281 saOwnerFunds = saTakerGets;
4283 else if (bGlobalFreeze)
4291 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4292 if (umBalanceEntry != umBalance.
end())
4296 saOwnerFunds = umBalanceEntry->second;
4297 firstOwnerOffer =
false;
4311 if (saOwnerFunds < beast::zero)
4315 saOwnerFunds.
clear();
4323 STAmount saOwnerFundsLimit = saOwnerFunds;
4335 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4338 if (saOwnerFundsLimit >= saTakerGets)
4341 saTakerGetsFunded = saTakerGets;
4347 saTakerGetsFunded = saOwnerFundsLimit;
4349 saTakerGetsFunded.
setJson(jvOffer[jss::taker_gets_funded]);
4353 saTakerGetsFunded, saDirRate, saTakerPays.
issue()))
4354 .setJson(jvOffer[jss::taker_pays_funded]);
4360 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4362 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4366 jvOf[jss::quality] = saDirRate.
getText();
4368 if (firstOwnerOffer)
4369 jvOf[jss::owner_funds] = saOwnerFunds.
getText();
4376 if (!
cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4378 bDirectAdvance =
true;
4383 <<
"getBookPage: offerIndex=" << offerIndex;
4403 unsigned int iLimit,
4411 MetaView lesActive(lpLedger,
tapNONE,
true);
4412 OrderBookIterator obIterator(lesActive, book);
4416 const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.
out.
account) ||
4417 lesActive.isGlobalFrozen(book.
in.
account);
4419 while (iLimit-- > 0 && obIterator.nextOffer())
4424 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4425 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4426 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4427 STAmount saDirRate = obIterator.getCurrentRate();
4433 saOwnerFunds = saTakerGets;
4435 else if (bGlobalFreeze)
4443 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4445 if (umBalanceEntry != umBalance.
end())
4449 saOwnerFunds = umBalanceEntry->second;
4455 saOwnerFunds = lesActive.accountHolds(
4461 if (saOwnerFunds.isNegative())
4465 saOwnerFunds.zero();
4472 STAmount saTakerGetsFunded;
4473 STAmount saOwnerFundsLimit = saOwnerFunds;
4485 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4488 if (saOwnerFundsLimit >= saTakerGets)
4491 saTakerGetsFunded = saTakerGets;
4496 saTakerGetsFunded = saOwnerFundsLimit;
4498 saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4504 multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4505 .setJson(jvOffer[jss::taker_pays_funded]);
4508 STAmount saOwnerPays = (
parityRate == offerRate)
4511 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4513 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4515 if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4519 jvOf[jss::quality] = saDirRate.
getText();
4534 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4574 ++counters_[
static_cast<std::size_t>(om)].transitions;
4576 counters_[
static_cast<std::size_t>(om)].transitions == 1)
4578 initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4579 now - processStart_)
4583 std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4592 auto [counters, mode, start, initialSync] = getCounterData();
4593 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4603 auto& state = obj[jss::state_accounting][
states_[i]];
4604 state[jss::transitions] =
std::to_string(counters[i].transitions);
4605 state[jss::duration_us] =
std::to_string(counters[i].dur.count());
4609 obj[jss::initial_sync_duration_us] =
std::to_string(initialSync);
4624 boost::asio::io_service& io_svc,
4628 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 resetDeadlockDetector()
Reset the deadlock 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)