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>
110 "ripple::NetworkOPsImp::TransactionStatus::TransactionStatus : "
153 std::chrono::steady_clock::time_point
start_ =
214 return !(*
this != b);
233 boost::asio::io_service& io_svc,
247 app_.logs().journal(
"FeeVote")),
250 app.getInboundTransactions(),
251 beast::get_abstract_clock<
std::chrono::steady_clock>(),
253 app_.logs().journal(
"LedgerConsensus"))
432 getServerInfo(
bool human,
bool admin,
bool counters)
override;
459 TER result)
override;
493 bool historyOnly)
override;
499 bool historyOnly)
override;
567 boost::system::error_code ec;
572 <<
"NetworkOPs: heartbeatTimer cancel error: "
581 <<
"NetworkOPs: clusterTimer cancel error: "
590 <<
"NetworkOPs: accountHistoryTxTimer cancel error: "
595 using namespace std::chrono_literals;
605 boost::asio::steady_timer& timer,
785 template <
class Handler>
787 Handler
const& handler,
789 :
hook(collector->make_hook(handler))
792 "Disconnected_duration"))
795 "Connected_duration"))
797 collector->make_gauge(
"State_Accounting",
"Syncing_duration"))
800 "Tracking_duration"))
802 collector->make_gauge(
"State_Accounting",
"Full_duration"))
805 "Disconnected_transitions"))
808 "Connected_transitions"))
811 "Syncing_transitions"))
814 "Tracking_transitions"))
816 collector->make_gauge(
"State_Accounting",
"Full_transitions"))
845 {
"disconnected",
"connected",
"syncing",
"tracking",
"full"}};
907 static std::string const hostname = boost::asio::ip::host_name();
914 static std::string const shroudedHostId = [
this]() {
920 return shroudedHostId;
935 boost::asio::steady_timer& timer,
942 [
this, onExpire, onError](boost::system::error_code
const& e) {
943 if ((e.value() == boost::system::errc::success) &&
944 (!m_job_queue.isStopped()))
949 if (e.value() != boost::system::errc::success &&
950 e.value() != boost::asio::error::operation_aborted)
953 JLOG(m_journal.error())
954 <<
"Timer got error '" << e.message()
955 <<
"'. Restarting timer.";
960 timer.expires_from_now(expiry_time);
961 timer.async_wait(std::move(*optionalCountedHandler));
966NetworkOPsImp::setHeartbeatTimer()
970 mConsensus.parms().ledgerGRANULARITY,
972 m_job_queue.addJob(jtNETOP_TIMER,
"NetOPs.heartbeat", [this]() {
973 processHeartbeatTimer();
976 [
this]() { setHeartbeatTimer(); });
980NetworkOPsImp::setClusterTimer()
982 using namespace std::chrono_literals;
989 processClusterTimer();
992 [
this]() { setClusterTimer(); });
998 JLOG(m_journal.debug()) <<
"Scheduling AccountHistory job for account "
1000 using namespace std::chrono_literals;
1002 accountHistoryTxTimer_,
1004 [
this, subInfo]() { addAccountHistoryJob(subInfo); },
1005 [
this, subInfo]() { setAccountHistoryJobTimer(subInfo); });
1009NetworkOPsImp::processHeartbeatTimer()
1018 std::size_t const numPeers = app_.overlay().size();
1021 if (numPeers < minPeerCount_)
1023 if (mMode != OperatingMode::DISCONNECTED)
1025 setMode(OperatingMode::DISCONNECTED);
1026 JLOG(m_journal.warn())
1027 <<
"Node count (" << numPeers <<
") has fallen "
1028 <<
"below required minimum (" << minPeerCount_ <<
").";
1035 setHeartbeatTimer();
1039 if (mMode == OperatingMode::DISCONNECTED)
1041 setMode(OperatingMode::CONNECTED);
1042 JLOG(m_journal.info())
1043 <<
"Node count (" << numPeers <<
") is sufficient.";
1048 if (mMode == OperatingMode::SYNCING)
1049 setMode(OperatingMode::SYNCING);
1050 else if (mMode == OperatingMode::CONNECTED)
1051 setMode(OperatingMode::CONNECTED);
1054 mConsensus.timerEntry(app_.timeKeeper().closeTime());
1057 if (mLastConsensusPhase != currPhase)
1059 reportConsensusStateChange(currPhase);
1060 mLastConsensusPhase = currPhase;
1063 setHeartbeatTimer();
1067NetworkOPsImp::processClusterTimer()
1069 if (app_.cluster().size() == 0)
1072 using namespace std::chrono_literals;
1074 bool const update = app_.cluster().update(
1075 app_.nodeIdentity().first,
1077 (m_ledgerMaster.getValidatedLedgerAge() <= 4min)
1078 ? app_.getFeeTrack().getLocalFee()
1080 app_.timeKeeper().now());
1084 JLOG(m_journal.debug()) <<
"Too soon to send cluster update";
1089 protocol::TMCluster cluster;
1090 app_.cluster().for_each([&cluster](
ClusterNode const& node) {
1091 protocol::TMClusterNode& n = *cluster.add_clusternodes();
1096 n.set_nodename(node.
name());
1100 for (
auto& item : gossip.
items)
1102 protocol::TMLoadSource& node = *cluster.add_loadsources();
1103 node.set_name(to_string(item.address));
1104 node.set_cost(item.balance);
1106 app_.overlay().foreach(
send_if(
1107 std::make_shared<Message>(cluster, protocol::mtCLUSTER),
1118 if (mode == OperatingMode::FULL && admin)
1120 auto const consensusMode = mConsensus.mode();
1121 if (consensusMode != ConsensusMode::wrongLedger)
1123 if (consensusMode == ConsensusMode::proposing)
1126 if (mConsensus.validating())
1127 return "validating";
1137 if (isNeedNetworkLedger())
1146 auto const txid = trans->getTransactionID();
1147 auto const flags = app_.getHashRouter().getFlags(txid);
1149 if ((flags & SF_BAD) != 0)
1151 JLOG(m_journal.warn()) <<
"Submitted transaction cached bad";
1158 app_.getHashRouter(),
1160 m_ledgerMaster.getValidatedRules(),
1163 if (validity != Validity::Valid)
1165 JLOG(m_journal.warn())
1166 <<
"Submitted transaction invalid: " << reason;
1172 JLOG(m_journal.warn())
1173 <<
"Exception checking transaction " << txid <<
": " << ex.
what();
1180 auto tx = std::make_shared<Transaction>(trans, reason, app_);
1182 m_job_queue.addJob(
jtTRANSACTION,
"submitTxn", [
this, tx]() {
1184 processTransaction(t,
false,
false, FailHard::no);
1189NetworkOPsImp::processTransaction(
1195 auto ev = m_job_queue.makeLoadEvent(
jtTXN_PROC,
"ProcessTXN");
1196 auto const newFlags = app_.getHashRouter().getFlags(transaction->getID());
1198 if ((newFlags & SF_BAD) != 0)
1201 JLOG(m_journal.warn()) << transaction->getID() <<
": cached bad!\n";
1202 transaction->setStatus(
INVALID);
1210 auto const view = m_ledgerMaster.getCurrentLedger();
1212 app_.getHashRouter(),
1213 *transaction->getSTransaction(),
1217 validity == Validity::Valid,
1218 "ripple::NetworkOPsImp::processTransaction : valid validity");
1221 if (validity == Validity::SigBad)
1223 JLOG(m_journal.info()) <<
"Transaction has bad signature: " << reason;
1224 transaction->setStatus(
INVALID);
1226 app_.getHashRouter().setFlags(transaction->getID(), SF_BAD);
1231 app_.getMasterTransaction().canonicalize(&transaction);
1234 doTransactionSync(transaction, bUnlimited, failType);
1236 doTransactionAsync(transaction, bUnlimited, failType);
1240NetworkOPsImp::doTransactionAsync(
1247 if (transaction->getApplying())
1250 mTransactions.push_back(
1252 transaction->setApplying();
1254 if (mDispatchState == DispatchState::none)
1256 if (m_job_queue.addJob(
1257 jtBATCH,
"transactionBatch", [
this]() { transactionBatch(); }))
1259 mDispatchState = DispatchState::scheduled;
1265NetworkOPsImp::doTransactionSync(
1272 if (!transaction->getApplying())
1274 mTransactions.push_back(
1276 transaction->setApplying();
1281 if (mDispatchState == DispatchState::running)
1290 if (mTransactions.size())
1293 if (m_job_queue.addJob(
jtBATCH,
"transactionBatch", [
this]() {
1297 mDispatchState = DispatchState::scheduled;
1301 }
while (transaction->getApplying());
1305NetworkOPsImp::transactionBatch()
1309 if (mDispatchState == DispatchState::running)
1312 while (mTransactions.size())
1323 mTransactions.
swap(transactions);
1325 !transactions.
empty(),
1326 "ripple::NetworkOPsImp::apply : non-empty transactions");
1328 mDispatchState != DispatchState::running,
1329 "ripple::NetworkOPsImp::apply : is not running");
1331 mDispatchState = DispatchState::running;
1337 bool changed =
false;
1340 m_ledgerMaster.peekMutex(), std::defer_lock};
1351 if (e.failType == FailHard::yes)
1354 auto const result = app_.getTxQ().apply(
1355 app_, view, e.transaction->getSTransaction(), flags, j);
1356 e.result = result.ter;
1357 e.applied = result.applied;
1358 changed = changed || result.applied;
1367 if (
auto const l = m_ledgerMaster.getValidatedLedger())
1368 validatedLedgerIndex = l->info().seq;
1370 auto newOL = app_.openLedger().current();
1373 e.transaction->clearSubmitResult();
1377 pubProposedTransaction(
1378 newOL, e.transaction->getSTransaction(), e.result);
1379 e.transaction->setApplied();
1382 e.transaction->setResult(e.result);
1385 app_.getHashRouter().setFlags(e.transaction->getID(), SF_BAD);
1394 JLOG(m_journal.info())
1395 <<
"TransactionResult: " << token <<
": " << human;
1400 bool addLocal = e.local;
1404 JLOG(m_journal.debug())
1405 <<
"Transaction is now included in open ledger";
1406 e.transaction->setStatus(
INCLUDED);
1408 auto const& txCur = e.transaction->getSTransaction();
1409 auto const txNext = m_ledgerMaster.popAcctTransaction(txCur);
1414 auto t = std::make_shared<Transaction>(trans, reason, app_);
1415 submit_held.
emplace_back(t,
false,
false, FailHard::no);
1422 JLOG(m_journal.info()) <<
"Transaction is obsolete";
1423 e.transaction->setStatus(
OBSOLETE);
1427 JLOG(m_journal.debug())
1428 <<
"Transaction is likely to claim a"
1429 <<
" fee, but is queued until fee drops";
1431 e.transaction->setStatus(
HELD);
1435 m_ledgerMaster.addHeldTransaction(e.transaction);
1436 e.transaction->setQueued();
1437 e.transaction->setKept();
1441 if (e.failType != FailHard::yes)
1444 JLOG(m_journal.debug())
1445 <<
"Transaction should be held: " << e.result;
1446 e.transaction->setStatus(
HELD);
1447 m_ledgerMaster.addHeldTransaction(e.transaction);
1448 e.transaction->setKept();
1453 JLOG(m_journal.debug())
1454 <<
"Status other than success " << e.result;
1455 e.transaction->setStatus(
INVALID);
1458 auto const enforceFailHard =
1459 e.failType == FailHard::yes && !
isTesSuccess(e.result);
1461 if (addLocal && !enforceFailHard)
1463 m_localTX->push_back(
1464 m_ledgerMaster.getCurrentLedgerIndex(),
1465 e.transaction->getSTransaction());
1466 e.transaction->setKept();
1470 ((mMode != OperatingMode::FULL) &&
1471 (e.failType != FailHard::yes) && e.local) ||
1476 app_.getHashRouter().shouldRelay(e.transaction->getID());
1480 protocol::TMTransaction tx;
1483 e.transaction->getSTransaction()->add(s);
1484 tx.set_rawtransaction(s.
data(), s.
size());
1485 tx.set_status(protocol::tsCURRENT);
1486 tx.set_receivetimestamp(
1487 app_.timeKeeper().now().time_since_epoch().count());
1490 app_.overlay().relay(e.transaction->getID(), tx, *toSkip);
1491 e.transaction->setBroadcast();
1495 if (validatedLedgerIndex)
1497 auto [fee, accountSeq, availableSeq] =
1498 app_.getTxQ().getTxRequiredFeeAndSeq(
1499 *newOL, e.transaction->getSTransaction());
1500 e.transaction->setCurrentLedgerState(
1501 *validatedLedgerIndex, fee, accountSeq, availableSeq);
1509 e.transaction->clearApplying();
1511 if (!submit_held.
empty())
1513 if (mTransactions.empty())
1514 mTransactions.swap(submit_held);
1516 for (
auto& e : submit_held)
1517 mTransactions.push_back(std::move(e));
1522 mDispatchState = DispatchState::none;
1530NetworkOPsImp::getOwnerInfo(
1535 auto root = keylet::ownerDir(account);
1536 auto sleNode = lpLedger->read(keylet::page(
root));
1543 for (
auto const& uDirEntry : sleNode->getFieldV256(sfIndexes))
1545 auto sleCur = lpLedger->read(keylet::child(uDirEntry));
1548 "ripple::NetworkOPsImp::getOwnerInfo : non-null child SLE");
1550 switch (sleCur->getType())
1553 if (!jvObjects.
isMember(jss::offers))
1554 jvObjects[jss::offers] =
1557 jvObjects[jss::offers].
append(
1558 sleCur->getJson(JsonOptions::none));
1561 case ltRIPPLE_STATE:
1562 if (!jvObjects.
isMember(jss::ripple_lines))
1564 jvObjects[jss::ripple_lines] =
1568 jvObjects[jss::ripple_lines].
append(
1569 sleCur->getJson(JsonOptions::none));
1572 case ltACCOUNT_ROOT:
1576 "ripple::NetworkOPsImp::getOwnerInfo : invalid "
1582 uNodeDir = sleNode->getFieldU64(sfIndexNext);
1586 sleNode = lpLedger->read(keylet::page(
root, uNodeDir));
1589 "ripple::NetworkOPsImp::getOwnerInfo : read next page");
1602NetworkOPsImp::isBlocked()
1604 return isAmendmentBlocked() || isUNLBlocked();
1608NetworkOPsImp::isAmendmentBlocked()
1610 return amendmentBlocked_;
1614NetworkOPsImp::setAmendmentBlocked()
1616 amendmentBlocked_ =
true;
1617 setMode(OperatingMode::CONNECTED);
1621NetworkOPsImp::isAmendmentWarned()
1623 return !amendmentBlocked_ && amendmentWarned_;
1627NetworkOPsImp::setAmendmentWarned()
1629 amendmentWarned_ =
true;
1633NetworkOPsImp::clearAmendmentWarned()
1635 amendmentWarned_ =
false;
1639NetworkOPsImp::isUNLBlocked()
1645NetworkOPsImp::setUNLBlocked()
1648 setMode(OperatingMode::CONNECTED);
1652NetworkOPsImp::clearUNLBlocked()
1654 unlBlocked_ =
false;
1658NetworkOPsImp::checkLastClosedLedger(
1667 JLOG(m_journal.trace()) <<
"NetworkOPsImp::checkLastClosedLedger";
1669 auto const ourClosed = m_ledgerMaster.getClosedLedger();
1674 uint256 closedLedger = ourClosed->info().hash;
1675 uint256 prevClosedLedger = ourClosed->info().parentHash;
1676 JLOG(m_journal.trace()) <<
"OurClosed: " << closedLedger;
1677 JLOG(m_journal.trace()) <<
"PrevClosed: " << prevClosedLedger;
1682 auto& validations = app_.getValidations();
1683 JLOG(m_journal.debug())
1684 <<
"ValidationTrie " <<
Json::Compact(validations.getJsonTrie());
1688 peerCounts[closedLedger] = 0;
1689 if (mMode >= OperatingMode::TRACKING)
1690 peerCounts[closedLedger]++;
1692 for (
auto& peer : peerList)
1694 uint256 peerLedger = peer->getClosedLedgerHash();
1697 ++peerCounts[peerLedger];
1700 for (
auto const& it : peerCounts)
1701 JLOG(m_journal.debug()) <<
"L: " << it.first <<
" n=" << it.second;
1703 uint256 preferredLCL = validations.getPreferredLCL(
1705 m_ledgerMaster.getValidLedgerIndex(),
1708 bool switchLedgers = preferredLCL != closedLedger;
1710 closedLedger = preferredLCL;
1712 if (switchLedgers && (closedLedger == prevClosedLedger))
1715 JLOG(m_journal.info()) <<
"We won't switch to our own previous ledger";
1716 networkClosed = ourClosed->info().hash;
1717 switchLedgers =
false;
1720 networkClosed = closedLedger;
1725 auto consensus = m_ledgerMaster.getLedgerByHash(closedLedger);
1728 consensus = app_.getInboundLedgers().acquire(
1729 closedLedger, 0, InboundLedger::Reason::CONSENSUS);
1732 (!m_ledgerMaster.canBeCurrent(consensus) ||
1733 !m_ledgerMaster.isCompatible(
1734 *consensus, m_journal.debug(),
"Not switching")))
1738 networkClosed = ourClosed->info().hash;
1742 JLOG(m_journal.warn()) <<
"We are not running on the consensus ledger";
1743 JLOG(m_journal.info()) <<
"Our LCL: " << ourClosed->info().hash
1745 JLOG(m_journal.info()) <<
"Net LCL " << closedLedger;
1747 if ((mMode == OperatingMode::TRACKING) || (mMode == OperatingMode::FULL))
1749 setMode(OperatingMode::CONNECTED);
1757 switchLastClosedLedger(consensus);
1764NetworkOPsImp::switchLastClosedLedger(
1768 JLOG(m_journal.error())
1769 <<
"JUMP last closed ledger to " << newLCL->info().hash;
1771 clearNeedNetworkLedger();
1774 app_.getTxQ().processClosedLedger(app_, *newLCL,
true);
1781 auto retries = m_localTX->getTxSet();
1782 auto const lastVal = app_.getLedgerMaster().getValidatedLedger();
1787 rules.
emplace(app_.config().features);
1788 app_.openLedger().accept(
1799 return app_.getTxQ().accept(app_, view);
1803 m_ledgerMaster.switchLCL(newLCL);
1805 protocol::TMStatusChange s;
1806 s.set_newevent(protocol::neSWITCHED_LEDGER);
1807 s.set_ledgerseq(newLCL->info().seq);
1808 s.set_networktime(app_.timeKeeper().now().time_since_epoch().count());
1809 s.set_ledgerhashprevious(
1810 newLCL->info().parentHash.begin(), newLCL->info().parentHash.size());
1811 s.set_ledgerhash(newLCL->info().hash.begin(), newLCL->info().hash.size());
1813 app_.overlay().foreach(
1814 send_always(std::make_shared<Message>(s, protocol::mtSTATUS_CHANGE)));
1818NetworkOPsImp::beginConsensus(
uint256 const& networkClosed)
1822 "ripple::NetworkOPsImp::beginConsensus : nonzero input");
1824 auto closingInfo = m_ledgerMaster.getCurrentLedger()->info();
1826 JLOG(m_journal.info()) <<
"Consensus time for #" << closingInfo.seq
1827 <<
" with LCL " << closingInfo.parentHash;
1829 auto prevLedger = m_ledgerMaster.getLedgerByHash(closingInfo.parentHash);
1834 if (mMode == OperatingMode::FULL)
1836 JLOG(m_journal.warn()) <<
"Don't have LCL, going to tracking";
1837 setMode(OperatingMode::TRACKING);
1844 prevLedger->info().hash == closingInfo.parentHash,
1845 "ripple::NetworkOPsImp::beginConsensus : prevLedger hash matches "
1848 closingInfo.parentHash == m_ledgerMaster.getClosedLedger()->info().hash,
1849 "ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches "
1852 if (prevLedger->rules().enabled(featureNegativeUNL))
1853 app_.validators().setNegativeUNL(prevLedger->negativeUNL());
1854 TrustChanges const changes = app_.validators().updateTrusted(
1855 app_.getValidations().getCurrentNodeIDs(),
1856 closingInfo.parentCloseTime,
1859 app_.getHashRouter());
1861 if (!changes.
added.empty() || !changes.
removed.empty())
1863 app_.getValidations().trustChanged(changes.
added, changes.
removed);
1865 app_.getAmendmentTable().trustChanged(
1866 app_.validators().getQuorumKeys().second);
1869 mConsensus.startRound(
1870 app_.timeKeeper().closeTime(),
1877 if (mLastConsensusPhase != currPhase)
1879 reportConsensusStateChange(currPhase);
1880 mLastConsensusPhase = currPhase;
1883 JLOG(m_journal.debug()) <<
"Initiating consensus engine";
1890 return mConsensus.peerProposal(app_.timeKeeper().closeTime(), peerPos);
1901 protocol::TMHaveTransactionSet msg;
1902 msg.set_hash(map->getHash().as_uint256().begin(), 256 / 8);
1903 msg.set_status(protocol::tsHAVE);
1904 app_.overlay().foreach(
1905 send_always(std::make_shared<Message>(msg, protocol::mtHAVE_SET)));
1909 mConsensus.gotTxSet(app_.timeKeeper().closeTime(),
RCLTxSet{map});
1913NetworkOPsImp::endConsensus()
1915 uint256 deadLedger = m_ledgerMaster.getClosedLedger()->info().parentHash;
1917 for (
auto const& it : app_.overlay().getActivePeers())
1919 if (it && (it->getClosedLedgerHash() == deadLedger))
1921 JLOG(m_journal.trace()) <<
"Killing obsolete peer status";
1928 checkLastClosedLedger(app_.overlay().getActivePeers(), networkClosed);
1930 if (networkClosed.
isZero())
1939 if (((mMode == OperatingMode::CONNECTED) ||
1940 (mMode == OperatingMode::SYNCING)) &&
1946 if (!needNetworkLedger_)
1947 setMode(OperatingMode::TRACKING);
1950 if (((mMode == OperatingMode::CONNECTED) ||
1951 (mMode == OperatingMode::TRACKING)) &&
1957 auto current = m_ledgerMaster.getCurrentLedger();
1958 if (app_.timeKeeper().now() < (
current->info().parentCloseTime +
1959 2 *
current->info().closeTimeResolution))
1961 setMode(OperatingMode::FULL);
1965 beginConsensus(networkClosed);
1969NetworkOPsImp::consensusViewChange()
1971 if ((mMode == OperatingMode::FULL) || (mMode == OperatingMode::TRACKING))
1973 setMode(OperatingMode::CONNECTED);
1983 if (!mStreamMaps[sManifests].empty())
1987 jvObj[jss::type] =
"manifestReceived";
1990 jvObj[jss::signing_key] =
1994 jvObj[jss::signature] =
strHex(*sig);
1997 jvObj[jss::domain] = mo.
domain;
2000 for (
auto i = mStreamMaps[sManifests].begin();
2001 i != mStreamMaps[sManifests].end();)
2003 if (
auto p = i->second.lock())
2005 p->send(jvObj,
true);
2010 i = mStreamMaps[sManifests].erase(i);
2016NetworkOPsImp::ServerFeeSummary::ServerFeeSummary(
2020 : loadFactorServer{loadFeeTrack.getLoadFactor()}
2021 , loadBaseServer{loadFeeTrack.getLoadBase()}
2023 , em{
std::move(escalationMetrics)}
2033 em.has_value() != b.
em.has_value())
2039 em->minProcessingFeeLevel != b.
em->minProcessingFeeLevel ||
2040 em->openLedgerFeeLevel != b.
em->openLedgerFeeLevel ||
2041 em->referenceFeeLevel != b.
em->referenceFeeLevel);
2074 jvObj[jss::type] =
"serverStatus";
2076 jvObj[jss::load_base] = f.loadBaseServer;
2077 jvObj[jss::load_factor_server] = f.loadFactorServer;
2078 jvObj[jss::base_fee] = f.baseFee.jsonClipped();
2083 safe_cast<std::uint64_t>(f.loadFactorServer),
2085 f.em->openLedgerFeeLevel,
2087 f.em->referenceFeeLevel)
2090 jvObj[jss::load_factor] =
trunc32(loadFactor);
2091 jvObj[jss::load_factor_fee_escalation] =
2092 f.em->openLedgerFeeLevel.jsonClipped();
2093 jvObj[jss::load_factor_fee_queue] =
2094 f.em->minProcessingFeeLevel.jsonClipped();
2095 jvObj[jss::load_factor_fee_reference] =
2096 f.em->referenceFeeLevel.jsonClipped();
2099 jvObj[jss::load_factor] = f.loadFactorServer;
2113 p->send(jvObj,
true);
2130 if (!streamMap.empty())
2133 jvObj[jss::type] =
"consensusPhase";
2134 jvObj[jss::consensus] =
to_string(phase);
2136 for (
auto i = streamMap.begin(); i != streamMap.end();)
2138 if (
auto p = i->second.lock())
2140 p->send(jvObj,
true);
2145 i = streamMap.erase(i);
2161 auto const signerPublic = val->getSignerPublic();
2163 jvObj[jss::type] =
"validationReceived";
2164 jvObj[jss::validation_public_key] =
2166 jvObj[jss::ledger_hash] =
to_string(val->getLedgerHash());
2167 jvObj[jss::signature] =
strHex(val->getSignature());
2168 jvObj[jss::full] = val->isFull();
2169 jvObj[jss::flags] = val->getFlags();
2170 jvObj[jss::signing_time] = *(*val)[~sfSigningTime];
2171 jvObj[jss::data] =
strHex(val->getSerializer().slice());
2173 if (
auto version = (*val)[~sfServerVersion])
2176 if (
auto cookie = (*val)[~sfCookie])
2179 if (
auto hash = (*val)[~sfValidatedHash])
2180 jvObj[jss::validated_hash] =
strHex(*hash);
2182 auto const masterKey =
2185 if (masterKey != signerPublic)
2190 if (
auto const seq = (*val)[~sfLedgerSequence])
2191 jvObj[jss::ledger_index] = *seq;
2193 if (val->isFieldPresent(sfAmendments))
2196 for (
auto const& amendment : val->getFieldV256(sfAmendments))
2200 if (
auto const closeTime = (*val)[~sfCloseTime])
2201 jvObj[jss::close_time] = *closeTime;
2203 if (
auto const loadFee = (*val)[~sfLoadFee])
2204 jvObj[jss::load_fee] = *loadFee;
2206 if (
auto const baseFee = val->at(~sfBaseFee))
2207 jvObj[jss::base_fee] =
static_cast<double>(*baseFee);
2209 if (
auto const reserveBase = val->at(~sfReserveBase))
2210 jvObj[jss::reserve_base] = *reserveBase;
2212 if (
auto const reserveInc = val->at(~sfReserveIncrement))
2213 jvObj[jss::reserve_inc] = *reserveInc;
2217 if (
auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops);
2218 baseFeeXRP && baseFeeXRP->native())
2219 jvObj[jss::base_fee] = baseFeeXRP->xrp().jsonClipped();
2221 if (
auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops);
2222 reserveBaseXRP && reserveBaseXRP->native())
2223 jvObj[jss::reserve_base] = reserveBaseXRP->xrp().jsonClipped();
2225 if (
auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops);
2226 reserveIncXRP && reserveIncXRP->native())
2227 jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped();
2236 if (jvTx.
isMember(jss::ledger_index))
2238 jvTx[jss::ledger_index] =
2239 std::to_string(jvTx[jss::ledger_index].asUInt());
2246 if (
auto p = i->second.lock())
2250 [&](
Json::Value const& jv) { p->send(jv, true); });
2270 jvObj[jss::type] =
"peerStatusChange";
2279 p->send(jvObj,
true);
2293 using namespace std::chrono_literals;
2325 <<
"recvValidation " << val->getLedgerHash() <<
" from " << source;
2341 <<
"Exception thrown for handling new validation "
2342 << val->getLedgerHash() <<
": " << e.
what();
2347 <<
"Unknown exception thrown for handling new validation "
2348 << val->getLedgerHash();
2360 ss <<
"VALIDATION: " << val->render() <<
" master_key: ";
2397 "This server is amendment blocked, and must be updated to be "
2398 "able to stay in sync with the network.";
2405 "This server has an expired validator list. validators.txt "
2406 "may be incorrectly configured or some [validator_list_sites] "
2407 "may be unreachable.";
2414 "One or more unsupported amendments have reached majority. "
2415 "Upgrade to the latest version before they are activated "
2416 "to avoid being amendment blocked.";
2417 if (
auto const expected =
2421 d[jss::expected_date] = expected->time_since_epoch().count();
2422 d[jss::expected_date_UTC] =
to_string(*expected);
2426 if (warnings.size())
2427 info[jss::warnings] = std::move(warnings);
2442 info[jss::time] =
to_string(std::chrono::floor<std::chrono::microseconds>(
2446 info[jss::network_ledger] =
"waiting";
2448 info[jss::validation_quorum] =
2456 info[jss::node_size] =
"tiny";
2459 info[jss::node_size] =
"small";
2462 info[jss::node_size] =
"medium";
2465 info[jss::node_size] =
"large";
2468 info[jss::node_size] =
"huge";
2477 info[jss::validator_list_expires] =
2478 safe_cast<Json::UInt>(when->time_since_epoch().count());
2480 info[jss::validator_list_expires] = 0;
2490 if (*when == TimeKeeper::time_point::max())
2492 x[jss::expiration] =
"never";
2493 x[jss::status] =
"active";
2500 x[jss::status] =
"active";
2502 x[jss::status] =
"expired";
2507 x[jss::status] =
"unknown";
2508 x[jss::expiration] =
"unknown";
2512#if defined(GIT_COMMIT_HASH) || defined(GIT_BRANCH)
2515#ifdef GIT_COMMIT_HASH
2516 x[jss::hash] = GIT_COMMIT_HASH;
2519 x[jss::branch] = GIT_BRANCH;
2524 info[jss::io_latency_ms] =
2532 info[jss::pubkey_validator] =
2537 info[jss::pubkey_validator] =
"none";
2547 info[jss::counters][jss::nodestore] = nodestore;
2551 info[jss::pubkey_node] =
2557 info[jss::amendment_blocked] =
true;
2571 lastClose[jss::converge_time_s] =
2576 lastClose[jss::converge_time] =
2580 info[jss::last_close] = lastClose;
2588 info[jss::network_id] =
static_cast<Json::UInt>(*netid);
2590 auto const escalationMetrics =
2598 auto const loadFactorFeeEscalation =
2600 escalationMetrics.openLedgerFeeLevel,
2602 escalationMetrics.referenceFeeLevel)
2606 safe_cast<std::uint64_t>(loadFactorServer), loadFactorFeeEscalation);
2610 info[jss::load_base] = loadBaseServer;
2611 info[jss::load_factor] =
trunc32(loadFactor);
2612 info[jss::load_factor_server] = loadFactorServer;
2619 info[jss::load_factor_fee_escalation] =
2620 escalationMetrics.openLedgerFeeLevel.jsonClipped();
2621 info[jss::load_factor_fee_queue] =
2622 escalationMetrics.minProcessingFeeLevel.jsonClipped();
2623 info[jss::load_factor_fee_reference] =
2624 escalationMetrics.referenceFeeLevel.jsonClipped();
2628 info[jss::load_factor] =
2629 static_cast<double>(loadFactor) / loadBaseServer;
2631 if (loadFactorServer != loadFactor)
2632 info[jss::load_factor_server] =
2633 static_cast<double>(loadFactorServer) / loadBaseServer;
2638 if (fee != loadBaseServer)
2639 info[jss::load_factor_local] =
2640 static_cast<double>(fee) / loadBaseServer;
2642 if (fee != loadBaseServer)
2643 info[jss::load_factor_net] =
2644 static_cast<double>(fee) / loadBaseServer;
2646 if (fee != loadBaseServer)
2647 info[jss::load_factor_cluster] =
2648 static_cast<double>(fee) / loadBaseServer;
2650 if (escalationMetrics.openLedgerFeeLevel !=
2651 escalationMetrics.referenceFeeLevel &&
2652 (admin || loadFactorFeeEscalation != loadFactor))
2653 info[jss::load_factor_fee_escalation] =
2654 escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2655 escalationMetrics.referenceFeeLevel);
2656 if (escalationMetrics.minProcessingFeeLevel !=
2657 escalationMetrics.referenceFeeLevel)
2658 info[jss::load_factor_fee_queue] =
2659 escalationMetrics.minProcessingFeeLevel.decimalFromReference(
2660 escalationMetrics.referenceFeeLevel);
2673 XRPAmount const baseFee = lpClosed->fees().base;
2675 l[jss::seq] =
Json::UInt(lpClosed->info().seq);
2676 l[jss::hash] =
to_string(lpClosed->info().hash);
2681 l[jss::reserve_base] =
2682 lpClosed->fees().accountReserve(0).jsonClipped();
2683 l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2685 lpClosed->info().closeTime.time_since_epoch().count());
2690 l[jss::reserve_base_xrp] =
2691 lpClosed->fees().accountReserve(0).decimalXRP();
2692 l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2695 std::abs(closeOffset.count()) >= 60)
2696 l[jss::close_time_offset] =
2704 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2708 auto lCloseTime = lpClosed->info().closeTime;
2710 if (lCloseTime <= closeTime)
2712 using namespace std::chrono_literals;
2713 auto age = closeTime - lCloseTime;
2715 Json::UInt(age < highAgeThreshold ? age.count() : 0);
2721 info[jss::validated_ledger] = l;
2723 info[jss::closed_ledger] = l;
2727 info[jss::published_ledger] =
"none";
2728 else if (lpPublished->info().seq != lpClosed->info().seq)
2729 info[jss::published_ledger] = lpPublished->info().seq;
2734 info[jss::jq_trans_overflow] =
2736 info[jss::peer_disconnects] =
2738 info[jss::peer_disconnects_resources] =
2743 "http",
"https",
"peer",
"ws",
"ws2",
"wss",
"wss2"};
2751 !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() &&
2752 port.admin_user.empty() && port.admin_password.empty()))
2766 for (
auto const& p : proto)
2767 jv[jss::protocol].append(p);
2774 auto const optPort = grpcSection.
get(
"port");
2775 if (optPort && grpcSection.get(
"ip"))
2778 jv[jss::port] = *optPort;
2780 jv[jss::protocol].append(
"grpc");
2783 info[jss::ports] = std::move(ports);
2808 transJson(transaction, result,
false, ledger, std::nullopt);
2822 [&](
Json::Value const& jv) { p->send(jv, true); });
2845 alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted,
app_);
2847 lpAccepted->info().hash, alpAccepted);
2851 alpAccepted->getLedger().
get() == lpAccepted.
get(),
2852 "ripple::NetworkOPsImp::pubLedger : accepted input");
2856 <<
"Publishing ledger " << lpAccepted->info().seq <<
" "
2857 << lpAccepted->info().hash;
2865 jvObj[jss::type] =
"ledgerClosed";
2866 jvObj[jss::ledger_index] = lpAccepted->info().seq;
2867 jvObj[jss::ledger_hash] =
to_string(lpAccepted->info().hash);
2869 lpAccepted->info().closeTime.time_since_epoch().count());
2871 if (!lpAccepted->rules().enabled(featureXRPFees))
2873 jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2874 jvObj[jss::reserve_base] =
2875 lpAccepted->fees().accountReserve(0).jsonClipped();
2876 jvObj[jss::reserve_inc] =
2877 lpAccepted->fees().increment.jsonClipped();
2879 jvObj[jss::txn_count] =
Json::UInt(alpAccepted->size());
2883 jvObj[jss::validated_ledgers] =
2893 p->send(jvObj,
true);
2911 p->send(jvObj,
true);
2920 static bool firstTime =
true;
2927 for (
auto& inner : outer.second)
2929 auto& subInfo = inner.second;
2930 if (subInfo.index_->separationLedgerSeq_ == 0)
2933 alpAccepted->getLedger(), subInfo);
2942 for (
auto const& accTx : *alpAccepted)
2946 lpAccepted, *accTx, accTx == *(--alpAccepted->end()));
2973 "reportConsensusStateChange->pubConsensus",
3004 jvObj[jss::type] =
"transaction";
3008 jvObj[jss::transaction] =
3015 jvObj[jss::meta], *ledger, transaction, meta->
get());
3017 jvObj[jss::meta], transaction, meta->
get());
3020 if (!ledger->open())
3021 jvObj[jss::ledger_hash] =
to_string(ledger->info().hash);
3025 jvObj[jss::ledger_index] = ledger->info().seq;
3026 jvObj[jss::transaction][jss::date] =
3027 ledger->info().closeTime.time_since_epoch().count();
3028 jvObj[jss::validated] =
true;
3029 jvObj[jss::close_time_iso] =
to_string_iso(ledger->info().closeTime);
3035 jvObj[jss::validated] =
false;
3036 jvObj[jss::ledger_current_index] = ledger->info().seq;
3039 jvObj[jss::status] = validated ?
"closed" :
"proposed";
3040 jvObj[jss::engine_result] = sToken;
3041 jvObj[jss::engine_result_code] = result;
3042 jvObj[jss::engine_result_message] = sHuman;
3044 if (transaction->getTxnType() == ttOFFER_CREATE)
3046 auto const account = transaction->getAccountID(sfAccount);
3047 auto const amount = transaction->getFieldAmount(sfTakerGets);
3050 if (account != amount.issue().account)
3058 jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3066 [&]<
unsigned Version>(
3068 RPC::insertDeliverMax(
3069 jvTx[jss::transaction], transaction->getTxnType(), Version);
3071 if constexpr (Version > 1)
3073 jvTx[jss::tx_json] = jvTx.removeMember(jss::transaction);
3074 jvTx[jss::hash] = hash;
3078 jvTx[jss::transaction][jss::hash] = hash;
3091 auto const& stTxn = transaction.
getTxn();
3095 auto const trResult = transaction.
getResult();
3110 [&](
Json::Value const& jv) { p->send(jv, true); });
3127 [&](
Json::Value const& jv) { p->send(jv, true); });
3152 auto const currLedgerSeq = ledger->seq();
3159 for (
auto const& affectedAccount : transaction.
getAffected())
3164 auto it = simiIt->second.begin();
3166 while (it != simiIt->second.end())
3177 it = simiIt->second.erase(it);
3184 auto it = simiIt->second.begin();
3185 while (it != simiIt->second.end())
3196 it = simiIt->second.erase(it);
3203 auto& subs = histoIt->second;
3204 auto it = subs.begin();
3205 while (it != subs.end())
3208 if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3222 it = subs.erase(it);
3233 <<
"pubAccountTransaction: " <<
"proposed=" << iProposed
3234 <<
", accepted=" << iAccepted;
3236 if (!notify.
empty() || !accountHistoryNotify.
empty())
3238 auto const& stTxn = transaction.
getTxn();
3242 auto const trResult = transaction.
getResult();
3248 isrListener->getApiVersion(),
3249 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3253 jvObj.
set(jss::account_history_boundary,
true);
3256 jvObj.
isMember(jss::account_history_tx_stream) ==
3258 "ripple::NetworkOPsImp::pubAccountTransaction : "
3259 "account_history_tx_stream not set");
3260 for (
auto& info : accountHistoryNotify)
3262 auto& index = info.index_;
3263 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3264 jvObj.
set(jss::account_history_tx_first,
true);
3266 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3269 info.sink_->getApiVersion(),
3270 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3295 for (
auto const& affectedAccount : tx->getMentionedAccounts())
3300 auto it = simiIt->second.begin();
3302 while (it != simiIt->second.end())
3313 it = simiIt->second.erase(it);
3320 JLOG(
m_journal.
trace()) <<
"pubProposedAccountTransaction: " << iProposed;
3322 if (!notify.
empty() || !accountHistoryNotify.
empty())
3329 isrListener->getApiVersion(),
3330 [&](
Json::Value const& jv) { isrListener->send(jv, true); });
3333 jvObj.
isMember(jss::account_history_tx_stream) ==
3335 "ripple::NetworkOPs::pubProposedAccountTransaction : "
3336 "account_history_tx_stream not set");
3337 for (
auto& info : accountHistoryNotify)
3339 auto& index = info.index_;
3340 if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3341 jvObj.
set(jss::account_history_tx_first,
true);
3342 jvObj.
set(jss::account_history_tx_index, index->forwardTxIndex_++);
3344 info.sink_->getApiVersion(),
3345 [&](
Json::Value const& jv) { info.sink_->send(jv, true); });
3362 for (
auto const& naAccountID : vnaAccountIDs)
3365 <<
"subAccount: account: " <<
toBase58(naAccountID);
3367 isrListener->insertSubAccountInfo(naAccountID, rt);
3372 for (
auto const& naAccountID : vnaAccountIDs)
3374 auto simIterator = subMap.
find(naAccountID);
3375 if (simIterator == subMap.
end())
3379 usisElement[isrListener->getSeq()] = isrListener;
3381 subMap.
insert(simIterator, make_pair(naAccountID, usisElement));
3386 simIterator->second[isrListener->getSeq()] = isrListener;
3397 for (
auto const& naAccountID : vnaAccountIDs)
3400 isrListener->deleteSubAccountInfo(naAccountID, rt);
3417 for (
auto const& naAccountID : vnaAccountIDs)
3419 auto simIterator = subMap.
find(naAccountID);
3421 if (simIterator != subMap.
end())
3424 simIterator->second.erase(uSeq);
3426 if (simIterator->second.empty())
3429 subMap.
erase(simIterator);
3438 enum DatabaseType { Sqlite,
None };
3439 static const auto databaseType = [&]() -> DatabaseType {
3444 return DatabaseType::Sqlite;
3446 return DatabaseType::None;
3449 if (databaseType == DatabaseType::None)
3452 <<
"AccountHistory job for account "
3464 "AccountHistoryTxStream",
3465 [
this, dbType = databaseType, subInfo]() {
3466 auto const& accountId = subInfo.
index_->accountId_;
3467 auto& lastLedgerSeq = subInfo.
index_->historyLastLedgerSeq_;
3468 auto& txHistoryIndex = subInfo.
index_->historyTxIndex_;
3471 <<
"AccountHistory job for account " <<
toBase58(accountId)
3472 <<
" started. lastLedgerSeq=" << lastLedgerSeq;
3482 auto stx = tx->getSTransaction();
3483 if (stx->getAccountID(sfAccount) == accountId &&
3484 stx->getSeqProxy().value() == 1)
3488 for (
auto& node : meta->getNodes())
3490 if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3493 if (node.isFieldPresent(sfNewFields))
3495 if (
auto inner =
dynamic_cast<const STObject*
>(
3496 node.peekAtPField(sfNewFields));
3499 if (inner->isFieldPresent(sfAccount) &&
3500 inner->getAccountID(sfAccount) == accountId)
3512 bool unsubscribe) ->
bool {
3515 sptr->send(jvObj,
true);
3525 bool unsubscribe) ->
bool {
3529 sptr->getApiVersion(),
3530 [&](
Json::Value const& jv) { sptr->send(jv,
true); });
3553 accountId, minLedger, maxLedger, marker, 0,
true};
3554 return db->newestAccountTxPage(options);
3558 "ripple::NetworkOPsImp::addAccountHistoryJob::"
3559 "getMoreTxns : invalid database type");
3568 while (lastLedgerSeq >= 2 && !subInfo.
index_->stopHistorical_)
3570 int feeChargeCount = 0;
3579 <<
"AccountHistory job for account "
3580 <<
toBase58(accountId) <<
" no InfoSub. Fee charged "
3581 << feeChargeCount <<
" times.";
3586 auto startLedgerSeq =
3587 (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3589 <<
"AccountHistory job for account " <<
toBase58(accountId)
3590 <<
", working on ledger range [" << startLedgerSeq <<
","
3591 << lastLedgerSeq <<
"]";
3593 auto haveRange = [&]() ->
bool {
3596 auto haveSomeValidatedLedgers =
3598 validatedMin, validatedMax);
3600 return haveSomeValidatedLedgers &&
3601 validatedMin <= startLedgerSeq &&
3602 lastLedgerSeq <= validatedMax;
3608 <<
"AccountHistory reschedule job for account "
3609 <<
toBase58(accountId) <<
", incomplete ledger range ["
3610 << startLedgerSeq <<
"," << lastLedgerSeq <<
"]";
3616 while (!subInfo.
index_->stopHistorical_)
3619 getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3623 <<
"AccountHistory job for account "
3624 <<
toBase58(accountId) <<
" getMoreTxns failed.";
3629 auto const& txns = dbResult->first;
3630 marker = dbResult->second;
3631 size_t num_txns = txns.size();
3632 for (
size_t i = 0; i < num_txns; ++i)
3634 auto const& [tx, meta] = txns[i];
3639 <<
"AccountHistory job for account "
3640 <<
toBase58(accountId) <<
" empty tx or meta.";
3650 <<
"AccountHistory job for account "
3651 <<
toBase58(accountId) <<
" no ledger.";
3656 tx->getSTransaction();
3660 <<
"AccountHistory job for account "
3662 <<
" getSTransaction failed.";
3668 auto const trR = meta->getResultTER();
3670 transJson(stTxn, trR,
true, curTxLedger, mRef);
3673 jss::account_history_tx_index, txHistoryIndex--);
3674 if (i + 1 == num_txns ||
3675 txns[i + 1].first->getLedger() != tx->getLedger())
3676 jvTx.
set(jss::account_history_boundary,
true);
3678 if (isFirstTx(tx, meta))
3680 jvTx.
set(jss::account_history_tx_first,
true);
3681 sendMultiApiJson(jvTx,
false);
3684 <<
"AccountHistory job for account "
3686 <<
" done, found last tx.";
3691 sendMultiApiJson(jvTx,
false);
3698 <<
"AccountHistory job for account "
3700 <<
" paging, marker=" << marker->ledgerSeq <<
":"
3709 if (!subInfo.
index_->stopHistorical_)
3711 lastLedgerSeq = startLedgerSeq - 1;
3712 if (lastLedgerSeq <= 1)
3715 <<
"AccountHistory job for account "
3717 <<
" done, reached genesis ledger.";
3730 subInfo.
index_->separationLedgerSeq_ = ledger->seq();
3731 auto const& accountId = subInfo.
index_->accountId_;
3733 if (!ledger->exists(accountKeylet))
3736 <<
"subAccountHistoryStart, no account " <<
toBase58(accountId)
3737 <<
", no need to add AccountHistory job.";
3742 if (
auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3744 if (sleAcct->getFieldU32(sfSequence) == 1)
3747 <<
"subAccountHistoryStart, genesis account "
3749 <<
" does not have tx, no need to add AccountHistory job.";
3756 "ripple::NetworkOPsImp::subAccountHistoryStart : failed to "
3757 "access genesis account");
3761 subInfo.
index_->historyLastLedgerSeq_ = ledger->seq();
3762 subInfo.
index_->haveHistorical_ =
true;
3765 <<
"subAccountHistoryStart, add AccountHistory job: accountId="
3766 <<
toBase58(accountId) <<
", currentLedgerSeq=" << ledger->seq();
3776 if (!isrListener->insertSubAccountHistory(accountId))
3779 <<
"subAccountHistory, already subscribed to account "
3786 isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3791 inner.
emplace(isrListener->getSeq(), ahi);
3797 simIterator->second.emplace(isrListener->getSeq(), ahi);
3811 <<
"subAccountHistory, no validated ledger yet, delay start";
3824 isrListener->deleteSubAccountHistory(account);
3838 auto& subInfoMap = simIterator->second;
3839 auto subInfoIter = subInfoMap.find(seq);
3840 if (subInfoIter != subInfoMap.end())
3842 subInfoIter->second.index_->stopHistorical_ =
true;
3847 simIterator->second.erase(seq);
3848 if (simIterator->second.empty())
3854 <<
"unsubAccountHistory, account " <<
toBase58(account)
3855 <<
", historyOnly = " << (historyOnly ?
"true" :
"false");
3863 listeners->addSubscriber(isrListener);
3865 UNREACHABLE(
"ripple::NetworkOPsImp::subBook : null book listeners");
3873 listeners->removeSubscriber(uSeq);
3885 m_standalone,
"ripple::NetworkOPsImp::acceptLedger : is standalone");
3888 Throw<std::runtime_error>(
3889 "Operation only possible in STANDALONE mode.");
3904 jvResult[jss::ledger_index] = lpClosed->info().seq;
3905 jvResult[jss::ledger_hash] =
to_string(lpClosed->info().hash);
3907 lpClosed->info().closeTime.time_since_epoch().count());
3908 if (!lpClosed->rules().enabled(featureXRPFees))
3910 jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
3911 jvResult[jss::reserve_base] =
3912 lpClosed->fees().accountReserve(0).jsonClipped();
3913 jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
3918 jvResult[jss::validated_ledgers] =
3924 .emplace(isrListener->getSeq(), isrListener)
3934 .emplace(isrListener->getSeq(), isrListener)
3960 .emplace(isrListener->getSeq(), isrListener)
3988 jvResult[jss::random] =
to_string(uRandom);
3990 jvResult[jss::load_base] = feeTrack.getLoadBase();
3991 jvResult[jss::load_factor] = feeTrack.getLoadFactor();
3992 jvResult[jss::hostid] =
getHostId(admin);
3993 jvResult[jss::pubkey_node] =
3998 .emplace(isrListener->getSeq(), isrListener)
4016 .emplace(isrListener->getSeq(), isrListener)
4034 .emplace(isrListener->getSeq(), isrListener)
4052 .emplace(isrListener->getSeq(), isrListener)
4076 .emplace(isrListener->getSeq(), isrListener)
4094 .emplace(isrListener->getSeq(), isrListener)
4142 if (map.find(pInfo->getSeq()) != map.end())
4149#ifndef USE_NEW_BOOK_PAGE
4160 unsigned int iLimit,
4170 uint256 uTipIndex = uBookBase;
4174 stream <<
"getBookPage:" << book;
4175 stream <<
"getBookPage: uBookBase=" << uBookBase;
4176 stream <<
"getBookPage: uBookEnd=" << uBookEnd;
4177 stream <<
"getBookPage: uTipIndex=" << uTipIndex;
4186 bool bDirectAdvance =
true;
4190 unsigned int uBookEntry;
4196 while (!bDone && iLimit-- > 0)
4200 bDirectAdvance =
false;
4204 auto const ledgerIndex = view.
succ(uTipIndex, uBookEnd);
4208 sleOfferDir.
reset();
4217 uTipIndex = sleOfferDir->key();
4220 cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4223 <<
"getBookPage: uTipIndex=" << uTipIndex;
4225 <<
"getBookPage: offerIndex=" << offerIndex;
4235 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4236 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4237 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4239 bool firstOwnerOffer(
true);
4245 saOwnerFunds = saTakerGets;
4247 else if (bGlobalFreeze)
4255 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4256 if (umBalanceEntry != umBalance.
end())
4260 saOwnerFunds = umBalanceEntry->second;
4261 firstOwnerOffer =
false;
4275 if (saOwnerFunds < beast::zero)
4279 saOwnerFunds.
clear();
4287 STAmount saOwnerFundsLimit = saOwnerFunds;
4299 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4302 if (saOwnerFundsLimit >= saTakerGets)
4305 saTakerGetsFunded = saTakerGets;
4311 saTakerGetsFunded = saOwnerFundsLimit;
4313 saTakerGetsFunded.
setJson(jvOffer[jss::taker_gets_funded]);
4317 saTakerGetsFunded, saDirRate, saTakerPays.
issue()))
4318 .setJson(jvOffer[jss::taker_pays_funded]);
4324 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4326 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4330 jvOf[jss::quality] = saDirRate.
getText();
4332 if (firstOwnerOffer)
4333 jvOf[jss::owner_funds] = saOwnerFunds.
getText();
4340 if (!
cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4342 bDirectAdvance =
true;
4347 <<
"getBookPage: offerIndex=" << offerIndex;
4367 unsigned int iLimit,
4375 MetaView lesActive(lpLedger,
tapNONE,
true);
4376 OrderBookIterator obIterator(lesActive, book);
4380 const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.
out.
account) ||
4381 lesActive.isGlobalFrozen(book.
in.
account);
4383 while (iLimit-- > 0 && obIterator.nextOffer())
4388 auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4389 auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4390 auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4391 STAmount saDirRate = obIterator.getCurrentRate();
4397 saOwnerFunds = saTakerGets;
4399 else if (bGlobalFreeze)
4407 auto umBalanceEntry = umBalance.
find(uOfferOwnerID);
4409 if (umBalanceEntry != umBalance.
end())
4413 saOwnerFunds = umBalanceEntry->second;
4419 saOwnerFunds = lesActive.accountHolds(
4425 if (saOwnerFunds.isNegative())
4429 saOwnerFunds.zero();
4436 STAmount saTakerGetsFunded;
4437 STAmount saOwnerFundsLimit = saOwnerFunds;
4449 saOwnerFundsLimit =
divide(saOwnerFunds, offerRate);
4452 if (saOwnerFundsLimit >= saTakerGets)
4455 saTakerGetsFunded = saTakerGets;
4460 saTakerGetsFunded = saOwnerFundsLimit;
4462 saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4468 multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4469 .setJson(jvOffer[jss::taker_pays_funded]);
4472 STAmount saOwnerPays = (
parityRate == offerRate)
4475 saOwnerFunds,
multiply(saTakerGetsFunded, offerRate));
4477 umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4479 if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4483 jvOf[jss::quality] = saDirRate.
getText();
4498 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4538 ++counters_[
static_cast<std::size_t>(om)].transitions;
4540 counters_[
static_cast<std::size_t>(om)].transitions == 1)
4542 initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4543 now - processStart_)
4547 std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4556 auto [counters, mode, start, initialSync] = getCounterData();
4557 auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4567 auto& state = obj[jss::state_accounting][
states_[i]];
4568 state[jss::transitions] =
std::to_string(counters[i].transitions);
4569 state[jss::duration_us] =
std::to_string(counters[i].dur.count());
4573 obj[jss::initial_sync_duration_us] =
std::to_string(initialSync);
4588 boost::asio::io_service& io_svc,
4592 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_
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
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
void endConsensus() 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 beginConsensus(uint256 const &networkClosed) override
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.
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)