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>
52#include <xrpl/basics/UptimeClock.h>
53#include <xrpl/basics/mulDiv.h>
54#include <xrpl/basics/safe_cast.h>
55#include <xrpl/basics/scope.h>
56#include <xrpl/beast/utility/rngfill.h>
57#include <xrpl/crypto/RFC1751.h>
58#include <xrpl/crypto/csprng.h>
59#include <xrpl/protocol/BuildInfo.h>
60#include <xrpl/protocol/Feature.h>
61#include <xrpl/protocol/MultiApiJson.h>
62#include <xrpl/protocol/RPCErr.h>
63#include <xrpl/protocol/jss.h>
64#include <xrpl/resource/Fees.h>
65#include <xrpl/resource/ResourceManager.h>
67#include <boost/asio/ip/host_name.hpp>
68#include <boost/asio/steady_timer.hpp>
107 "ripple::NetworkOPsImp::TransactionStatus::TransactionStatus : "
150 std::chrono::steady_clock::time_point
start_ =
211 return !(*
this != b);
230 boost::asio::io_service& io_svc,
244 app_.logs().journal(
"FeeVote")),
247 app.getInboundTransactions(),
248 beast::get_abstract_clock<
std::chrono::steady_clock>(),
250 app_.logs().journal(
"LedgerConsensus"))
431 getServerInfo(
bool human,
bool admin,
bool counters)
override;
458 TER result)
override;
492 bool historyOnly)
override;
498 bool historyOnly)
override;
566 boost::system::error_code ec;
571 <<
"NetworkOPs: heartbeatTimer cancel error: "
580 <<
"NetworkOPs: clusterTimer cancel error: "
589 <<
"NetworkOPs: accountHistoryTxTimer cancel error: "
594 using namespace std::chrono_literals;
604 boost::asio::steady_timer& timer,
784 template <
class Handler>
786 Handler
const& handler,
788 :
hook(collector->make_hook(handler))
791 "Disconnected_duration"))
794 "Connected_duration"))
796 collector->make_gauge(
"State_Accounting",
"Syncing_duration"))
799 "Tracking_duration"))
801 collector->make_gauge(
"State_Accounting",
"Full_duration"))
804 "Disconnected_transitions"))
807 "Connected_transitions"))
810 "Syncing_transitions"))
813 "Tracking_transitions"))
815 collector->make_gauge(
"State_Accounting",
"Full_transitions"))
844 {
"disconnected",
"connected",
"syncing",
"tracking",
"full"}};
906 static std::string const hostname = boost::asio::ip::host_name();
913 static std::string const shroudedHostId = [
this]() {
919 return shroudedHostId;
934 boost::asio::steady_timer& timer,
941 [
this, onExpire, onError](boost::system::error_code
const& e) {
942 if ((e.value() == boost::system::errc::success) &&
943 (!m_job_queue.isStopped()))
948 if (e.value() != boost::system::errc::success &&
949 e.value() != boost::asio::error::operation_aborted)
952 JLOG(m_journal.error())
953 <<
"Timer got error '" << e.message()
954 <<
"'. Restarting timer.";
959 timer.expires_from_now(expiry_time);
960 timer.async_wait(std::move(*optionalCountedHandler));
965NetworkOPsImp::setHeartbeatTimer()
969 mConsensus.parms().ledgerGRANULARITY,
971 m_job_queue.addJob(jtNETOP_TIMER,
"NetOPs.heartbeat", [this]() {
972 processHeartbeatTimer();
975 [
this]() { setHeartbeatTimer(); });
979NetworkOPsImp::setClusterTimer()
981 using namespace std::chrono_literals;
988 processClusterTimer();
991 [
this]() { setClusterTimer(); });
997 JLOG(m_journal.debug()) <<
"Scheduling AccountHistory job for account "
999 using namespace std::chrono_literals;
1001 accountHistoryTxTimer_,
1003 [
this, subInfo]() { addAccountHistoryJob(subInfo); },
1004 [
this, subInfo]() { setAccountHistoryJobTimer(subInfo); });
1008NetworkOPsImp::processHeartbeatTimer()
1011 "Heartbeat Timer", mConsensus.validating(), m_journal);
1019 std::size_t const numPeers = app_.overlay().size();
1022 if (numPeers < minPeerCount_)
1024 if (mMode != OperatingMode::DISCONNECTED)
1026 setMode(OperatingMode::DISCONNECTED);
1028 ss <<
"Node count (" << numPeers <<
") has fallen "
1029 <<
"below required minimum (" << minPeerCount_ <<
").";
1030 JLOG(m_journal.warn()) << ss.
str();
1031 CLOG(clog.
ss()) <<
"set mode to DISCONNECTED: " << ss.
str();
1036 <<
"already DISCONNECTED. too few peers (" << numPeers
1037 <<
"), need at least " << minPeerCount_;
1044 setHeartbeatTimer();
1049 if (mMode == OperatingMode::DISCONNECTED)
1051 setMode(OperatingMode::CONNECTED);
1052 JLOG(m_journal.info())
1053 <<
"Node count (" << numPeers <<
") is sufficient.";
1054 CLOG(clog.
ss()) <<
"setting mode to CONNECTED based on " << numPeers
1060 auto origMode = mMode.load();
1061 CLOG(clog.
ss()) <<
"mode: " << strOperatingMode(origMode,
true);
1062 if (mMode == OperatingMode::SYNCING)
1063 setMode(OperatingMode::SYNCING);
1064 else if (mMode == OperatingMode::CONNECTED)
1065 setMode(OperatingMode::CONNECTED);
1066 auto newMode = mMode.load();
1067 if (origMode != newMode)
1070 <<
", changing to " << strOperatingMode(newMode,
true);
1072 CLOG(clog.
ss()) <<
". ";
1075 mConsensus.timerEntry(app_.timeKeeper().closeTime(), clog.
ss());
1077 CLOG(clog.
ss()) <<
"consensus phase " << to_string(mLastConsensusPhase);
1079 if (mLastConsensusPhase != currPhase)
1081 reportConsensusStateChange(currPhase);
1082 mLastConsensusPhase = currPhase;
1083 CLOG(clog.
ss()) <<
" changed to " << to_string(mLastConsensusPhase);
1085 CLOG(clog.
ss()) <<
". ";
1087 setHeartbeatTimer();
1091NetworkOPsImp::processClusterTimer()
1093 if (app_.cluster().size() == 0)
1096 using namespace std::chrono_literals;
1098 bool const update = app_.cluster().update(
1099 app_.nodeIdentity().first,
1101 (m_ledgerMaster.getValidatedLedgerAge() <= 4min)
1102 ? app_.getFeeTrack().getLocalFee()
1104 app_.timeKeeper().now());
1108 JLOG(m_journal.debug()) <<
"Too soon to send cluster update";
1113 protocol::TMCluster cluster;
1114 app_.cluster().for_each([&cluster](
ClusterNode const& node) {
1115 protocol::TMClusterNode& n = *cluster.add_clusternodes();
1120 n.set_nodename(node.
name());
1124 for (
auto& item : gossip.
items)
1126 protocol::TMLoadSource& node = *cluster.add_loadsources();
1127 node.set_name(to_string(item.address));
1128 node.set_cost(item.balance);
1130 app_.overlay().foreach(
send_if(
1131 std::make_shared<Message>(cluster, protocol::mtCLUSTER),
1142 if (mode == OperatingMode::FULL && admin)
1144 auto const consensusMode = mConsensus.mode();
1145 if (consensusMode != ConsensusMode::wrongLedger)
1147 if (consensusMode == ConsensusMode::proposing)
1150 if (mConsensus.validating())
1151 return "validating";
1161 if (isNeedNetworkLedger())
1170 auto const txid = trans->getTransactionID();
1171 auto const flags = app_.getHashRouter().getFlags(txid);
1173 if ((flags & SF_BAD) != 0)
1175 JLOG(m_journal.warn()) <<
"Submitted transaction cached bad";
1182 app_.getHashRouter(),
1184 m_ledgerMaster.getValidatedRules(),
1187 if (validity != Validity::Valid)
1189 JLOG(m_journal.warn())
1190 <<
"Submitted transaction invalid: " << reason;
1196 JLOG(m_journal.warn())
1197 <<
"Exception checking transaction " << txid <<
": " << ex.
what();
1204 auto tx = std::make_shared<Transaction>(trans, reason, app_);
1206 m_job_queue.addJob(
jtTRANSACTION,
"submitTxn", [
this, tx]() {
1208 processTransaction(t,
false,
false, FailHard::no);
1213NetworkOPsImp::processTransaction(
1219 auto ev = m_job_queue.makeLoadEvent(
jtTXN_PROC,
"ProcessTXN");
1220 auto const newFlags = app_.getHashRouter().getFlags(transaction->getID());
1222 if ((newFlags & SF_BAD) != 0)
1225 JLOG(m_journal.warn()) << transaction->getID() <<
": cached bad!\n";
1226 transaction->setStatus(
INVALID);
1234 auto const view = m_ledgerMaster.getCurrentLedger();
1236 app_.getHashRouter(),
1237 *transaction->getSTransaction(),
1241 validity == Validity::Valid,
1242 "ripple::NetworkOPsImp::processTransaction : valid validity");
1245 if (validity == Validity::SigBad)
1247 JLOG(m_journal.info()) <<
"Transaction has bad signature: " << reason;
1248 transaction->setStatus(
INVALID);
1250 app_.getHashRouter().setFlags(transaction->getID(), SF_BAD);
1255 app_.getMasterTransaction().canonicalize(&transaction);
1258 doTransactionSync(transaction, bUnlimited, failType);
1260 doTransactionAsync(transaction, bUnlimited, failType);
1264NetworkOPsImp::doTransactionAsync(
1271 if (transaction->getApplying())
1274 mTransactions.push_back(
1276 transaction->setApplying();
1278 if (mDispatchState == DispatchState::none)
1280 if (m_job_queue.addJob(
1281 jtBATCH,
"transactionBatch", [
this]() { transactionBatch(); }))
1283 mDispatchState = DispatchState::scheduled;
1289NetworkOPsImp::doTransactionSync(
1296 if (!transaction->getApplying())
1298 mTransactions.push_back(
1300 transaction->setApplying();
1305 if (mDispatchState == DispatchState::running)
1314 if (mTransactions.size())
1317 if (m_job_queue.addJob(
jtBATCH,
"transactionBatch", [
this]() {
1321 mDispatchState = DispatchState::scheduled;
1325 }
while (transaction->getApplying());
1329NetworkOPsImp::transactionBatch()
1333 if (mDispatchState == DispatchState::running)
1336 while (mTransactions.size())
1347 mTransactions.
swap(transactions);
1349 !transactions.
empty(),
1350 "ripple::NetworkOPsImp::apply : non-empty transactions");
1352 mDispatchState != DispatchState::running,
1353 "ripple::NetworkOPsImp::apply : is not running");
1355 mDispatchState = DispatchState::running;
1361 bool changed =
false;
1364 m_ledgerMaster.peekMutex(), std::defer_lock};
1375 if (e.failType == FailHard::yes)
1378 auto const result = app_.getTxQ().apply(
1379 app_, view, e.transaction->getSTransaction(), flags, j);
1380 e.result = result.ter;
1381 e.applied = result.applied;
1382 changed = changed || result.applied;
1391 if (
auto const l = m_ledgerMaster.getValidatedLedger())
1392 validatedLedgerIndex = l->info().seq;
1394 auto newOL = app_.openLedger().current();
1397 e.transaction->clearSubmitResult();
1401 pubProposedTransaction(
1402 newOL, e.transaction->getSTransaction(), e.result);
1403 e.transaction->setApplied();
1406 e.transaction->setResult(e.result);
1409 app_.getHashRouter().setFlags(e.transaction->getID(), SF_BAD);
1418 JLOG(m_journal.info())
1419 <<
"TransactionResult: " << token <<
": " << human;
1424 bool addLocal = e.local;
1428 JLOG(m_journal.debug())
1429 <<
"Transaction is now included in open ledger";
1430 e.transaction->setStatus(
INCLUDED);
1432 auto const& txCur = e.transaction->getSTransaction();
1433 auto const txNext = m_ledgerMaster.popAcctTransaction(txCur);
1438 auto t = std::make_shared<Transaction>(trans, reason, app_);
1439 submit_held.
emplace_back(t,
false,
false, FailHard::no);
1446 JLOG(m_journal.info()) <<
"Transaction is obsolete";
1447 e.transaction->setStatus(
OBSOLETE);
1451 JLOG(m_journal.debug())
1452 <<
"Transaction is likely to claim a"
1453 <<
" fee, but is queued until fee drops";
1455 e.transaction->setStatus(
HELD);
1459 m_ledgerMaster.addHeldTransaction(e.transaction);
1460 e.transaction->setQueued();
1461 e.transaction->setKept();
1465 if (e.failType != FailHard::yes)
1468 JLOG(m_journal.debug())
1469 <<
"Transaction should be held: " << e.result;
1470 e.transaction->setStatus(
HELD);
1471 m_ledgerMaster.addHeldTransaction(e.transaction);
1472 e.transaction->setKept();
1477 JLOG(m_journal.debug())
1478 <<
"Status other than success " << e.result;
1479 e.transaction->setStatus(
INVALID);
1482 auto const enforceFailHard =
1483 e.failType == FailHard::yes && !
isTesSuccess(e.result);
1485 if (addLocal && !enforceFailHard)
1487 m_localTX->push_back(
1488 m_ledgerMaster.getCurrentLedgerIndex(),
1489 e.transaction->getSTransaction());
1490 e.transaction->setKept();
1494 ((mMode != OperatingMode::FULL) &&
1495 (e.failType != FailHard::yes) && e.local) ||
1500 app_.getHashRouter().shouldRelay(e.transaction->getID());
1504 protocol::TMTransaction tx;
1507 e.transaction->getSTransaction()->add(s);
1508 tx.set_rawtransaction(s.
data(), s.
size());
1509 tx.set_status(protocol::tsCURRENT);
1510 tx.set_receivetimestamp(
1511 app_.timeKeeper().now().time_since_epoch().count());
1514 app_.overlay().relay(e.transaction->getID(), tx, *toSkip);
1515 e.transaction->setBroadcast();
1519 if (validatedLedgerIndex)
1521 auto [fee, accountSeq, availableSeq] =
1522 app_.getTxQ().getTxRequiredFeeAndSeq(
1523 *newOL, e.transaction->getSTransaction());
1524 e.transaction->setCurrentLedgerState(
1525 *validatedLedgerIndex, fee, accountSeq, availableSeq);
1533 e.transaction->clearApplying();
1535 if (!submit_held.
empty())
1537 if (mTransactions.empty())
1538 mTransactions.swap(submit_held);
1540 for (
auto& e : submit_held)
1541 mTransactions.push_back(std::move(e));
1546 mDispatchState = DispatchState::none;
1554NetworkOPsImp::getOwnerInfo(
1559 auto root = keylet::ownerDir(account);
1560 auto sleNode = lpLedger->read(keylet::page(
root));
1567 for (
auto const& uDirEntry : sleNode->getFieldV256(sfIndexes))
1569 auto sleCur = lpLedger->read(keylet::child(uDirEntry));
1572 "ripple::NetworkOPsImp::getOwnerInfo : non-null child SLE");
1574 switch (sleCur->getType())
1577 if (!jvObjects.
isMember(jss::offers))
1578 jvObjects[jss::offers] =
1581 jvObjects[jss::offers].
append(
1582 sleCur->getJson(JsonOptions::none));
1585 case ltRIPPLE_STATE:
1586 if (!jvObjects.
isMember(jss::ripple_lines))
1588 jvObjects[jss::ripple_lines] =
1592 jvObjects[jss::ripple_lines].
append(
1593 sleCur->getJson(JsonOptions::none));
1596 case ltACCOUNT_ROOT:
1600 "ripple::NetworkOPsImp::getOwnerInfo : invalid "
1606 uNodeDir = sleNode->getFieldU64(sfIndexNext);
1610 sleNode = lpLedger->read(keylet::page(
root, uNodeDir));
1613 "ripple::NetworkOPsImp::getOwnerInfo : read next page");
1626NetworkOPsImp::isBlocked()
1628 return isAmendmentBlocked() || isUNLBlocked();
1632NetworkOPsImp::isAmendmentBlocked()
1634 return amendmentBlocked_;
1638NetworkOPsImp::setAmendmentBlocked()
1640 amendmentBlocked_ =
true;
1641 setMode(OperatingMode::CONNECTED);
1645NetworkOPsImp::isAmendmentWarned()
1647 return !amendmentBlocked_ && amendmentWarned_;
1651NetworkOPsImp::setAmendmentWarned()
1653 amendmentWarned_ =
true;
1657NetworkOPsImp::clearAmendmentWarned()
1659 amendmentWarned_ =
false;
1663NetworkOPsImp::isUNLBlocked()
1669NetworkOPsImp::setUNLBlocked()
1672 setMode(OperatingMode::CONNECTED);
1676NetworkOPsImp::clearUNLBlocked()
1678 unlBlocked_ =
false;
1682NetworkOPsImp::checkLastClosedLedger(
1691 JLOG(m_journal.trace()) <<
"NetworkOPsImp::checkLastClosedLedger";
1693 auto const ourClosed = m_ledgerMaster.getClosedLedger();
1698 uint256 closedLedger = ourClosed->info().hash;
1699 uint256 prevClosedLedger = ourClosed->info().parentHash;
1700 JLOG(m_journal.trace()) <<
"OurClosed: " << closedLedger;
1701 JLOG(m_journal.trace()) <<
"PrevClosed: " << prevClosedLedger;
1706 auto& validations = app_.getValidations();
1707 JLOG(m_journal.debug())
1708 <<
"ValidationTrie " <<
Json::Compact(validations.getJsonTrie());
1712 peerCounts[closedLedger] = 0;
1713 if (mMode >= OperatingMode::TRACKING)
1714 peerCounts[closedLedger]++;
1716 for (
auto& peer : peerList)
1718 uint256 peerLedger = peer->getClosedLedgerHash();
1721 ++peerCounts[peerLedger];
1724 for (
auto const& it : peerCounts)
1725 JLOG(m_journal.debug()) <<
"L: " << it.first <<
" n=" << it.second;
1727 uint256 preferredLCL = validations.getPreferredLCL(
1729 m_ledgerMaster.getValidLedgerIndex(),
1732 bool switchLedgers = preferredLCL != closedLedger;
1734 closedLedger = preferredLCL;
1736 if (switchLedgers && (closedLedger == prevClosedLedger))
1739 JLOG(m_journal.info()) <<
"We won't switch to our own previous ledger";
1740 networkClosed = ourClosed->info().hash;
1741 switchLedgers =
false;
1744 networkClosed = closedLedger;
1749 auto consensus = m_ledgerMaster.getLedgerByHash(closedLedger);
1752 consensus = app_.getInboundLedgers().acquire(
1753 closedLedger, 0, InboundLedger::Reason::CONSENSUS);
1756 (!m_ledgerMaster.canBeCurrent(consensus) ||
1757 !m_ledgerMaster.isCompatible(
1758 *consensus, m_journal.debug(),
"Not switching")))
1762 networkClosed = ourClosed->info().hash;
1766 JLOG(m_journal.warn()) <<
"We are not running on the consensus ledger";
1767 JLOG(m_journal.info()) <<
"Our LCL: " << ourClosed->info().hash
1769 JLOG(m_journal.info()) <<
"Net LCL " << closedLedger;
1771 if ((mMode == OperatingMode::TRACKING) || (mMode == OperatingMode::FULL))
1773 setMode(OperatingMode::CONNECTED);
1781 switchLastClosedLedger(consensus);
1788NetworkOPsImp::switchLastClosedLedger(
1792 JLOG(m_journal.error())
1793 <<
"JUMP last closed ledger to " << newLCL->info().hash;
1795 clearNeedNetworkLedger();
1798 app_.getTxQ().processClosedLedger(app_, *newLCL,
true);
1805 auto retries = m_localTX->getTxSet();
1806 auto const lastVal = app_.getLedgerMaster().getValidatedLedger();
1811 rules.
emplace(app_.config().features);
1812 app_.openLedger().accept(
1823 return app_.getTxQ().accept(app_, view);
1827 m_ledgerMaster.switchLCL(newLCL);
1829 protocol::TMStatusChange s;
1830 s.set_newevent(protocol::neSWITCHED_LEDGER);
1831 s.set_ledgerseq(newLCL->info().seq);
1832 s.set_networktime(app_.timeKeeper().now().time_since_epoch().count());
1833 s.set_ledgerhashprevious(
1834 newLCL->info().parentHash.begin(), newLCL->info().parentHash.size());
1835 s.set_ledgerhash(newLCL->info().hash.begin(), newLCL->info().hash.size());
1837 app_.overlay().foreach(
1838 send_always(std::make_shared<Message>(s, protocol::mtSTATUS_CHANGE)));
1842NetworkOPsImp::beginConsensus(
1848 "ripple::NetworkOPsImp::beginConsensus : nonzero input");
1850 auto closingInfo = m_ledgerMaster.getCurrentLedger()->info();
1852 JLOG(m_journal.info()) <<
"Consensus time for #" << closingInfo.seq
1853 <<
" with LCL " << closingInfo.parentHash;
1855 auto prevLedger = m_ledgerMaster.getLedgerByHash(closingInfo.parentHash);
1860 if (mMode == OperatingMode::FULL)
1862 JLOG(m_journal.warn()) <<
"Don't have LCL, going to tracking";
1863 setMode(OperatingMode::TRACKING);
1864 CLOG(clog) <<
"beginConsensus Don't have LCL, going to tracking. ";
1867 CLOG(clog) <<
"beginConsensus no previous ledger. ";
1872 prevLedger->info().hash == closingInfo.parentHash,
1873 "ripple::NetworkOPsImp::beginConsensus : prevLedger hash matches "
1876 closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->info().hash,
1877 "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches "
1880 if (prevLedger->rules().enabled(featureNegativeUNL))
1881 app_.validators().setNegativeUNL(prevLedger->negativeUNL());
1882 TrustChanges const changes = app_.validators().updateTrusted(
1883 app_.getValidations().getCurrentNodeIDs(),
1884 closingInfo.parentCloseTime,
1887 app_.getHashRouter());
1889 if (!changes.
added.empty() || !changes.
removed.empty())
1891 app_.getValidations().trustChanged(changes.
added, changes.
removed);
1893 app_.getAmendmentTable().trustChanged(
1894 app_.validators().getQuorumKeys().second);
1897 mConsensus.startRound(
1898 app_.timeKeeper().closeTime(),
1906 if (mLastConsensusPhase != currPhase)
1908 reportConsensusStateChange(currPhase);
1909 mLastConsensusPhase = currPhase;
1912 JLOG(m_journal.debug()) <<
"Initiating consensus engine";
1919 return mConsensus.peerProposal(app_.timeKeeper().closeTime(), peerPos);
1930 protocol::TMHaveTransactionSet msg;
1931 msg.set_hash(map->getHash().as_uint256().begin(), 256 / 8);
1932 msg.set_status(protocol::tsHAVE);
1933 app_.overlay().foreach(
1934 send_always(std::make_shared<Message>(msg, protocol::mtHAVE_SET)));
1938 mConsensus.gotTxSet(app_.timeKeeper().closeTime(),
RCLTxSet{map});
1944 uint256 deadLedger = m_ledgerMaster.getClosedLedger()->info().parentHash;
1946 for (
auto const& it : app_.overlay().getActivePeers())
1948 if (it && (it->getClosedLedgerHash() == deadLedger))
1950 JLOG(m_journal.trace()) <<
"Killing obsolete peer status";
1957 checkLastClosedLedger(app_.overlay().getActivePeers(), networkClosed);
1959 if (networkClosed.
isZero())
1961 CLOG(clog) <<
"endConsensus last closed ledger is zero. ";
1971 if (((mMode == OperatingMode::CONNECTED) ||
1972 (mMode == OperatingMode::SYNCING)) &&
1978 if (!needNetworkLedger_)
1979 setMode(OperatingMode::TRACKING);
1982 if (((mMode == OperatingMode::CONNECTED) ||
1983 (mMode == OperatingMode::TRACKING)) &&
1989 auto current = m_ledgerMaster.getCurrentLedger();
1990 if (app_.timeKeeper().now() < (
current->info().parentCloseTime +
1991 2 *
current->info().closeTimeResolution))
1993 setMode(OperatingMode::FULL);
1997 beginConsensus(networkClosed, clog);
2001NetworkOPsImp::consensusViewChange()
2003 if ((mMode == OperatingMode::FULL) || (mMode == OperatingMode::TRACKING))
2005 setMode(OperatingMode::CONNECTED);
2015 if (!mStreamMaps[sManifests].empty())
2019 jvObj[jss::type] =
"manifestReceived";
2022 jvObj[jss::signing_key] =
2026 jvObj[jss::signature] =
strHex(*sig);
2029 jvObj[jss::domain] = mo.
domain;
2032 for (
auto i = mStreamMaps[sManifests].begin();
2033 i != mStreamMaps[sManifests].end();)
2035 if (
auto p = i->second.lock())
2037 p->send(jvObj,
true);
2042 i = mStreamMaps[sManifests].erase(i);
2048NetworkOPsImp::ServerFeeSummary::ServerFeeSummary(
2052 : loadFactorServer{loadFeeTrack.getLoadFactor()}
2053 , loadBaseServer{loadFeeTrack.getLoadBase()}
2055 , em{
std::move(escalationMetrics)}
2065 em.has_value() != b.
em.has_value())
2071 em->minProcessingFeeLevel != b.
em->minProcessingFeeLevel ||
2072 em->openLedgerFeeLevel != b.
em->openLedgerFeeLevel ||
2073 em->referenceFeeLevel != b.
em->referenceFeeLevel);
2106 jvObj[jss::type] =
"serverStatus";
2108 jvObj[jss::load_base] = f.loadBaseServer;
2109 jvObj[jss::load_factor_server] = f.loadFactorServer;
2110 jvObj[jss::base_fee] = f.baseFee.jsonClipped();
2115 safe_cast<std::uint64_t>(f.loadFactorServer),
2117 f.em->openLedgerFeeLevel,
2119 f.em->referenceFeeLevel)
2122 jvObj[jss::load_factor] =
trunc32(loadFactor);
2123 jvObj[jss::load_factor_fee_escalation] =
2124 f.em->openLedgerFeeLevel.jsonClipped();
2125 jvObj[jss::load_factor_fee_queue] =
2126 f.em->minProcessingFeeLevel.jsonClipped();
2127 jvObj[jss::load_factor_fee_reference] =
2128 f.em->referenceFeeLevel.jsonClipped();
2131 jvObj[jss::load_factor] = f.loadFactorServer;
2145 p->send(jvObj,
true);
2162 if (!streamMap.empty())
2165 jvObj[jss::type] =
"consensusPhase";
2166 jvObj[jss::consensus] =
to_string(phase);
2168 for (
auto i = streamMap.begin(); i != streamMap.end();)
2170 if (
auto p = i->second.lock())
2172 p->send(jvObj,
true);
2177 i = streamMap.erase(i);
2193 auto const signerPublic = val->getSignerPublic();
2195 jvObj[jss::type] =
"validationReceived";
2196 jvObj[jss::validation_public_key] =
2198 jvObj[jss::ledger_hash] =
to_string(val->getLedgerHash());
2199 jvObj[jss::signature] =
strHex(val->getSignature());
2200 jvObj[jss::full] = val->isFull();
2201 jvObj[jss::flags] = val->getFlags();
2202 jvObj[jss::signing_time] = *(*val)[~sfSigningTime];
2203 jvObj[jss::data] =
strHex(val->getSerializer().slice());
2205 if (
auto version = (*val)[~sfServerVersion])
2208 if (
auto cookie = (*val)[~sfCookie])
2211 if (
auto hash = (*val)[~sfValidatedHash])
2212 jvObj[jss::validated_hash] =
strHex(*hash);
2214 auto const masterKey =
2217 if (masterKey != signerPublic)
2222 if (
auto const seq = (*val)[~sfLedgerSequence])
2223 jvObj[jss::ledger_index] = *seq;
2225 if (val->isFieldPresent(sfAmendments))
2228 for (
auto const& amendment : val->getFieldV256(sfAmendments))
2232 if (
auto const closeTime = (*val)[~sfCloseTime])
2233 jvObj[jss::close_time] = *closeTime;
2235 if (
auto const loadFee = (*val)[~sfLoadFee])
2236 jvObj[jss::load_fee] = *loadFee;
2238 if (
auto const baseFee = val->at(~sfBaseFee))
2239 jvObj[jss::base_fee] =
static_cast<double>(*baseFee);
2241 if (
auto const reserveBase = val->at(~sfReserveBase))
2242 jvObj[jss::reserve_base] = *reserveBase;
2244 if (
auto const reserveInc = val->at(~sfReserveIncrement))
2245 jvObj[jss::reserve_inc] = *reserveInc;
2249 if (
auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops);
2250 baseFeeXRP && baseFeeXRP->native())
2251 jvObj[jss::base_fee] = baseFeeXRP->xrp().jsonClipped();
2253 if (
auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops);
2254 reserveBaseXRP && reserveBaseXRP->native())
2255 jvObj[jss::reserve_base] = reserveBaseXRP->xrp().jsonClipped();
2257 if (
auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops);
2258 reserveIncXRP && reserveIncXRP->native())
2259 jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped();
2268 if (jvTx.
isMember(jss::ledger_index))
2270 jvTx[jss::ledger_index] =
2271 std::to_string(jvTx[jss::ledger_index].asUInt());
2278 if (
auto p = i->second.lock())
2282 [&](
Json::Value const& jv) { p->send(jv, true); });
2302 jvObj[jss::type] =
"peerStatusChange";
2311 p->send(jvObj,
true);
2325 using namespace std::chrono_literals;
2357 <<
"recvValidation " << val->getLedgerHash() <<
" from " << source;
2373 <<
"Exception thrown for handling new validation "
2374 << val->getLedgerHash() <<
": " << e.
what();
2379 <<
"Unknown exception thrown for handling new validation "
2380 << val->getLedgerHash();
2392 ss <<
"VALIDATION: " << val->render() <<
" master_key: ";
2429 "This server is amendment blocked, and must be updated to be "
2430 "able to stay in sync with the network.";
2437 "This server has an expired validator list. validators.txt "
2438 "may be incorrectly configured or some [validator_list_sites] "
2439 "may be unreachable.";
2446 "One or more unsupported amendments have reached majority. "
2447 "Upgrade to the latest version before they are activated "
2448 "to avoid being amendment blocked.";
2449 if (
auto const expected =
2453 d[jss::expected_date] = expected->time_since_epoch().count();
2454 d[jss::expected_date_UTC] =
to_string(*expected);
2458 if (warnings.size())
2459 info[jss::warnings] = std::move(warnings);
2474 info[jss::time] =
to_string(std::chrono::floor<std::chrono::microseconds>(
2478 info[jss::network_ledger] =
"waiting";
2480 info[jss::validation_quorum] =
2488 info[jss::node_size] =
"tiny";
2491 info[jss::node_size] =
"small";
2494 info[jss::node_size] =
"medium";
2497 info[jss::node_size] =
"large";
2500 info[jss::node_size] =
"huge";
2509 info[jss::validator_list_expires] =
2510 safe_cast<Json::UInt>(when->time_since_epoch().count());
2512 info[jss::validator_list_expires] = 0;
2522 if (*when == TimeKeeper::time_point::max())
2524 x[jss::expiration] =
"never";
2525 x[jss::status] =
"active";
2532 x[jss::status] =
"active";
2534 x[jss::status] =
"expired";
2539 x[jss::status] =
"unknown";
2540 x[jss::expiration] =
"unknown";
2544#if defined(GIT_COMMIT_HASH) || defined(GIT_BRANCH)
2547#ifdef GIT_COMMIT_HASH
2548 x[jss::hash] = GIT_COMMIT_HASH;
2551 x[jss::branch] = GIT_BRANCH;
2556 info[jss::io_latency_ms] =
2564 info[jss::pubkey_validator] =
2569 info[jss::pubkey_validator] =
"none";
2579 info[jss::counters][jss::nodestore] = nodestore;
2583 info[jss::pubkey_node] =
2589 info[jss::amendment_blocked] =
true;
2603 lastClose[jss::converge_time_s] =
2608 lastClose[jss::converge_time] =
2612 info[jss::last_close] = lastClose;
2620 info[jss::network_id] =
static_cast<Json::UInt>(*netid);
2622 auto const escalationMetrics =
2630 auto const loadFactorFeeEscalation =
2632 escalationMetrics.openLedgerFeeLevel,
2634 escalationMetrics.referenceFeeLevel)
2638 safe_cast<std::uint64_t>(loadFactorServer), loadFactorFeeEscalation);
2642 info[jss::load_base] = loadBaseServer;
2643 info[jss::load_factor] =
trunc32(loadFactor);
2644 info[jss::load_factor_server] = loadFactorServer;
2651 info[jss::load_factor_fee_escalation] =
2652 escalationMetrics.openLedgerFeeLevel.jsonClipped();
2653 info[jss::load_factor_fee_queue] =
2654 escalationMetrics.minProcessingFeeLevel.jsonClipped();
2655 info[jss::load_factor_fee_reference] =
2656 escalationMetrics.referenceFeeLevel.jsonClipped();
2660 info[jss::load_factor] =
2661 static_cast<double>(loadFactor) / loadBaseServer;
2663 if (loadFactorServer != loadFactor)
2664 info[jss::load_factor_server] =
2665 static_cast<double>(loadFactorServer) / loadBaseServer;
2670 if (fee != loadBaseServer)
2671 info[jss::load_factor_local] =
2672 static_cast<double>(fee) / loadBaseServer;
2674 if (fee != loadBaseServer)
2675 info[jss::load_factor_net] =
2676 static_cast<double>(fee) / loadBaseServer;
2678 if (fee != loadBaseServer)
2679 info[jss::load_factor_cluster] =
2680 static_cast<double>(fee) / loadBaseServer;
2682 if (escalationMetrics.openLedgerFeeLevel !=
2683 escalationMetrics.referenceFeeLevel &&
2684 (admin || loadFactorFeeEscalation != loadFactor))
2685 info[jss::load_factor_fee_escalation] =
2686 escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2687 escalationMetrics.referenceFeeLevel);
2688 if (escalationMetrics.minProcessingFeeLevel !=
2689 escalationMetrics.referenceFeeLevel)
2690 info[jss::load_factor_fee_queue] =
2691 escalationMetrics.minProcessingFeeLevel.decimalFromReference(
2692 escalationMetrics.referenceFeeLevel);
2705 XRPAmount const baseFee = lpClosed->fees().base;
2707 l[jss::seq] =
Json::UInt(lpClosed->info().seq);
2708 l[jss::hash] =
to_string(lpClosed->info().hash);
2713 l[jss::reserve_base] =
2714 lpClosed->fees().accountReserve(0).jsonClipped();
2715 l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2717 lpClosed->info().closeTime.time_since_epoch().count());
2722 l[jss::reserve_base_xrp] =
2723 lpClosed->fees().accountReserve(0).decimalXRP();
2724 l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2727 std::abs(closeOffset.count()) >= 60)
2728 l[jss::close_time_offset] =
2736 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2740 auto lCloseTime = lpClosed->info().closeTime;
2742 if (lCloseTime <= closeTime)
2744 using namespace std::chrono_literals;
2745 auto age = closeTime - lCloseTime;
2747 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2753 info[jss::validated_ledger] = l;
2755 info[jss::closed_ledger] = l;
2759 info[jss::published_ledger] =
"none";
2760 else if (lpPublished->info().seq != lpClosed->info().seq)
2761 info[jss::published_ledger] = lpPublished->info().seq;
2766 info[jss::jq_trans_overflow] =
2768 info[jss::peer_disconnects] =
2770 info[jss::peer_disconnects_resources] =
2775 "http",
"https",
"peer",
"ws",
"ws2",
"wss",
"wss2"};
2783 !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() &&
2784 port.admin_user.empty() && port.admin_password.empty()))
2798 for (
auto const& p : proto)
2799 jv[jss::protocol].append(p);
2806 auto const optPort = grpcSection.
get(
"port");
2807 if (optPort && grpcSection.get(
"ip"))
2810 jv[jss::port] = *optPort;
2812 jv[jss::protocol].append(
"grpc");
2815 info[jss::ports] = std::move(ports);
2840 transJson(transaction, result,
false, ledger, std::nullopt);
2854 [&](
Json::Value const& jv) { p->send(jv, true); });
2877 alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted,
app_);
2879 lpAccepted->info().hash, alpAccepted);
2883 alpAccepted->getLedger().
get() == lpAccepted.
get(),
2884 "ripple::NetworkOPsImp::pubLedger : accepted input");
2888 <<
"Publishing ledger " << lpAccepted->info().seq <<
" "
2889 << lpAccepted->info().hash;
2897 jvObj[jss::type] =
"ledgerClosed";
2898 jvObj[jss::ledger_index] = lpAccepted->info().seq;
2899 jvObj[jss::ledger_hash] =
to_string(lpAccepted->info().hash);
2901 lpAccepted->info().closeTime.time_since_epoch().count());
2903 if (!lpAccepted->rules().enabled(featureXRPFees))
2905 jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2906 jvObj[jss::reserve_base] =
2907 lpAccepted->fees().accountReserve(0).jsonClipped();
2908 jvObj[jss::reserve_inc] =
2909 lpAccepted->fees().increment.jsonClipped();
2911 jvObj[jss::txn_count] =
Json::UInt(alpAccepted->size());
2915 jvObj[jss::validated_ledgers] =
2925 p->send(jvObj,
true);
2943 p->send(jvObj,
true);
2952 static bool firstTime =
true;
2959 for (
auto& inner : outer.second)
2961 auto& subInfo = inner.second;
2962 if (subInfo.index_->separationLedgerSeq_ == 0)
2965 alpAccepted->getLedger(), subInfo);
2974 for (
auto const& accTx : *alpAccepted)
2978 lpAccepted, *accTx, accTx == *(--alpAccepted->end()));
3005 "reportConsensusStateChange->pubConsensus",
3036 jvObj[jss::type] =
"transaction";
3040 jvObj[jss::transaction] =
3047 jvObj[jss::meta], *ledger, transaction, meta->
get());
3049 jvObj[jss::meta], transaction, meta->
get());
3052 if (!ledger->open())
3053 jvObj[jss::ledger_hash] =
to_string(ledger->info().hash);
3057 jvObj[jss::ledger_index] = ledger->info().seq;
3058 jvObj[jss::transaction][jss::date] =
3059 ledger->info().closeTime.time_since_epoch().count();
3060 jvObj[jss::validated] =
true;
3061 jvObj[jss::close_time_iso] =
to_string_iso(ledger->info().closeTime);
3067 jvObj[jss::validated] =
false;
3068 jvObj[jss::ledger_current_index] = ledger->info().seq;
3071 jvObj[jss::status] = validated ?
"closed" :
"proposed";
3072 jvObj[jss::engine_result] = sToken;
3073 jvObj[jss::engine_result_code] = result;
3074 jvObj[jss::engine_result_message] = sHuman;
3076 if (transaction->getTxnType() == ttOFFER_CREATE)
3078 auto const account = transaction->getAccountID(sfAccount);
3079 auto const amount = transaction->getFieldAmount(sfTakerGets);
3082 if (account != amount.issue().account)
3090 jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3098 [&]<
unsigned Version>(
3100 RPC::insertDeliverMax(
3101 jvTx[jss::transaction], transaction->getTxnType(), Version);
3103 if constexpr (Version > 1)
3105 jvTx[jss::tx_json] = jvTx.removeMember(jss::transaction);
3106 jvTx[jss::hash] = hash;
3110 jvTx[jss::transaction][jss::hash] = hash;
3123 auto const& stTxn = transaction.
getTxn();
3127 auto const trResult = transaction.
getResult();
3142 [&](
Json::Value const& jv) { p->send(jv, true); });
3159 [&](
Json::Value const& jv) { p->send(jv, true); });
3184 auto const currLedgerSeq = ledger->seq();
3191 for (
auto const& affectedAccount : transaction.
getAffected())
3196 auto it = simiIt->second.begin();
3198 while (it != simiIt->second.end())
3209 it = simiIt->second.erase(it);
3216 auto it = simiIt->second.begin();
3217 while (it != simiIt->second.end())
3228 it = simiIt->second.erase(it);
3235 auto& subs = histoIt->second;
3236 auto it = subs.begin();
3237 while (it != subs.end())
3240 if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3254 it = subs.erase(it);
3265 <<
"pubAccountTransaction: " <<
"proposed=" << iProposed
3266 <<
", accepted=" << iAccepted;
3268 if (!notify.
empty() || !accountHistoryNotify.
empty())
3270 auto const& stTxn = transaction.
getTxn();
3274 auto const trResult = transaction.
getResult();
3280 isrListener->getApiVersion(),
3281 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3285 jvObj.
set(jss::account_history_boundary,
true);
3288 jvObj.
isMember(jss::account_history_tx_stream) ==
3290 "ripple::NetworkOPsImp::pubAccountTransaction : "
3291 "account_history_tx_stream not set");
3292 for (
auto& info : accountHistoryNotify)
3294 auto& index = info.index_;
3295 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3296 jvObj.
set(jss::account_history_tx_first,
true);
3298 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3301 info.sink_->getApiVersion(),
3302 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3327 for (
auto const& affectedAccount : tx->getMentionedAccounts())
3332 auto it = simiIt->second.begin();
3334 while (it != simiIt->second.end())
3345 it = simiIt->second.erase(it);
3352 JLOG(
m_journal.
trace()) <<
"pubProposedAccountTransaction: " << iProposed;
3354 if (!notify.
empty() || !accountHistoryNotify.
empty())
3361 isrListener->getApiVersion(),
3362 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3365 jvObj.
isMember(jss::account_history_tx_stream) ==
3367 "ripple::NetworkOPs::pubProposedAccountTransaction : "
3368 "account_history_tx_stream not set");
3369 for (
auto& info : accountHistoryNotify)
3371 auto& index = info.index_;
3372 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3373 jvObj.
set(jss::account_history_tx_first,
true);
3374 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3376 info.sink_->getApiVersion(),
3377 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3394 for (
auto const& naAccountID : vnaAccountIDs)
3397 <<
"subAccount: account: " <<
toBase58(naAccountID);
3399 isrListener->insertSubAccountInfo(naAccountID, rt);
3404 for (
auto const& naAccountID : vnaAccountIDs)
3406 auto simIterator = subMap.
find(naAccountID);
3407 if (simIterator == subMap.
end())
3411 usisElement[isrListener->getSeq()] = isrListener;
3413 subMap.
insert(simIterator, make_pair(naAccountID, usisElement));
3418 simIterator->second[isrListener->getSeq()] = isrListener;
3429 for (
auto const& naAccountID : vnaAccountIDs)
3432 isrListener->deleteSubAccountInfo(naAccountID, rt);
3449 for (
auto const& naAccountID : vnaAccountIDs)
3451 auto simIterator = subMap.
find(naAccountID);
3453 if (simIterator != subMap.
end())
3456 simIterator->second.erase(uSeq);
3458 if (simIterator->second.empty())
3461 subMap.
erase(simIterator);
3470 enum DatabaseType { Sqlite,
None };
3471 static const auto databaseType = [&]() -> DatabaseType {
3476 return DatabaseType::Sqlite;
3478 return DatabaseType::None;
3481 if (databaseType == DatabaseType::None)
3484 <<
"AccountHistory job for account "
3496 "AccountHistoryTxStream",
3497 [
this, dbType = databaseType, subInfo]() {
3498 auto const& accountId = subInfo.
index_->accountId_;
3499 auto& lastLedgerSeq = subInfo.
index_->historyLastLedgerSeq_;
3500 auto& txHistoryIndex = subInfo.
index_->historyTxIndex_;
3503 <<
"AccountHistory job for account " <<
toBase58(accountId)
3504 <<
" started. lastLedgerSeq=" << lastLedgerSeq;
3514 auto stx = tx->getSTransaction();
3515 if (stx->getAccountID(sfAccount) == accountId &&
3516 stx->getSeqProxy().value() == 1)
3520 for (
auto& node : meta->getNodes())
3522 if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3525 if (node.isFieldPresent(sfNewFields))
3527 if (
auto inner =
dynamic_cast<const STObject*
>(
3528 node.peekAtPField(sfNewFields));
3531 if (inner->isFieldPresent(sfAccount) &&
3532 inner->getAccountID(sfAccount) == accountId)
3544 bool unsubscribe) ->
bool {
3547 sptr->send(jvObj,
true);
3557 bool unsubscribe) ->
bool {
3561 sptr->getApiVersion(),
3562 [&](
Json::Value const& jv) { sptr->send(jv,
true); });
3585 accountId, minLedger, maxLedger, marker, 0,
true};
3586 return db->newestAccountTxPage(options);
3590 "ripple::NetworkOPsImp::addAccountHistoryJob::"
3591 "getMoreTxns : invalid database type");
3600 while (lastLedgerSeq >= 2 && !subInfo.
index_->stopHistorical_)
3602 int feeChargeCount = 0;
3611 <<
"AccountHistory job for account "
3612 <<
toBase58(accountId) <<
" no InfoSub. Fee charged "
3613 << feeChargeCount <<
" times.";
3618 auto startLedgerSeq =
3619 (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3621 <<
"AccountHistory job for account " <<
toBase58(accountId)
3622 <<
", working on ledger range [" << startLedgerSeq <<
","
3623 << lastLedgerSeq <<
"]";
3625 auto haveRange = [&]() ->
bool {
3628 auto haveSomeValidatedLedgers =
3630 validatedMin, validatedMax);
3632 return haveSomeValidatedLedgers &&
3633 validatedMin <= startLedgerSeq &&
3634 lastLedgerSeq <= validatedMax;
3640 <<
"AccountHistory reschedule job for account "
3641 <<
toBase58(accountId) <<
", incomplete ledger range ["
3642 << startLedgerSeq <<
"," << lastLedgerSeq <<
"]";
3648 while (!subInfo.
index_->stopHistorical_)
3651 getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3655 <<
"AccountHistory job for account "
3656 <<
toBase58(accountId) <<
" getMoreTxns failed.";
3661 auto const& txns = dbResult->first;
3662 marker = dbResult->second;
3663 size_t num_txns = txns.size();
3664 for (
size_t i = 0; i < num_txns; ++i)
3666 auto const& [tx, meta] = txns[i];
3671 <<
"AccountHistory job for account "
3672 <<
toBase58(accountId) <<
" empty tx or meta.";
3682 <<
"AccountHistory job for account "
3683 <<
toBase58(accountId) <<
" no ledger.";
3688 tx->getSTransaction();
3692 <<
"AccountHistory job for account "
3694 <<
" getSTransaction failed.";
3700 auto const trR = meta->getResultTER();
3702 transJson(stTxn, trR,
true, curTxLedger, mRef);
3705 jss::account_history_tx_index, txHistoryIndex--);
3706 if (i + 1 == num_txns ||
3707 txns[i + 1].first->getLedger() != tx->getLedger())
3708 jvTx.
set(jss::account_history_boundary,
true);
3710 if (isFirstTx(tx, meta))
3712 jvTx.
set(jss::account_history_tx_first,
true);
3713 sendMultiApiJson(jvTx,
false);
3716 <<
"AccountHistory job for account "
3718 <<
" done, found last tx.";
3723 sendMultiApiJson(jvTx,
false);
3730 <<
"AccountHistory job for account "
3732 <<
" paging, marker=" << marker->ledgerSeq <<
":"
3741 if (!subInfo.
index_->stopHistorical_)
3743 lastLedgerSeq = startLedgerSeq - 1;
3744 if (lastLedgerSeq <= 1)
3747 <<
"AccountHistory job for account "
3749 <<
" done, reached genesis ledger.";
3762 subInfo.
index_->separationLedgerSeq_ = ledger->seq();
3763 auto const& accountId = subInfo.
index_->accountId_;
3765 if (!ledger->exists(accountKeylet))
3768 <<
"subAccountHistoryStart, no account " <<
toBase58(accountId)
3769 <<
", no need to add AccountHistory job.";
3774 if (
auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3776 if (sleAcct->getFieldU32(sfSequence) == 1)
3779 <<
"subAccountHistoryStart, genesis account "
3781 <<
" does not have tx, no need to add AccountHistory job.";
3788 "ripple::NetworkOPsImp::subAccountHistoryStart : failed to "
3789 "access genesis account");
3793 subInfo.
index_->historyLastLedgerSeq_ = ledger->seq();
3794 subInfo.
index_->haveHistorical_ =
true;
3797 <<
"subAccountHistoryStart, add AccountHistory job: accountId="
3798 <<
toBase58(accountId) <<
", currentLedgerSeq=" << ledger->seq();
3808 if (!isrListener->insertSubAccountHistory(accountId))
3811 <<
"subAccountHistory, already subscribed to account "
3818 isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3823 inner.
emplace(isrListener->getSeq(), ahi);
3829 simIterator->second.emplace(isrListener->getSeq(), ahi);
3843 <<
"subAccountHistory, no validated ledger yet, delay start";
3856 isrListener->deleteSubAccountHistory(account);
3870 auto& subInfoMap = simIterator->second;
3871 auto subInfoIter = subInfoMap.find(seq);
3872 if (subInfoIter != subInfoMap.end())
3874 subInfoIter->second.index_->stopHistorical_ =
true;
3879 simIterator->second.erase(seq);
3880 if (simIterator->second.empty())
3886 <<
"unsubAccountHistory, account " <<
toBase58(account)
3887 <<
", historyOnly = " << (historyOnly ?
"true" :
"false");
3895 listeners->addSubscriber(isrListener);
3897 UNREACHABLE(
"ripple::NetworkOPsImp::subBook : null book listeners");
3905 listeners->removeSubscriber(uSeq);
3917 m_standalone,
"ripple::NetworkOPsImp::acceptLedger : is standalone");
3920 Throw<std::runtime_error>(
3921 "Operation only possible in STANDALONE mode.");
3936 jvResult[jss::ledger_index] = lpClosed->info().seq;
3937 jvResult[jss::ledger_hash] =
to_string(lpClosed->info().hash);
3939 lpClosed->info().closeTime.time_since_epoch().count());
3940 if (!lpClosed->rules().enabled(featureXRPFees))
3942 jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
3943 jvResult[jss::reserve_base] =
3944 lpClosed->fees().accountReserve(0).jsonClipped();
3945 jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
3950 jvResult[jss::validated_ledgers] =
3956 .emplace(isrListener->getSeq(), isrListener)
3966 .emplace(isrListener->getSeq(), isrListener)
3992 .emplace(isrListener->getSeq(), isrListener)
4020 jvResult[jss::random] =
to_string(uRandom);
4022 jvResult[jss::load_base] = feeTrack.getLoadBase();
4023 jvResult[jss::load_factor] = feeTrack.getLoadFactor();
4024 jvResult[jss::hostid] =
getHostId(admin);
4025 jvResult[jss::pubkey_node] =
4030 .emplace(isrListener->getSeq(), isrListener)
4048 .emplace(isrListener->getSeq(), isrListener)
4066 .emplace(isrListener->getSeq(), isrListener)
4084 .emplace(isrListener->getSeq(), isrListener)
4108 .emplace(isrListener->getSeq(), isrListener)
4126 .emplace(isrListener->getSeq(), isrListener)
4174 if (map.find(pInfo->getSeq()) != map.end())
4181#ifndef USE_NEW_BOOK_PAGE
4192 unsigned int iLimit,
4202 uint256 uTipIndex = uBookBase;
4206 stream <<
"getBookPage:" << book;
4207 stream <<
"getBookPage: uBookBase=" << uBookBase;
4208 stream <<
"getBookPage: uBookEnd=" << uBookEnd;
4209 stream <<
"getBookPage: uTipIndex=" << uTipIndex;
4218 bool bDirectAdvance =
true;
4222 unsigned int uBookEntry;
4228 while (!bDone && iLimit-- > 0)
4232 bDirectAdvance =
false;
4236 auto const ledgerIndex = view.
succ(uTipIndex, uBookEnd);
4240 sleOfferDir.
reset();
4249 uTipIndex = sleOfferDir->key();
4252 cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4255 <<
"getBookPage: uTipIndex=" << uTipIndex;
4257 <<
"getBookPage: offerIndex=" << offerIndex;
4267 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4268 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4269 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4271 bool firstOwnerOffer(
true);
4277 saOwnerFunds = saTakerGets;
4279 else if (bGlobalFreeze)
4287 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4288 if (umBalanceEntry != umBalance.
end())
4292 saOwnerFunds = umBalanceEntry->second;
4293 firstOwnerOffer =
false;
4307 if (saOwnerFunds < beast::zero)
4311 saOwnerFunds.
clear();
4319 STAmount saOwnerFundsLimit = saOwnerFunds;
4331 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4334 if (saOwnerFundsLimit >= saTakerGets)
4337 saTakerGetsFunded = saTakerGets;
4343 saTakerGetsFunded = saOwnerFundsLimit;
4345 saTakerGetsFunded.
setJson(jvOffer[jss::taker_gets_funded]);
4349 saTakerGetsFunded, saDirRate, saTakerPays.
issue()))
4350 .setJson(jvOffer[jss::taker_pays_funded]);
4356 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4358 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4362 jvOf[jss::quality] = saDirRate.
getText();
4364 if (firstOwnerOffer)
4365 jvOf[jss::owner_funds] = saOwnerFunds.
getText();
4372 if (!
cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4374 bDirectAdvance =
true;
4379 <<
"getBookPage: offerIndex=" << offerIndex;
4399 unsigned int iLimit,
4407 MetaView lesActive(lpLedger,
tapNONE,
true);
4408 OrderBookIterator obIterator(lesActive, book);
4412 const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.
out.
account) ||
4413 lesActive.isGlobalFrozen(book.
in.
account);
4415 while (iLimit-- > 0 && obIterator.nextOffer())
4420 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4421 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4422 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4423 STAmount saDirRate = obIterator.getCurrentRate();
4429 saOwnerFunds = saTakerGets;
4431 else if (bGlobalFreeze)
4439 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4441 if (umBalanceEntry != umBalance.
end())
4445 saOwnerFunds = umBalanceEntry->second;
4451 saOwnerFunds = lesActive.accountHolds(
4457 if (saOwnerFunds.isNegative())
4461 saOwnerFunds.zero();
4468 STAmount saTakerGetsFunded;
4469 STAmount saOwnerFundsLimit = saOwnerFunds;
4481 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4484 if (saOwnerFundsLimit >= saTakerGets)
4487 saTakerGetsFunded = saTakerGets;
4492 saTakerGetsFunded = saOwnerFundsLimit;
4494 saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4500 multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4501 .setJson(jvOffer[jss::taker_pays_funded]);
4504 STAmount saOwnerPays = (
parityRate == offerRate)
4507 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4509 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4511 if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4515 jvOf[jss::quality] = saDirRate.
getText();
4530 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4570 ++counters_[
static_cast<std::size_t>(om)].transitions;
4572 counters_[
static_cast<std::size_t>(om)].transitions == 1)
4574 initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4575 now - processStart_)
4579 std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4588 auto [counters, mode, start, initialSync] = getCounterData();
4589 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4599 auto& state = obj[jss::state_accounting][
states_[i]];
4600 state[jss::transitions] =
std::to_string(counters[i].transitions);
4601 state[jss::duration_us] =
std::to_string(counters[i].dur.count());
4605 obj[jss::initial_sync_duration_us] =
std::to_string(initialSync);
4620 boost::asio::io_service& io_svc,
4624 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)