rippled
NetworkOPs.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/consensus/RCLConsensus.h>
21 #include <ripple/app/consensus/RCLValidations.h>
22 #include <ripple/app/ledger/AcceptedLedger.h>
23 #include <ripple/app/ledger/InboundLedgers.h>
24 #include <ripple/app/ledger/LedgerMaster.h>
25 #include <ripple/app/ledger/LedgerToJson.h>
26 #include <ripple/app/ledger/LocalTxs.h>
27 #include <ripple/app/ledger/OpenLedger.h>
28 #include <ripple/app/ledger/OrderBookDB.h>
29 #include <ripple/app/ledger/TransactionMaster.h>
30 #include <ripple/app/main/LoadManager.h>
31 #include <ripple/app/misc/AmendmentTable.h>
32 #include <ripple/app/misc/HashRouter.h>
33 #include <ripple/app/misc/LoadFeeTrack.h>
34 #include <ripple/app/misc/NetworkOPs.h>
35 #include <ripple/app/misc/Transaction.h>
36 #include <ripple/app/misc/TxQ.h>
37 #include <ripple/app/misc/ValidatorKeys.h>
38 #include <ripple/app/misc/ValidatorList.h>
39 #include <ripple/app/misc/impl/AccountTxPaging.h>
40 #include <ripple/app/rdb/backend/PostgresDatabase.h>
41 #include <ripple/app/rdb/backend/SQLiteDatabase.h>
42 #include <ripple/app/reporting/ReportingETL.h>
43 #include <ripple/app/tx/apply.h>
44 #include <ripple/basics/PerfLog.h>
45 #include <ripple/basics/UptimeClock.h>
46 #include <ripple/basics/mulDiv.h>
47 #include <ripple/basics/safe_cast.h>
48 #include <ripple/beast/rfc2616.h>
49 #include <ripple/beast/utility/rngfill.h>
50 #include <ripple/consensus/Consensus.h>
51 #include <ripple/consensus/ConsensusParms.h>
52 #include <ripple/crypto/RFC1751.h>
53 #include <ripple/crypto/csprng.h>
54 #include <ripple/json/to_string.h>
55 #include <ripple/net/RPCErr.h>
56 #include <ripple/nodestore/DatabaseShard.h>
57 #include <ripple/overlay/Cluster.h>
58 #include <ripple/overlay/Overlay.h>
59 #include <ripple/overlay/predicates.h>
60 #include <ripple/protocol/BuildInfo.h>
61 #include <ripple/protocol/Feature.h>
62 #include <ripple/protocol/STParsedJSON.h>
63 #include <ripple/resource/Fees.h>
64 #include <ripple/resource/ResourceManager.h>
65 #include <ripple/rpc/BookChanges.h>
66 #include <ripple/rpc/DeliveredAmount.h>
67 #include <ripple/rpc/impl/RPCHelpers.h>
68 #include <boost/asio/ip/host_name.hpp>
69 #include <boost/asio/steady_timer.hpp>
70 
71 #include <mutex>
72 #include <string>
73 #include <tuple>
74 #include <unordered_map>
75 #include <utility>
76 
77 namespace ripple {
78 
79 class NetworkOPsImp final : public NetworkOPs
80 {
86  {
87  public:
89  bool const admin;
90  bool const local;
92  bool applied = false;
94 
97  bool a,
98  bool l,
99  FailHard f)
100  : transaction(t), admin(a), local(l), failType(f)
101  {
102  assert(local || failType == FailHard::no);
103  }
104  };
105 
109  enum class DispatchState : unsigned char {
110  none,
111  scheduled,
112  running,
113  };
114 
116 
132  {
133  struct Counters
134  {
135  explicit Counters() = default;
136 
139  };
140 
144  std::chrono::steady_clock::time_point start_ =
146  std::chrono::steady_clock::time_point const processStart_ = start_;
149 
150  public:
151  explicit StateAccounting()
152  {
154  .transitions = 1;
155  }
156 
163  void
164  mode(OperatingMode om);
165 
171  void
172  json(Json::Value& obj) const;
173 
174  struct CounterData
175  {
176  decltype(counters_) counters;
177  decltype(mode_) mode;
178  decltype(start_) start;
180  };
181 
184  {
185  std::lock_guard lock(mutex_);
186  return {counters_, mode_, start_, initialSyncUs_};
187  }
188  };
189 
192  {
193  ServerFeeSummary() = default;
194 
196  XRPAmount fee,
197  TxQ::Metrics&& escalationMetrics,
198  LoadFeeTrack const& loadFeeTrack);
199  bool
200  operator!=(ServerFeeSummary const& b) const;
201 
202  bool
203  operator==(ServerFeeSummary const& b) const
204  {
205  return !(*this != b);
206  }
207 
212  };
213 
214 public:
216  Application& app,
217  NetworkOPs::clock_type& clock,
218  bool standalone,
219  std::size_t minPeerCount,
220  bool start_valid,
221  JobQueue& job_queue,
222  LedgerMaster& ledgerMaster,
223  ValidatorKeys const& validatorKeys,
224  boost::asio::io_service& io_svc,
225  beast::Journal journal,
226  beast::insight::Collector::ptr const& collector)
227  : app_(app)
228  , m_journal(journal)
230  , mMode(start_valid ? OperatingMode::FULL : OperatingMode::DISCONNECTED)
231  , heartbeatTimer_(io_svc)
232  , clusterTimer_(io_svc)
233  , accountHistoryTxTimer_(io_svc)
234  , mConsensus(
235  app,
236  make_FeeVote(
237  setup_FeeVote(app_.config().section("voting")),
238  app_.logs().journal("FeeVote")),
239  ledgerMaster,
240  *m_localTX,
241  app.getInboundTransactions(),
242  beast::get_abstract_clock<std::chrono::steady_clock>(),
243  validatorKeys,
244  app_.logs().journal("LedgerConsensus"))
246  , m_job_queue(job_queue)
247  , m_standalone(standalone)
248  , minPeerCount_(start_valid ? 0 : minPeerCount)
249  , m_stats(std::bind(&NetworkOPsImp::collect_metrics, this), collector)
250  {
251  }
252 
253  ~NetworkOPsImp() override
254  {
255  // This clear() is necessary to ensure the shared_ptrs in this map get
256  // destroyed NOW because the objects in this map invoke methods on this
257  // class when they are destroyed
258  mRpcSubMap.clear();
259  }
260 
261 public:
263  getOperatingMode() const override;
264 
266  strOperatingMode(OperatingMode const mode, bool const admin) const override;
267 
269  strOperatingMode(bool const admin = false) const override;
270 
271  //
272  // Transaction operations.
273  //
274 
275  // Must complete immediately.
276  void
278 
279  void
281  std::shared_ptr<Transaction>& transaction,
282  bool bUnlimited,
283  bool bLocal,
284  FailHard failType) override;
285 
294  void
296  std::shared_ptr<Transaction> transaction,
297  bool bUnlimited,
298  FailHard failType);
299 
309  void
311  std::shared_ptr<Transaction> transaction,
312  bool bUnlimited,
313  FailHard failtype);
314 
318  void
320 
326  void
328 
329  //
330  // Owner functions.
331  //
332 
334  getOwnerInfo(
336  AccountID const& account) override;
337 
338  //
339  // Book functions.
340  //
341 
342  void
343  getBookPage(
345  Book const&,
346  AccountID const& uTakerID,
347  const bool bProof,
348  unsigned int iLimit,
349  Json::Value const& jvMarker,
350  Json::Value& jvResult) override;
351 
352  // Ledger proposal/close functions.
353  bool
354  processTrustedProposal(RCLCxPeerPos proposal) override;
355 
356  bool
359  std::string const& source) override;
360 
361  void
362  mapComplete(std::shared_ptr<SHAMap> const& map, bool fromAcquire) override;
363 
364  // Network state machine.
365 
366  // Used for the "jump" case.
367 private:
368  void
370  bool
371  checkLastClosedLedger(const Overlay::PeerSequence&, uint256& networkClosed);
372 
373 public:
374  bool
375  beginConsensus(uint256 const& networkClosed) override;
376  void
377  endConsensus() override;
378  void
379  setStandAlone() override;
380 
384  void
385  setStateTimer() override;
386 
387  void
388  setNeedNetworkLedger() override;
389  void
390  clearNeedNetworkLedger() override;
391  bool
392  isNeedNetworkLedger() override;
393  bool
394  isFull() override;
395 
396  void
397  setMode(OperatingMode om) override;
398 
399  bool
400  isBlocked() override;
401  bool
402  isAmendmentBlocked() override;
403  void
404  setAmendmentBlocked() override;
405  bool
406  isAmendmentWarned() override;
407  void
408  setAmendmentWarned() override;
409  void
410  clearAmendmentWarned() override;
411  bool
412  isUNLBlocked() override;
413  void
414  setUNLBlocked() override;
415  void
416  clearUNLBlocked() override;
417  void
418  consensusViewChange() override;
419 
421  getConsensusInfo() override;
423  getServerInfo(bool human, bool admin, bool counters) override;
424  void
425  clearLedgerFetch() override;
427  getLedgerFetchInfo() override;
429  acceptLedger(
430  std::optional<std::chrono::milliseconds> consensusDelay) override;
431  void
432  reportFeeChange() override;
433  void
435 
436  void
437  updateLocalTx(ReadView const& view) override;
439  getLocalTxCount() override;
440 
441  //
442  // Monitoring: publisher side.
443  //
444  void
445  pubLedger(std::shared_ptr<ReadView const> const& lpAccepted) override;
446  void
448  std::shared_ptr<ReadView const> const& ledger,
449  std::shared_ptr<STTx const> const& transaction,
450  TER result) override;
451  void
452  pubValidation(std::shared_ptr<STValidation> const& val) override;
453 
454  void
455  forwardValidation(Json::Value const& jvObj) override;
456  void
457  forwardManifest(Json::Value const& jvObj) override;
458  void
459  forwardProposedTransaction(Json::Value const& jvObj) override;
460  void
461  forwardProposedAccountTransaction(Json::Value const& jvObj) override;
462 
463  //--------------------------------------------------------------------------
464  //
465  // InfoSub::Source.
466  //
467  void
468  subAccount(
469  InfoSub::ref ispListener,
470  hash_set<AccountID> const& vnaAccountIDs,
471  bool rt) override;
472  void
473  unsubAccount(
474  InfoSub::ref ispListener,
475  hash_set<AccountID> const& vnaAccountIDs,
476  bool rt) override;
477 
478  // Just remove the subscription from the tracking
479  // not from the InfoSub. Needed for InfoSub destruction
480  void
482  std::uint64_t seq,
483  hash_set<AccountID> const& vnaAccountIDs,
484  bool rt) override;
485 
487  subAccountHistory(InfoSub::ref ispListener, AccountID const& account)
488  override;
489  void
491  InfoSub::ref ispListener,
492  AccountID const& account,
493  bool historyOnly) override;
494 
495  void
497  std::uint64_t seq,
498  AccountID const& account,
499  bool historyOnly) override;
500 
501  bool
502  subLedger(InfoSub::ref ispListener, Json::Value& jvResult) override;
503  bool
504  unsubLedger(std::uint64_t uListener) override;
505 
506  bool
507  subBookChanges(InfoSub::ref ispListener) override;
508  bool
509  unsubBookChanges(std::uint64_t uListener) override;
510 
511  bool
512  subServer(InfoSub::ref ispListener, Json::Value& jvResult, bool admin)
513  override;
514  bool
515  unsubServer(std::uint64_t uListener) override;
516 
517  bool
518  subBook(InfoSub::ref ispListener, Book const&) override;
519  bool
520  unsubBook(std::uint64_t uListener, Book const&) override;
521 
522  bool
523  subManifests(InfoSub::ref ispListener) override;
524  bool
525  unsubManifests(std::uint64_t uListener) override;
526  void
527  pubManifest(Manifest const&) override;
528 
529  bool
530  subTransactions(InfoSub::ref ispListener) override;
531  bool
532  unsubTransactions(std::uint64_t uListener) override;
533 
534  bool
535  subRTTransactions(InfoSub::ref ispListener) override;
536  bool
537  unsubRTTransactions(std::uint64_t uListener) override;
538 
539  bool
540  subValidations(InfoSub::ref ispListener) override;
541  bool
542  unsubValidations(std::uint64_t uListener) override;
543 
544  bool
545  subPeerStatus(InfoSub::ref ispListener) override;
546  bool
547  unsubPeerStatus(std::uint64_t uListener) override;
548  void
549  pubPeerStatus(std::function<Json::Value(void)> const&) override;
550 
551  bool
552  subConsensus(InfoSub::ref ispListener) override;
553  bool
554  unsubConsensus(std::uint64_t uListener) override;
555 
557  findRpcSub(std::string const& strUrl) override;
559  addRpcSub(std::string const& strUrl, InfoSub::ref) override;
560  bool
561  tryRemoveRpcSub(std::string const& strUrl) override;
562 
563  void
564  stop() override
565  {
566  {
567  boost::system::error_code ec;
568  heartbeatTimer_.cancel(ec);
569  if (ec)
570  {
571  JLOG(m_journal.error())
572  << "NetworkOPs: heartbeatTimer cancel error: "
573  << ec.message();
574  }
575 
576  ec.clear();
577  clusterTimer_.cancel(ec);
578  if (ec)
579  {
580  JLOG(m_journal.error())
581  << "NetworkOPs: clusterTimer cancel error: "
582  << ec.message();
583  }
584 
585  ec.clear();
586  accountHistoryTxTimer_.cancel(ec);
587  if (ec)
588  {
589  JLOG(m_journal.error())
590  << "NetworkOPs: accountHistoryTxTimer cancel error: "
591  << ec.message();
592  }
593  }
594  // Make sure that any waitHandlers pending in our timers are done.
595  using namespace std::chrono_literals;
596  waitHandlerCounter_.join("NetworkOPs", 1s, m_journal);
597  }
598 
599  void
600  stateAccounting(Json::Value& obj) override;
601 
602 private:
603  void
604  setTimer(
605  boost::asio::steady_timer& timer,
606  std::chrono::milliseconds const& expiry_time,
607  std::function<void()> onExpire,
608  std::function<void()> onError);
609  void
611  void
612  setClusterTimer();
613  void
615  void
617 
619  transJson(
620  const STTx& transaction,
621  TER result,
622  bool validated,
623  std::shared_ptr<ReadView const> const& ledger);
624 
625  void
627  std::shared_ptr<ReadView const> const& ledger,
628  AcceptedLedgerTx const& transaction);
629 
630  void
632  std::shared_ptr<ReadView const> const& ledger,
633  AcceptedLedgerTx const& transaction);
634 
635  void
637  std::shared_ptr<ReadView const> const& ledger,
638  std::shared_ptr<STTx const> const& transaction,
639  TER result);
640 
641  void
642  pubServer();
643  void
645 
647  getHostId(bool forAdmin);
648 
649 private:
653 
654  /*
655  * With a validated ledger to separate history and future, the node
656  * streams historical txns with negative indexes starting from -1,
657  * and streams future txns starting from index 0.
658  * The SubAccountHistoryIndex struct maintains these indexes.
659  * It also has a flag stopHistorical_ for stopping streaming
660  * the historical txns.
661  */
663  {
665  // forward
667  // separate backward and forward
669  // history, backward
674 
676  : accountId_(accountId)
677  , forwardTxIndex_(0)
680  , historyTxIndex_(-1)
681  , haveHistorical_(false)
682  , stopHistorical_(false)
683  {
684  }
685  };
687  {
690  };
692  {
695  };
698 
702  void
704  std::shared_ptr<ReadView const> const& ledger,
705  SubAccountHistoryInfoWeak& subInfo);
706  void
708  void
710 
713 
715 
717 
719 
724 
726  boost::asio::steady_timer heartbeatTimer_;
727  boost::asio::steady_timer clusterTimer_;
728  boost::asio::steady_timer accountHistoryTxTimer_;
729 
731 
733 
735 
738 
740 
742 
743  enum SubTypes {
744  sLedger, // Accepted ledgers.
745  sManifests, // Received validator manifests.
746  sServer, // When server changes connectivity state.
747  sTransactions, // All accepted transactions.
748  sRTTransactions, // All proposed and accepted transactions.
749  sValidations, // Received validations.
750  sPeerStatus, // Peer status changes.
751  sConsensusPhase, // Consensus phase
752  sBookChanges, // Per-ledger order book changes
753 
754  sLastEntry = sBookChanges // as this name implies, any new entry
755  // must be ADDED ABOVE this one
756  };
758 
760 
762 
763  // Whether we are in standalone mode.
764  bool const m_standalone;
765 
766  // The number of nodes that we need to consider ourselves connected.
768 
769  // Transaction batching.
774 
776 
777 private:
778  struct Stats
779  {
780  template <class Handler>
782  Handler const& handler,
783  beast::insight::Collector::ptr const& collector)
784  : hook(collector->make_hook(handler))
785  , disconnected_duration(collector->make_gauge(
786  "State_Accounting",
787  "Disconnected_duration"))
788  , connected_duration(collector->make_gauge(
789  "State_Accounting",
790  "Connected_duration"))
792  collector->make_gauge("State_Accounting", "Syncing_duration"))
793  , tracking_duration(collector->make_gauge(
794  "State_Accounting",
795  "Tracking_duration"))
796  , full_duration(
797  collector->make_gauge("State_Accounting", "Full_duration"))
798  , disconnected_transitions(collector->make_gauge(
799  "State_Accounting",
800  "Disconnected_transitions"))
801  , connected_transitions(collector->make_gauge(
802  "State_Accounting",
803  "Connected_transitions"))
804  , syncing_transitions(collector->make_gauge(
805  "State_Accounting",
806  "Syncing_transitions"))
807  , tracking_transitions(collector->make_gauge(
808  "State_Accounting",
809  "Tracking_transitions"))
811  collector->make_gauge("State_Accounting", "Full_transitions"))
812  {
813  }
814 
821 
827  };
828 
829  std::mutex m_statsMutex; // Mutex to lock m_stats
831 
832 private:
833  void
834  collect_metrics();
835 };
836 
837 //------------------------------------------------------------------------------
838 
840  {"disconnected", "connected", "syncing", "tracking", "full"}};
841 
843 
851 
852 static auto const genesisAccountId = calcAccountID(
853  generateKeyPair(KeyType::secp256k1, generateSeed("masterpassphrase"))
854  .first);
855 
856 //------------------------------------------------------------------------------
857 inline OperatingMode
859 {
860  return mMode;
861 }
862 
863 inline std::string
864 NetworkOPsImp::strOperatingMode(bool const admin /* = false */) const
865 {
866  return strOperatingMode(mMode, admin);
867 }
868 
869 inline void
871 {
873 }
874 
875 inline void
877 {
878  needNetworkLedger_ = true;
879 }
880 
881 inline void
883 {
884  needNetworkLedger_ = false;
885 }
886 
887 inline bool
889 {
890  return needNetworkLedger_;
891 }
892 
893 inline bool
895 {
897 }
898 
901 {
902  static std::string const hostname = boost::asio::ip::host_name();
903 
904  if (forAdmin)
905  return hostname;
906 
907  // For non-admin uses hash the node public key into a
908  // single RFC1751 word:
909  static std::string const shroudedHostId = [this]() {
910  auto const& id = app_.nodeIdentity();
911 
912  return RFC1751::getWordFromBlob(id.first.data(), id.first.size());
913  }();
914 
915  return shroudedHostId;
916 }
917 
918 void
920 {
922 
923  // Only do this work if a cluster is configured
924  if (app_.cluster().size() != 0)
925  setClusterTimer();
926 }
927 
928 void
930  boost::asio::steady_timer& timer,
931  const std::chrono::milliseconds& expiry_time,
932  std::function<void()> onExpire,
933  std::function<void()> onError)
934 {
935  // Only start the timer if waitHandlerCounter_ is not yet joined.
936  if (auto optionalCountedHandler = waitHandlerCounter_.wrap(
937  [this, onExpire, onError](boost::system::error_code const& e) {
938  if ((e.value() == boost::system::errc::success) &&
939  (!m_job_queue.isStopped()))
940  {
941  onExpire();
942  }
943  // Recover as best we can if an unexpected error occurs.
944  if (e.value() != boost::system::errc::success &&
945  e.value() != boost::asio::error::operation_aborted)
946  {
947  // Try again later and hope for the best.
948  JLOG(m_journal.error())
949  << "Timer got error '" << e.message()
950  << "'. Restarting timer.";
951  onError();
952  }
953  }))
954  {
955  timer.expires_from_now(expiry_time);
956  timer.async_wait(std::move(*optionalCountedHandler));
957  }
958 }
959 
960 void
962 {
963  setTimer(
966  [this]() {
967  m_job_queue.addJob(jtNETOP_TIMER, "NetOPs.heartbeat", [this]() {
968  processHeartbeatTimer();
969  });
970  },
971  [this]() { setHeartbeatTimer(); });
972 }
973 
974 void
975 NetworkOPsImp::setClusterTimer()
976 {
977  using namespace std::chrono_literals;
978 
979  setTimer(
980  clusterTimer_,
981  10s,
982  [this]() {
983  m_job_queue.addJob(jtNETOP_CLUSTER, "NetOPs.cluster", [this]() {
984  processClusterTimer();
985  });
986  },
987  [this]() { setClusterTimer(); });
988 }
989 
990 void
991 NetworkOPsImp::setAccountHistoryJobTimer(SubAccountHistoryInfoWeak subInfo)
992 {
993  JLOG(m_journal.debug()) << "Scheduling AccountHistory job for account "
994  << toBase58(subInfo.index_->accountId_);
995  using namespace std::chrono_literals;
996  setTimer(
997  accountHistoryTxTimer_,
998  4s,
999  [this, subInfo]() { addAccountHistoryJob(subInfo); },
1000  [this, subInfo]() { setAccountHistoryJobTimer(subInfo); });
1001 }
1002 
1003 void
1004 NetworkOPsImp::processHeartbeatTimer()
1005 {
1006  {
1007  std::unique_lock lock{app_.getMasterMutex()};
1008 
1009  // VFALCO NOTE This is for diagnosing a crash on exit
1010  LoadManager& mgr(app_.getLoadManager());
1011  mgr.resetDeadlockDetector();
1012 
1013  std::size_t const numPeers = app_.overlay().size();
1014 
1015  // do we have sufficient peers? If not, we are disconnected.
1016  if (numPeers < minPeerCount_)
1017  {
1018  if (mMode != OperatingMode::DISCONNECTED)
1019  {
1020  setMode(OperatingMode::DISCONNECTED);
1021  JLOG(m_journal.warn())
1022  << "Node count (" << numPeers << ") has fallen "
1023  << "below required minimum (" << minPeerCount_ << ").";
1024  }
1025 
1026  // MasterMutex lock need not be held to call setHeartbeatTimer()
1027  lock.unlock();
1028  // We do not call mConsensus.timerEntry until there are enough
1029  // peers providing meaningful inputs to consensus
1030  setHeartbeatTimer();
1031  return;
1032  }
1033 
1034  if (mMode == OperatingMode::DISCONNECTED)
1035  {
1036  setMode(OperatingMode::CONNECTED);
1037  JLOG(m_journal.info())
1038  << "Node count (" << numPeers << ") is sufficient.";
1039  }
1040 
1041  // Check if the last validated ledger forces a change between these
1042  // states.
1043  if (mMode == OperatingMode::SYNCING)
1044  setMode(OperatingMode::SYNCING);
1045  else if (mMode == OperatingMode::CONNECTED)
1046  setMode(OperatingMode::CONNECTED);
1047  }
1048 
1049  mConsensus.timerEntry(app_.timeKeeper().closeTime());
1050 
1051  const ConsensusPhase currPhase = mConsensus.phase();
1052  if (mLastConsensusPhase != currPhase)
1053  {
1054  reportConsensusStateChange(currPhase);
1055  mLastConsensusPhase = currPhase;
1056  }
1057 
1058  setHeartbeatTimer();
1059 }
1060 
1061 void
1062 NetworkOPsImp::processClusterTimer()
1063 {
1064  if (app_.cluster().size() == 0)
1065  return;
1066 
1067  using namespace std::chrono_literals;
1068 
1069  bool const update = app_.cluster().update(
1070  app_.nodeIdentity().first,
1071  "",
1072  (m_ledgerMaster.getValidatedLedgerAge() <= 4min)
1073  ? app_.getFeeTrack().getLocalFee()
1074  : 0,
1075  app_.timeKeeper().now());
1076 
1077  if (!update)
1078  {
1079  JLOG(m_journal.debug()) << "Too soon to send cluster update";
1080  setClusterTimer();
1081  return;
1082  }
1083 
1084  protocol::TMCluster cluster;
1085  app_.cluster().for_each([&cluster](ClusterNode const& node) {
1086  protocol::TMClusterNode& n = *cluster.add_clusternodes();
1087  n.set_publickey(toBase58(TokenType::NodePublic, node.identity()));
1088  n.set_reporttime(node.getReportTime().time_since_epoch().count());
1089  n.set_nodeload(node.getLoadFee());
1090  if (!node.name().empty())
1091  n.set_nodename(node.name());
1092  });
1093 
1094  Resource::Gossip gossip = app_.getResourceManager().exportConsumers();
1095  for (auto& item : gossip.items)
1096  {
1097  protocol::TMLoadSource& node = *cluster.add_loadsources();
1098  node.set_name(to_string(item.address));
1099  node.set_cost(item.balance);
1100  }
1101  app_.overlay().foreach(send_if(
1102  std::make_shared<Message>(cluster, protocol::mtCLUSTER),
1103  peer_in_cluster()));
1104  setClusterTimer();
1105 }
1106 
1107 //------------------------------------------------------------------------------
1108 
1110 NetworkOPsImp::strOperatingMode(OperatingMode const mode, bool const admin)
1111  const
1112 {
1113  if (mode == OperatingMode::FULL && admin)
1114  {
1115  auto const consensusMode = mConsensus.mode();
1116  if (consensusMode != ConsensusMode::wrongLedger)
1117  {
1118  if (consensusMode == ConsensusMode::proposing)
1119  return "proposing";
1120 
1121  if (mConsensus.validating())
1122  return "validating";
1123  }
1124  }
1125 
1126  return states_[static_cast<std::size_t>(mode)];
1127 }
1128 
1129 void
1130 NetworkOPsImp::submitTransaction(std::shared_ptr<STTx const> const& iTrans)
1131 {
1132  if (isNeedNetworkLedger())
1133  {
1134  // Nothing we can do if we've never been in sync
1135  return;
1136  }
1137 
1138  // this is an asynchronous interface
1139  auto const trans = sterilize(*iTrans);
1140 
1141  auto const txid = trans->getTransactionID();
1142  auto const flags = app_.getHashRouter().getFlags(txid);
1143 
1144  if ((flags & SF_BAD) != 0)
1145  {
1146  JLOG(m_journal.warn()) << "Submitted transaction cached bad";
1147  return;
1148  }
1149 
1150  try
1151  {
1152  auto const [validity, reason] = checkValidity(
1153  app_.getHashRouter(),
1154  *trans,
1155  m_ledgerMaster.getValidatedRules(),
1156  app_.config());
1157 
1158  if (validity != Validity::Valid)
1159  {
1160  JLOG(m_journal.warn())
1161  << "Submitted transaction invalid: " << reason;
1162  return;
1163  }
1164  }
1165  catch (std::exception const&)
1166  {
1167  JLOG(m_journal.warn()) << "Exception checking transaction" << txid;
1168 
1169  return;
1170  }
1171 
1172  std::string reason;
1173 
1174  auto tx = std::make_shared<Transaction>(trans, reason, app_);
1175 
1176  m_job_queue.addJob(jtTRANSACTION, "submitTxn", [this, tx]() {
1177  auto t = tx;
1178  processTransaction(t, false, false, FailHard::no);
1179  });
1180 }
1181 
1182 void
1183 NetworkOPsImp::processTransaction(
1184  std::shared_ptr<Transaction>& transaction,
1185  bool bUnlimited,
1186  bool bLocal,
1187  FailHard failType)
1188 {
1189  auto ev = m_job_queue.makeLoadEvent(jtTXN_PROC, "ProcessTXN");
1190  auto const newFlags = app_.getHashRouter().getFlags(transaction->getID());
1191 
1192  if ((newFlags & SF_BAD) != 0)
1193  {
1194  // cached bad
1195  JLOG(m_journal.warn()) << transaction->getID() << ": cached bad!\n";
1196  transaction->setStatus(INVALID);
1197  transaction->setResult(temBAD_SIGNATURE);
1198  return;
1199  }
1200 
1201  // NOTE eahennis - I think this check is redundant,
1202  // but I'm not 100% sure yet.
1203  // If so, only cost is looking up HashRouter flags.
1204  auto const view = m_ledgerMaster.getCurrentLedger();
1205  auto const [validity, reason] = checkValidity(
1206  app_.getHashRouter(),
1207  *transaction->getSTransaction(),
1208  view->rules(),
1209  app_.config());
1210  assert(validity == Validity::Valid);
1211 
1212  // Not concerned with local checks at this point.
1213  if (validity == Validity::SigBad)
1214  {
1215  JLOG(m_journal.info()) << "Transaction has bad signature: " << reason;
1216  transaction->setStatus(INVALID);
1217  transaction->setResult(temBAD_SIGNATURE);
1218  app_.getHashRouter().setFlags(transaction->getID(), SF_BAD);
1219  return;
1220  }
1221 
1222  // canonicalize can change our pointer
1223  app_.getMasterTransaction().canonicalize(&transaction);
1224 
1225  if (bLocal)
1226  doTransactionSync(transaction, bUnlimited, failType);
1227  else
1228  doTransactionAsync(transaction, bUnlimited, failType);
1229 }
1230 
1231 void
1232 NetworkOPsImp::doTransactionAsync(
1233  std::shared_ptr<Transaction> transaction,
1234  bool bUnlimited,
1235  FailHard failType)
1236 {
1237  std::lock_guard lock(mMutex);
1238 
1239  if (transaction->getApplying())
1240  return;
1241 
1242  mTransactions.push_back(
1243  TransactionStatus(transaction, bUnlimited, false, failType));
1244  transaction->setApplying();
1245 
1246  if (mDispatchState == DispatchState::none)
1247  {
1248  if (m_job_queue.addJob(
1249  jtBATCH, "transactionBatch", [this]() { transactionBatch(); }))
1250  {
1251  mDispatchState = DispatchState::scheduled;
1252  }
1253  }
1254 }
1255 
1256 void
1257 NetworkOPsImp::doTransactionSync(
1258  std::shared_ptr<Transaction> transaction,
1259  bool bUnlimited,
1260  FailHard failType)
1261 {
1262  std::unique_lock<std::mutex> lock(mMutex);
1263 
1264  if (!transaction->getApplying())
1265  {
1266  mTransactions.push_back(
1267  TransactionStatus(transaction, bUnlimited, true, failType));
1268  transaction->setApplying();
1269  }
1270 
1271  do
1272  {
1273  if (mDispatchState == DispatchState::running)
1274  {
1275  // A batch processing job is already running, so wait.
1276  mCond.wait(lock);
1277  }
1278  else
1279  {
1280  apply(lock);
1281 
1282  if (mTransactions.size())
1283  {
1284  // More transactions need to be applied, but by another job.
1285  if (m_job_queue.addJob(jtBATCH, "transactionBatch", [this]() {
1286  transactionBatch();
1287  }))
1288  {
1289  mDispatchState = DispatchState::scheduled;
1290  }
1291  }
1292  }
1293  } while (transaction->getApplying());
1294 }
1295 
1296 void
1297 NetworkOPsImp::transactionBatch()
1298 {
1299  std::unique_lock<std::mutex> lock(mMutex);
1300 
1301  if (mDispatchState == DispatchState::running)
1302  return;
1303 
1304  while (mTransactions.size())
1305  {
1306  apply(lock);
1307  }
1308 }
1309 
1310 void
1311 NetworkOPsImp::apply(std::unique_lock<std::mutex>& batchLock)
1312 {
1313  std::vector<TransactionStatus> submit_held;
1314  std::vector<TransactionStatus> transactions;
1315  mTransactions.swap(transactions);
1316  assert(!transactions.empty());
1317 
1318  assert(mDispatchState != DispatchState::running);
1319  mDispatchState = DispatchState::running;
1320 
1321  batchLock.unlock();
1322 
1323  {
1324  std::unique_lock masterLock{app_.getMasterMutex(), std::defer_lock};
1325  bool changed = false;
1326  {
1327  std::unique_lock ledgerLock{
1328  m_ledgerMaster.peekMutex(), std::defer_lock};
1329  std::lock(masterLock, ledgerLock);
1330 
1331  app_.openLedger().modify([&](OpenView& view, beast::Journal j) {
1332  for (TransactionStatus& e : transactions)
1333  {
1334  // we check before adding to the batch
1335  ApplyFlags flags = tapNONE;
1336  if (e.admin)
1337  flags |= tapUNLIMITED;
1338 
1339  if (e.failType == FailHard::yes)
1340  flags |= tapFAIL_HARD;
1341 
1342  auto const result = app_.getTxQ().apply(
1343  app_, view, e.transaction->getSTransaction(), flags, j);
1344  e.result = result.first;
1345  e.applied = result.second;
1346  changed = changed || result.second;
1347  }
1348  return changed;
1349  });
1350  }
1351  if (changed)
1352  reportFeeChange();
1353 
1354  std::optional<LedgerIndex> validatedLedgerIndex;
1355  if (auto const l = m_ledgerMaster.getValidatedLedger())
1356  validatedLedgerIndex = l->info().seq;
1357 
1358  auto newOL = app_.openLedger().current();
1359  for (TransactionStatus& e : transactions)
1360  {
1361  e.transaction->clearSubmitResult();
1362 
1363  if (e.applied)
1364  {
1365  pubProposedTransaction(
1366  newOL, e.transaction->getSTransaction(), e.result);
1367  e.transaction->setApplied();
1368  }
1369 
1370  e.transaction->setResult(e.result);
1371 
1372  if (isTemMalformed(e.result))
1373  app_.getHashRouter().setFlags(e.transaction->getID(), SF_BAD);
1374 
1375 #ifdef DEBUG
1376  if (e.result != tesSUCCESS)
1377  {
1378  std::string token, human;
1379 
1380  if (transResultInfo(e.result, token, human))
1381  {
1382  JLOG(m_journal.info())
1383  << "TransactionResult: " << token << ": " << human;
1384  }
1385  }
1386 #endif
1387 
1388  bool addLocal = e.local;
1389 
1390  if (e.result == tesSUCCESS)
1391  {
1392  JLOG(m_journal.debug())
1393  << "Transaction is now included in open ledger";
1394  e.transaction->setStatus(INCLUDED);
1395 
1396  auto const& txCur = e.transaction->getSTransaction();
1397  auto const txNext = m_ledgerMaster.popAcctTransaction(txCur);
1398  if (txNext)
1399  {
1400  std::string reason;
1401  auto const trans = sterilize(*txNext);
1402  auto t = std::make_shared<Transaction>(trans, reason, app_);
1403  submit_held.emplace_back(t, false, false, FailHard::no);
1404  t->setApplying();
1405  }
1406  }
1407  else if (e.result == tefPAST_SEQ)
1408  {
1409  // duplicate or conflict
1410  JLOG(m_journal.info()) << "Transaction is obsolete";
1411  e.transaction->setStatus(OBSOLETE);
1412  }
1413  else if (e.result == terQUEUED)
1414  {
1415  JLOG(m_journal.debug())
1416  << "Transaction is likely to claim a"
1417  << " fee, but is queued until fee drops";
1418 
1419  e.transaction->setStatus(HELD);
1420  // Add to held transactions, because it could get
1421  // kicked out of the queue, and this will try to
1422  // put it back.
1423  m_ledgerMaster.addHeldTransaction(e.transaction);
1424  e.transaction->setQueued();
1425  e.transaction->setKept();
1426  }
1427  else if (isTerRetry(e.result))
1428  {
1429  if (e.failType != FailHard::yes)
1430  {
1431  // transaction should be held
1432  JLOG(m_journal.debug())
1433  << "Transaction should be held: " << e.result;
1434  e.transaction->setStatus(HELD);
1435  m_ledgerMaster.addHeldTransaction(e.transaction);
1436  e.transaction->setKept();
1437  }
1438  }
1439  else
1440  {
1441  JLOG(m_journal.debug())
1442  << "Status other than success " << e.result;
1443  e.transaction->setStatus(INVALID);
1444  }
1445 
1446  auto const enforceFailHard =
1447  e.failType == FailHard::yes && !isTesSuccess(e.result);
1448 
1449  if (addLocal && !enforceFailHard)
1450  {
1451  m_localTX->push_back(
1452  m_ledgerMaster.getCurrentLedgerIndex(),
1453  e.transaction->getSTransaction());
1454  e.transaction->setKept();
1455  }
1456 
1457  if ((e.applied ||
1458  ((mMode != OperatingMode::FULL) &&
1459  (e.failType != FailHard::yes) && e.local) ||
1460  (e.result == terQUEUED)) &&
1461  !enforceFailHard)
1462  {
1463  auto const toSkip =
1464  app_.getHashRouter().shouldRelay(e.transaction->getID());
1465 
1466  if (toSkip)
1467  {
1468  protocol::TMTransaction tx;
1469  Serializer s;
1470 
1471  e.transaction->getSTransaction()->add(s);
1472  tx.set_rawtransaction(s.data(), s.size());
1473  tx.set_status(protocol::tsCURRENT);
1474  tx.set_receivetimestamp(
1475  app_.timeKeeper().now().time_since_epoch().count());
1476  tx.set_deferred(e.result == terQUEUED);
1477  // FIXME: This should be when we received it
1478  app_.overlay().relay(e.transaction->getID(), tx, *toSkip);
1479  e.transaction->setBroadcast();
1480  }
1481  }
1482 
1483  if (validatedLedgerIndex)
1484  {
1485  auto [fee, accountSeq, availableSeq] =
1486  app_.getTxQ().getTxRequiredFeeAndSeq(
1487  *newOL, e.transaction->getSTransaction());
1488  e.transaction->setCurrentLedgerState(
1489  *validatedLedgerIndex, fee, accountSeq, availableSeq);
1490  }
1491  }
1492  }
1493 
1494  batchLock.lock();
1495 
1496  for (TransactionStatus& e : transactions)
1497  e.transaction->clearApplying();
1498 
1499  if (!submit_held.empty())
1500  {
1501  if (mTransactions.empty())
1502  mTransactions.swap(submit_held);
1503  else
1504  for (auto& e : submit_held)
1505  mTransactions.push_back(std::move(e));
1506  }
1507 
1508  mCond.notify_all();
1509 
1510  mDispatchState = DispatchState::none;
1511 }
1512 
1513 //
1514 // Owner functions
1515 //
1516 
1518 NetworkOPsImp::getOwnerInfo(
1520  AccountID const& account)
1521 {
1522  Json::Value jvObjects(Json::objectValue);
1523  auto root = keylet::ownerDir(account);
1524  auto sleNode = lpLedger->read(keylet::page(root));
1525  if (sleNode)
1526  {
1527  std::uint64_t uNodeDir;
1528 
1529  do
1530  {
1531  for (auto const& uDirEntry : sleNode->getFieldV256(sfIndexes))
1532  {
1533  auto sleCur = lpLedger->read(keylet::child(uDirEntry));
1534  assert(sleCur);
1535 
1536  switch (sleCur->getType())
1537  {
1538  case ltOFFER:
1539  if (!jvObjects.isMember(jss::offers))
1540  jvObjects[jss::offers] =
1542 
1543  jvObjects[jss::offers].append(
1544  sleCur->getJson(JsonOptions::none));
1545  break;
1546 
1547  case ltRIPPLE_STATE:
1548  if (!jvObjects.isMember(jss::ripple_lines))
1549  {
1550  jvObjects[jss::ripple_lines] =
1552  }
1553 
1554  jvObjects[jss::ripple_lines].append(
1555  sleCur->getJson(JsonOptions::none));
1556  break;
1557 
1558  case ltACCOUNT_ROOT:
1559  case ltDIR_NODE:
1560  default:
1561  assert(false);
1562  break;
1563  }
1564  }
1565 
1566  uNodeDir = sleNode->getFieldU64(sfIndexNext);
1567 
1568  if (uNodeDir)
1569  {
1570  sleNode = lpLedger->read(keylet::page(root, uNodeDir));
1571  assert(sleNode);
1572  }
1573  } while (uNodeDir);
1574  }
1575 
1576  return jvObjects;
1577 }
1578 
1579 //
1580 // Other
1581 //
1582 
1583 inline bool
1584 NetworkOPsImp::isBlocked()
1585 {
1586  return isAmendmentBlocked() || isUNLBlocked();
1587 }
1588 
1589 inline bool
1590 NetworkOPsImp::isAmendmentBlocked()
1591 {
1592  return amendmentBlocked_;
1593 }
1594 
1595 void
1596 NetworkOPsImp::setAmendmentBlocked()
1597 {
1598  amendmentBlocked_ = true;
1599  setMode(OperatingMode::CONNECTED);
1600 }
1601 
1602 inline bool
1603 NetworkOPsImp::isAmendmentWarned()
1604 {
1605  return !amendmentBlocked_ && amendmentWarned_;
1606 }
1607 
1608 inline void
1609 NetworkOPsImp::setAmendmentWarned()
1610 {
1611  amendmentWarned_ = true;
1612 }
1613 
1614 inline void
1615 NetworkOPsImp::clearAmendmentWarned()
1616 {
1617  amendmentWarned_ = false;
1618 }
1619 
1620 inline bool
1621 NetworkOPsImp::isUNLBlocked()
1622 {
1623  return unlBlocked_;
1624 }
1625 
1626 void
1627 NetworkOPsImp::setUNLBlocked()
1628 {
1629  unlBlocked_ = true;
1630  setMode(OperatingMode::CONNECTED);
1631 }
1632 
1633 inline void
1634 NetworkOPsImp::clearUNLBlocked()
1635 {
1636  unlBlocked_ = false;
1637 }
1638 
1639 bool
1640 NetworkOPsImp::checkLastClosedLedger(
1641  const Overlay::PeerSequence& peerList,
1642  uint256& networkClosed)
1643 {
1644  // Returns true if there's an *abnormal* ledger issue, normal changing in
1645  // TRACKING mode should return false. Do we have sufficient validations for
1646  // our last closed ledger? Or do sufficient nodes agree? And do we have no
1647  // better ledger available? If so, we are either tracking or full.
1648 
1649  JLOG(m_journal.trace()) << "NetworkOPsImp::checkLastClosedLedger";
1650 
1651  auto const ourClosed = m_ledgerMaster.getClosedLedger();
1652 
1653  if (!ourClosed)
1654  return false;
1655 
1656  uint256 closedLedger = ourClosed->info().hash;
1657  uint256 prevClosedLedger = ourClosed->info().parentHash;
1658  JLOG(m_journal.trace()) << "OurClosed: " << closedLedger;
1659  JLOG(m_journal.trace()) << "PrevClosed: " << prevClosedLedger;
1660 
1661  //-------------------------------------------------------------------------
1662  // Determine preferred last closed ledger
1663 
1664  auto& validations = app_.getValidations();
1665  JLOG(m_journal.debug())
1666  << "ValidationTrie " << Json::Compact(validations.getJsonTrie());
1667 
1668  // Will rely on peer LCL if no trusted validations exist
1670  peerCounts[closedLedger] = 0;
1671  if (mMode >= OperatingMode::TRACKING)
1672  peerCounts[closedLedger]++;
1673 
1674  for (auto& peer : peerList)
1675  {
1676  uint256 peerLedger = peer->getClosedLedgerHash();
1677 
1678  if (peerLedger.isNonZero())
1679  ++peerCounts[peerLedger];
1680  }
1681 
1682  for (auto const& it : peerCounts)
1683  JLOG(m_journal.debug()) << "L: " << it.first << " n=" << it.second;
1684 
1685  uint256 preferredLCL = validations.getPreferredLCL(
1686  RCLValidatedLedger{ourClosed, validations.adaptor().journal()},
1687  m_ledgerMaster.getValidLedgerIndex(),
1688  peerCounts);
1689 
1690  bool switchLedgers = preferredLCL != closedLedger;
1691  if (switchLedgers)
1692  closedLedger = preferredLCL;
1693  //-------------------------------------------------------------------------
1694  if (switchLedgers && (closedLedger == prevClosedLedger))
1695  {
1696  // don't switch to our own previous ledger
1697  JLOG(m_journal.info()) << "We won't switch to our own previous ledger";
1698  networkClosed = ourClosed->info().hash;
1699  switchLedgers = false;
1700  }
1701  else
1702  networkClosed = closedLedger;
1703 
1704  if (!switchLedgers)
1705  return false;
1706 
1707  auto consensus = m_ledgerMaster.getLedgerByHash(closedLedger);
1708 
1709  if (!consensus)
1710  consensus = app_.getInboundLedgers().acquire(
1711  closedLedger, 0, InboundLedger::Reason::CONSENSUS);
1712 
1713  if (consensus &&
1714  (!m_ledgerMaster.canBeCurrent(consensus) ||
1715  !m_ledgerMaster.isCompatible(
1716  *consensus, m_journal.debug(), "Not switching")))
1717  {
1718  // Don't switch to a ledger not on the validated chain
1719  // or with an invalid close time or sequence
1720  networkClosed = ourClosed->info().hash;
1721  return false;
1722  }
1723 
1724  JLOG(m_journal.warn()) << "We are not running on the consensus ledger";
1725  JLOG(m_journal.info()) << "Our LCL: " << getJson({*ourClosed, {}});
1726  JLOG(m_journal.info()) << "Net LCL " << closedLedger;
1727 
1728  if ((mMode == OperatingMode::TRACKING) || (mMode == OperatingMode::FULL))
1729  {
1730  setMode(OperatingMode::CONNECTED);
1731  }
1732 
1733  if (consensus)
1734  {
1735  // FIXME: If this rewinds the ledger sequence, or has the same
1736  // sequence, we should update the status on any stored transactions
1737  // in the invalidated ledgers.
1738  switchLastClosedLedger(consensus);
1739  }
1740 
1741  return true;
1742 }
1743 
1744 void
1745 NetworkOPsImp::switchLastClosedLedger(
1746  std::shared_ptr<Ledger const> const& newLCL)
1747 {
1748  // set the newLCL as our last closed ledger -- this is abnormal code
1749  JLOG(m_journal.error())
1750  << "JUMP last closed ledger to " << newLCL->info().hash;
1751 
1752  clearNeedNetworkLedger();
1753 
1754  // Update fee computations.
1755  app_.getTxQ().processClosedLedger(app_, *newLCL, true);
1756 
1757  // Caller must own master lock
1758  {
1759  // Apply tx in old open ledger to new
1760  // open ledger. Then apply local tx.
1761 
1762  auto retries = m_localTX->getTxSet();
1763  auto const lastVal = app_.getLedgerMaster().getValidatedLedger();
1764  std::optional<Rules> rules;
1765  if (lastVal)
1766  rules = makeRulesGivenLedger(*lastVal, app_.config().features);
1767  else
1768  rules.emplace(app_.config().features);
1769  app_.openLedger().accept(
1770  app_,
1771  *rules,
1772  newLCL,
1773  OrderedTxs({}),
1774  false,
1775  retries,
1776  tapNONE,
1777  "jump",
1778  [&](OpenView& view, beast::Journal j) {
1779  // Stuff the ledger with transactions from the queue.
1780  return app_.getTxQ().accept(app_, view);
1781  });
1782  }
1783 
1784  m_ledgerMaster.switchLCL(newLCL);
1785 
1786  protocol::TMStatusChange s;
1787  s.set_newevent(protocol::neSWITCHED_LEDGER);
1788  s.set_ledgerseq(newLCL->info().seq);
1789  s.set_networktime(app_.timeKeeper().now().time_since_epoch().count());
1790  s.set_ledgerhashprevious(
1791  newLCL->info().parentHash.begin(), newLCL->info().parentHash.size());
1792  s.set_ledgerhash(newLCL->info().hash.begin(), newLCL->info().hash.size());
1793 
1794  app_.overlay().foreach(
1795  send_always(std::make_shared<Message>(s, protocol::mtSTATUS_CHANGE)));
1796 }
1797 
1798 bool
1799 NetworkOPsImp::beginConsensus(uint256 const& networkClosed)
1800 {
1801  assert(networkClosed.isNonZero());
1802 
1803  auto closingInfo = m_ledgerMaster.getCurrentLedger()->info();
1804 
1805  JLOG(m_journal.info()) << "Consensus time for #" << closingInfo.seq
1806  << " with LCL " << closingInfo.parentHash;
1807 
1808  auto prevLedger = m_ledgerMaster.getLedgerByHash(closingInfo.parentHash);
1809 
1810  if (!prevLedger)
1811  {
1812  // this shouldn't happen unless we jump ledgers
1813  if (mMode == OperatingMode::FULL)
1814  {
1815  JLOG(m_journal.warn()) << "Don't have LCL, going to tracking";
1816  setMode(OperatingMode::TRACKING);
1817  }
1818 
1819  return false;
1820  }
1821 
1822  assert(prevLedger->info().hash == closingInfo.parentHash);
1823  assert(
1824  closingInfo.parentHash ==
1825  m_ledgerMaster.getClosedLedger()->info().hash);
1826 
1827  if (prevLedger->rules().enabled(featureNegativeUNL))
1828  app_.validators().setNegativeUNL(prevLedger->negativeUNL());
1829  TrustChanges const changes = app_.validators().updateTrusted(
1830  app_.getValidations().getCurrentNodeIDs(),
1831  closingInfo.parentCloseTime,
1832  *this,
1833  app_.overlay(),
1834  app_.getHashRouter());
1835 
1836  if (!changes.added.empty() || !changes.removed.empty())
1837  app_.getValidations().trustChanged(changes.added, changes.removed);
1838 
1839  mConsensus.startRound(
1840  app_.timeKeeper().closeTime(),
1841  networkClosed,
1842  prevLedger,
1843  changes.removed,
1844  changes.added);
1845 
1846  const ConsensusPhase currPhase = mConsensus.phase();
1847  if (mLastConsensusPhase != currPhase)
1848  {
1849  reportConsensusStateChange(currPhase);
1850  mLastConsensusPhase = currPhase;
1851  }
1852 
1853  JLOG(m_journal.debug()) << "Initiating consensus engine";
1854  return true;
1855 }
1856 
1857 bool
1858 NetworkOPsImp::processTrustedProposal(RCLCxPeerPos peerPos)
1859 {
1860  return mConsensus.peerProposal(app_.timeKeeper().closeTime(), peerPos);
1861 }
1862 
1863 void
1864 NetworkOPsImp::mapComplete(std::shared_ptr<SHAMap> const& map, bool fromAcquire)
1865 {
1866  // We now have an additional transaction set
1867  // either created locally during the consensus process
1868  // or acquired from a peer
1869 
1870  // Inform peers we have this set
1871  protocol::TMHaveTransactionSet msg;
1872  msg.set_hash(map->getHash().as_uint256().begin(), 256 / 8);
1873  msg.set_status(protocol::tsHAVE);
1874  app_.overlay().foreach(
1875  send_always(std::make_shared<Message>(msg, protocol::mtHAVE_SET)));
1876 
1877  // We acquired it because consensus asked us to
1878  if (fromAcquire)
1879  mConsensus.gotTxSet(app_.timeKeeper().closeTime(), RCLTxSet{map});
1880 }
1881 
1882 void
1883 NetworkOPsImp::endConsensus()
1884 {
1885  uint256 deadLedger = m_ledgerMaster.getClosedLedger()->info().parentHash;
1886 
1887  for (auto const& it : app_.overlay().getActivePeers())
1888  {
1889  if (it && (it->getClosedLedgerHash() == deadLedger))
1890  {
1891  JLOG(m_journal.trace()) << "Killing obsolete peer status";
1892  it->cycleStatus();
1893  }
1894  }
1895 
1896  uint256 networkClosed;
1897  bool ledgerChange =
1898  checkLastClosedLedger(app_.overlay().getActivePeers(), networkClosed);
1899 
1900  if (networkClosed.isZero())
1901  return;
1902 
1903  // WRITEME: Unless we are in FULL and in the process of doing a consensus,
1904  // we must count how many nodes share our LCL, how many nodes disagree with
1905  // our LCL, and how many validations our LCL has. We also want to check
1906  // timing to make sure there shouldn't be a newer LCL. We need this
1907  // information to do the next three tests.
1908 
1909  if (((mMode == OperatingMode::CONNECTED) ||
1910  (mMode == OperatingMode::SYNCING)) &&
1911  !ledgerChange)
1912  {
1913  // Count number of peers that agree with us and UNL nodes whose
1914  // validations we have for LCL. If the ledger is good enough, go to
1915  // TRACKING - TODO
1916  if (!needNetworkLedger_)
1917  setMode(OperatingMode::TRACKING);
1918  }
1919 
1920  if (((mMode == OperatingMode::CONNECTED) ||
1921  (mMode == OperatingMode::TRACKING)) &&
1922  !ledgerChange)
1923  {
1924  // check if the ledger is good enough to go to FULL
1925  // Note: Do not go to FULL if we don't have the previous ledger
1926  // check if the ledger is bad enough to go to CONNECTE D -- TODO
1927  auto current = m_ledgerMaster.getCurrentLedger();
1928  if (app_.timeKeeper().now() < (current->info().parentCloseTime +
1929  2 * current->info().closeTimeResolution))
1930  {
1931  setMode(OperatingMode::FULL);
1932  }
1933  }
1934 
1935  beginConsensus(networkClosed);
1936 }
1937 
1938 void
1939 NetworkOPsImp::consensusViewChange()
1940 {
1941  if ((mMode == OperatingMode::FULL) || (mMode == OperatingMode::TRACKING))
1942  {
1943  setMode(OperatingMode::CONNECTED);
1944  }
1945 }
1946 
1947 void
1948 NetworkOPsImp::pubManifest(Manifest const& mo)
1949 {
1950  // VFALCO consider std::shared_mutex
1951  std::lock_guard sl(mSubLock);
1952 
1953  if (!mStreamMaps[sManifests].empty())
1954  {
1956 
1957  jvObj[jss::type] = "manifestReceived";
1958  jvObj[jss::master_key] = toBase58(TokenType::NodePublic, mo.masterKey);
1959  if (!mo.signingKey.empty())
1960  jvObj[jss::signing_key] =
1961  toBase58(TokenType::NodePublic, mo.signingKey);
1962  jvObj[jss::seq] = Json::UInt(mo.sequence);
1963  if (auto sig = mo.getSignature())
1964  jvObj[jss::signature] = strHex(*sig);
1965  jvObj[jss::master_signature] = strHex(mo.getMasterSignature());
1966  if (!mo.domain.empty())
1967  jvObj[jss::domain] = mo.domain;
1968  jvObj[jss::manifest] = strHex(mo.serialized);
1969 
1970  for (auto i = mStreamMaps[sManifests].begin();
1971  i != mStreamMaps[sManifests].end();)
1972  {
1973  if (auto p = i->second.lock())
1974  {
1975  p->send(jvObj, true);
1976  ++i;
1977  }
1978  else
1979  {
1980  i = mStreamMaps[sManifests].erase(i);
1981  }
1982  }
1983  }
1984 }
1985 
1986 NetworkOPsImp::ServerFeeSummary::ServerFeeSummary(
1987  XRPAmount fee,
1988  TxQ::Metrics&& escalationMetrics,
1989  LoadFeeTrack const& loadFeeTrack)
1990  : loadFactorServer{loadFeeTrack.getLoadFactor()}
1991  , loadBaseServer{loadFeeTrack.getLoadBase()}
1992  , baseFee{fee}
1993  , em{std::move(escalationMetrics)}
1994 {
1995 }
1996 
1997 bool
1999  NetworkOPsImp::ServerFeeSummary const& b) const
2000 {
2001  if (loadFactorServer != b.loadFactorServer ||
2002  loadBaseServer != b.loadBaseServer || baseFee != b.baseFee ||
2003  em.has_value() != b.em.has_value())
2004  return true;
2005 
2006  if (em && b.em)
2007  {
2008  return (
2009  em->minProcessingFeeLevel != b.em->minProcessingFeeLevel ||
2010  em->openLedgerFeeLevel != b.em->openLedgerFeeLevel ||
2011  em->referenceFeeLevel != b.em->referenceFeeLevel);
2012  }
2013 
2014  return false;
2015 }
2016 
2017 // Need to cap to uint64 to uint32 due to JSON limitations
2018 static std::uint32_t
2020 {
2022 
2023  return std::min(max32, v);
2024 };
2025 
2026 void
2028 {
2029  // VFALCO TODO Don't hold the lock across calls to send...make a copy of the
2030  // list into a local array while holding the lock then release
2031  // the lock and call send on everyone.
2032  //
2034 
2035  if (!mStreamMaps[sServer].empty())
2036  {
2038 
2039  ServerFeeSummary f{
2040  app_.openLedger().current()->fees().base,
2042  app_.getFeeTrack()};
2043 
2044  jvObj[jss::type] = "serverStatus";
2045  jvObj[jss::server_status] = strOperatingMode();
2046  jvObj[jss::load_base] = f.loadBaseServer;
2047  jvObj[jss::load_factor_server] = f.loadFactorServer;
2048  jvObj[jss::base_fee] = f.baseFee.jsonClipped();
2049 
2050  if (f.em)
2051  {
2052  auto const loadFactor = std::max(
2053  safe_cast<std::uint64_t>(f.loadFactorServer),
2054  mulDiv(
2055  f.em->openLedgerFeeLevel,
2056  f.loadBaseServer,
2057  f.em->referenceFeeLevel)
2058  .second);
2059 
2060  jvObj[jss::load_factor] = trunc32(loadFactor);
2061  jvObj[jss::load_factor_fee_escalation] =
2062  f.em->openLedgerFeeLevel.jsonClipped();
2063  jvObj[jss::load_factor_fee_queue] =
2064  f.em->minProcessingFeeLevel.jsonClipped();
2065  jvObj[jss::load_factor_fee_reference] =
2066  f.em->referenceFeeLevel.jsonClipped();
2067  }
2068  else
2069  jvObj[jss::load_factor] = f.loadFactorServer;
2070 
2071  mLastFeeSummary = f;
2072 
2073  for (auto i = mStreamMaps[sServer].begin();
2074  i != mStreamMaps[sServer].end();)
2075  {
2076  InfoSub::pointer p = i->second.lock();
2077 
2078  // VFALCO TODO research the possibility of using thread queues and
2079  // linearizing the deletion of subscribers with the
2080  // sending of JSON data.
2081  if (p)
2082  {
2083  p->send(jvObj, true);
2084  ++i;
2085  }
2086  else
2087  {
2088  i = mStreamMaps[sServer].erase(i);
2089  }
2090  }
2091  }
2092 }
2093 
2094 void
2096 {
2098 
2099  auto& streamMap = mStreamMaps[sConsensusPhase];
2100  if (!streamMap.empty())
2101  {
2103  jvObj[jss::type] = "consensusPhase";
2104  jvObj[jss::consensus] = to_string(phase);
2105 
2106  for (auto i = streamMap.begin(); i != streamMap.end();)
2107  {
2108  if (auto p = i->second.lock())
2109  {
2110  p->send(jvObj, true);
2111  ++i;
2112  }
2113  else
2114  {
2115  i = streamMap.erase(i);
2116  }
2117  }
2118  }
2119 }
2120 
2121 void
2123 {
2124  // VFALCO consider std::shared_mutex
2126 
2127  if (!mStreamMaps[sValidations].empty())
2128  {
2130 
2131  auto const signerPublic = val->getSignerPublic();
2132 
2133  jvObj[jss::type] = "validationReceived";
2134  jvObj[jss::validation_public_key] =
2135  toBase58(TokenType::NodePublic, signerPublic);
2136  jvObj[jss::ledger_hash] = to_string(val->getLedgerHash());
2137  jvObj[jss::signature] = strHex(val->getSignature());
2138  jvObj[jss::full] = val->isFull();
2139  jvObj[jss::flags] = val->getFlags();
2140  jvObj[jss::signing_time] = *(*val)[~sfSigningTime];
2141  jvObj[jss::data] = strHex(val->getSerializer().slice());
2142 
2143  if (auto version = (*val)[~sfServerVersion])
2144  jvObj[jss::server_version] = std::to_string(*version);
2145 
2146  if (auto cookie = (*val)[~sfCookie])
2147  jvObj[jss::cookie] = std::to_string(*cookie);
2148 
2149  if (auto hash = (*val)[~sfValidatedHash])
2150  jvObj[jss::validated_hash] = strHex(*hash);
2151 
2152  auto const masterKey =
2153  app_.validatorManifests().getMasterKey(signerPublic);
2154 
2155  if (masterKey != signerPublic)
2156  jvObj[jss::master_key] = toBase58(TokenType::NodePublic, masterKey);
2157 
2158  if (auto const seq = (*val)[~sfLedgerSequence])
2159  jvObj[jss::ledger_index] = to_string(*seq);
2160 
2161  if (val->isFieldPresent(sfAmendments))
2162  {
2163  jvObj[jss::amendments] = Json::Value(Json::arrayValue);
2164  for (auto const& amendment : val->getFieldV256(sfAmendments))
2165  jvObj[jss::amendments].append(to_string(amendment));
2166  }
2167 
2168  if (auto const closeTime = (*val)[~sfCloseTime])
2169  jvObj[jss::close_time] = *closeTime;
2170 
2171  if (auto const loadFee = (*val)[~sfLoadFee])
2172  jvObj[jss::load_fee] = *loadFee;
2173 
2174  if (auto const baseFee = val->at(~sfBaseFee))
2175  jvObj[jss::base_fee] = static_cast<double>(*baseFee);
2176 
2177  if (auto const reserveBase = val->at(~sfReserveBase))
2178  jvObj[jss::reserve_base] = *reserveBase;
2179 
2180  if (auto const reserveInc = val->at(~sfReserveIncrement))
2181  jvObj[jss::reserve_inc] = *reserveInc;
2182 
2183  // (The ~ operator converts the Proxy to a std::optional, which
2184  // simplifies later operations)
2185  if (auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops);
2186  baseFeeXRP && baseFeeXRP->native())
2187  jvObj[jss::base_fee_drops] = baseFeeXRP->xrp().jsonClipped();
2188 
2189  if (auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops);
2190  reserveBaseXRP && reserveBaseXRP->native())
2191  jvObj[jss::reserve_base_drops] =
2192  reserveBaseXRP->xrp().jsonClipped();
2193 
2194  if (auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops);
2195  reserveIncXRP && reserveIncXRP->native())
2196  jvObj[jss::reserve_inc_drops] = reserveIncXRP->xrp().jsonClipped();
2197 
2198  for (auto i = mStreamMaps[sValidations].begin();
2199  i != mStreamMaps[sValidations].end();)
2200  {
2201  if (auto p = i->second.lock())
2202  {
2203  p->send(jvObj, true);
2204  ++i;
2205  }
2206  else
2207  {
2208  i = mStreamMaps[sValidations].erase(i);
2209  }
2210  }
2211  }
2212 }
2213 
2214 void
2216 {
2218 
2219  if (!mStreamMaps[sPeerStatus].empty())
2220  {
2221  Json::Value jvObj(func());
2222 
2223  jvObj[jss::type] = "peerStatusChange";
2224 
2225  for (auto i = mStreamMaps[sPeerStatus].begin();
2226  i != mStreamMaps[sPeerStatus].end();)
2227  {
2228  InfoSub::pointer p = i->second.lock();
2229 
2230  if (p)
2231  {
2232  p->send(jvObj, true);
2233  ++i;
2234  }
2235  else
2236  {
2237  i = mStreamMaps[sPeerStatus].erase(i);
2238  }
2239  }
2240  }
2241 }
2242 
2243 void
2245 {
2246  using namespace std::chrono_literals;
2247  if (om == OperatingMode::CONNECTED)
2248  {
2251  }
2252  else if (om == OperatingMode::SYNCING)
2253  {
2254  if (app_.getLedgerMaster().getValidatedLedgerAge() >= 1min)
2256  }
2257 
2258  if ((om > OperatingMode::CONNECTED) && isBlocked())
2260 
2261  if (mMode == om)
2262  return;
2263 
2264  mMode = om;
2265 
2266  accounting_.mode(om);
2267 
2268  JLOG(m_journal.info()) << "STATE->" << strOperatingMode();
2269  pubServer();
2270 }
2271 
2272 bool
2274  std::shared_ptr<STValidation> const& val,
2275  std::string const& source)
2276 {
2277  JLOG(m_journal.trace())
2278  << "recvValidation " << val->getLedgerHash() << " from " << source;
2279 
2280  handleNewValidation(app_, val, source);
2281 
2282  pubValidation(val);
2283 
2284  // We will always relay trusted validations; if configured, we will
2285  // also relay all untrusted validations.
2286  return app_.config().RELAY_UNTRUSTED_VALIDATIONS == 1 || val->isTrusted();
2287 }
2288 
2291 {
2292  return mConsensus.getJson(true);
2293 }
2294 
2296 NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters)
2297 {
2299 
2300  // System-level warnings
2301  {
2302  Json::Value warnings{Json::arrayValue};
2303  if (isAmendmentBlocked())
2304  {
2305  Json::Value& w = warnings.append(Json::objectValue);
2306  w[jss::id] = warnRPC_AMENDMENT_BLOCKED;
2307  w[jss::message] =
2308  "This server is amendment blocked, and must be updated to be "
2309  "able to stay in sync with the network.";
2310  }
2311  if (isUNLBlocked())
2312  {
2313  Json::Value& w = warnings.append(Json::objectValue);
2314  w[jss::id] = warnRPC_EXPIRED_VALIDATOR_LIST;
2315  w[jss::message] =
2316  "This server has an expired validator list. validators.txt "
2317  "may be incorrectly configured or some [validator_list_sites] "
2318  "may be unreachable.";
2319  }
2320  if (admin && isAmendmentWarned())
2321  {
2322  Json::Value& w = warnings.append(Json::objectValue);
2323  w[jss::id] = warnRPC_UNSUPPORTED_MAJORITY;
2324  w[jss::message] =
2325  "One or more unsupported amendments have reached majority. "
2326  "Upgrade to the latest version before they are activated "
2327  "to avoid being amendment blocked.";
2328  if (auto const expected =
2330  {
2331  auto& d = w[jss::details] = Json::objectValue;
2332  d[jss::expected_date] = expected->time_since_epoch().count();
2333  d[jss::expected_date_UTC] = to_string(*expected);
2334  }
2335  }
2336 
2337  if (warnings.size())
2338  info[jss::warnings] = std::move(warnings);
2339  }
2340 
2341  // hostid: unique string describing the machine
2342  if (human)
2343  info[jss::hostid] = getHostId(admin);
2344 
2345  // domain: if configured with a domain, report it:
2346  if (!app_.config().SERVER_DOMAIN.empty())
2347  info[jss::server_domain] = app_.config().SERVER_DOMAIN;
2348 
2349  info[jss::build_version] = BuildInfo::getVersionString();
2350 
2351  info[jss::server_state] = strOperatingMode(admin);
2352 
2353  info[jss::time] = to_string(std::chrono::floor<std::chrono::microseconds>(
2355 
2356  if (needNetworkLedger_)
2357  info[jss::network_ledger] = "waiting";
2358 
2359  info[jss::validation_quorum] =
2360  static_cast<Json::UInt>(app_.validators().quorum());
2361 
2362  if (admin)
2363  {
2364  switch (app_.config().NODE_SIZE)
2365  {
2366  case 0:
2367  info[jss::node_size] = "tiny";
2368  break;
2369  case 1:
2370  info[jss::node_size] = "small";
2371  break;
2372  case 2:
2373  info[jss::node_size] = "medium";
2374  break;
2375  case 3:
2376  info[jss::node_size] = "large";
2377  break;
2378  case 4:
2379  info[jss::node_size] = "huge";
2380  break;
2381  }
2382 
2383  auto when = app_.validators().expires();
2384 
2385  if (!human)
2386  {
2387  if (when)
2388  info[jss::validator_list_expires] =
2389  safe_cast<Json::UInt>(when->time_since_epoch().count());
2390  else
2391  info[jss::validator_list_expires] = 0;
2392  }
2393  else
2394  {
2395  auto& x = (info[jss::validator_list] = Json::objectValue);
2396 
2397  x[jss::count] = static_cast<Json::UInt>(app_.validators().count());
2398 
2399  if (when)
2400  {
2401  if (*when == TimeKeeper::time_point::max())
2402  {
2403  x[jss::expiration] = "never";
2404  x[jss::status] = "active";
2405  }
2406  else
2407  {
2408  x[jss::expiration] = to_string(*when);
2409 
2410  if (*when > app_.timeKeeper().now())
2411  x[jss::status] = "active";
2412  else
2413  x[jss::status] = "expired";
2414  }
2415  }
2416  else
2417  {
2418  x[jss::status] = "unknown";
2419  x[jss::expiration] = "unknown";
2420  }
2421  }
2422  }
2423  info[jss::io_latency_ms] =
2424  static_cast<Json::UInt>(app_.getIOLatency().count());
2425 
2426  if (admin)
2427  {
2429  {
2430  info[jss::pubkey_validator] = toBase58(
2432  }
2433  else
2434  {
2435  info[jss::pubkey_validator] = "none";
2436  }
2437  }
2438 
2439  if (counters)
2440  {
2441  info[jss::counters] = app_.getPerfLog().countersJson();
2442 
2443  Json::Value nodestore(Json::objectValue);
2444  if (app_.getShardStore())
2445  app_.getShardStore()->getCountsJson(nodestore);
2446  else
2447  app_.getNodeStore().getCountsJson(nodestore);
2448  info[jss::counters][jss::nodestore] = nodestore;
2449  info[jss::current_activities] = app_.getPerfLog().currentJson();
2450  }
2451 
2452  info[jss::pubkey_node] =
2454 
2455  info[jss::complete_ledgers] = app_.getLedgerMaster().getCompleteLedgers();
2456 
2457  if (amendmentBlocked_)
2458  info[jss::amendment_blocked] = true;
2459 
2460  auto const fp = m_ledgerMaster.getFetchPackCacheSize();
2461 
2462  if (fp != 0)
2463  info[jss::fetch_pack] = Json::UInt(fp);
2464 
2465  if (!app_.config().reporting())
2466  info[jss::peers] = Json::UInt(app_.overlay().size());
2467 
2468  Json::Value lastClose = Json::objectValue;
2469  lastClose[jss::proposers] = Json::UInt(mConsensus.prevProposers());
2470 
2471  if (human)
2472  {
2473  lastClose[jss::converge_time_s] =
2475  }
2476  else
2477  {
2478  lastClose[jss::converge_time] =
2480  }
2481 
2482  info[jss::last_close] = lastClose;
2483 
2484  // info[jss::consensus] = mConsensus.getJson();
2485 
2486  if (admin)
2487  info[jss::load] = m_job_queue.getJson();
2488 
2489  if (!app_.config().reporting())
2490  {
2491  if (auto const netid = app_.overlay().networkID())
2492  info[jss::network_id] = static_cast<Json::UInt>(*netid);
2493 
2494  auto const escalationMetrics =
2496 
2497  auto const loadFactorServer = app_.getFeeTrack().getLoadFactor();
2498  auto const loadBaseServer = app_.getFeeTrack().getLoadBase();
2499  /* Scale the escalated fee level to unitless "load factor".
2500  In practice, this just strips the units, but it will continue
2501  to work correctly if either base value ever changes. */
2502  auto const loadFactorFeeEscalation =
2503  mulDiv(
2504  escalationMetrics.openLedgerFeeLevel,
2505  loadBaseServer,
2506  escalationMetrics.referenceFeeLevel)
2507  .second;
2508 
2509  auto const loadFactor = std::max(
2510  safe_cast<std::uint64_t>(loadFactorServer),
2511  loadFactorFeeEscalation);
2512 
2513  if (!human)
2514  {
2515  info[jss::load_base] = loadBaseServer;
2516  info[jss::load_factor] = trunc32(loadFactor);
2517  info[jss::load_factor_server] = loadFactorServer;
2518 
2519  /* Json::Value doesn't support uint64, so clamp to max
2520  uint32 value. This is mostly theoretical, since there
2521  probably isn't enough extant XRP to drive the factor
2522  that high.
2523  */
2524  info[jss::load_factor_fee_escalation] =
2525  escalationMetrics.openLedgerFeeLevel.jsonClipped();
2526  info[jss::load_factor_fee_queue] =
2527  escalationMetrics.minProcessingFeeLevel.jsonClipped();
2528  info[jss::load_factor_fee_reference] =
2529  escalationMetrics.referenceFeeLevel.jsonClipped();
2530  }
2531  else
2532  {
2533  info[jss::load_factor] =
2534  static_cast<double>(loadFactor) / loadBaseServer;
2535 
2536  if (loadFactorServer != loadFactor)
2537  info[jss::load_factor_server] =
2538  static_cast<double>(loadFactorServer) / loadBaseServer;
2539 
2540  if (admin)
2541  {
2543  if (fee != loadBaseServer)
2544  info[jss::load_factor_local] =
2545  static_cast<double>(fee) / loadBaseServer;
2546  fee = app_.getFeeTrack().getRemoteFee();
2547  if (fee != loadBaseServer)
2548  info[jss::load_factor_net] =
2549  static_cast<double>(fee) / loadBaseServer;
2550  fee = app_.getFeeTrack().getClusterFee();
2551  if (fee != loadBaseServer)
2552  info[jss::load_factor_cluster] =
2553  static_cast<double>(fee) / loadBaseServer;
2554  }
2555  if (escalationMetrics.openLedgerFeeLevel !=
2556  escalationMetrics.referenceFeeLevel &&
2557  (admin || loadFactorFeeEscalation != loadFactor))
2558  info[jss::load_factor_fee_escalation] =
2559  escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2560  escalationMetrics.referenceFeeLevel);
2561  if (escalationMetrics.minProcessingFeeLevel !=
2562  escalationMetrics.referenceFeeLevel)
2563  info[jss::load_factor_fee_queue] =
2564  escalationMetrics.minProcessingFeeLevel
2565  .decimalFromReference(
2566  escalationMetrics.referenceFeeLevel);
2567  }
2568  }
2569 
2570  bool valid = false;
2571  auto lpClosed = m_ledgerMaster.getValidatedLedger();
2572 
2573  if (lpClosed)
2574  valid = true;
2575  else if (!app_.config().reporting())
2576  lpClosed = m_ledgerMaster.getClosedLedger();
2577 
2578  if (lpClosed)
2579  {
2580  XRPAmount const baseFee = lpClosed->fees().base;
2582  l[jss::seq] = Json::UInt(lpClosed->info().seq);
2583  l[jss::hash] = to_string(lpClosed->info().hash);
2584 
2585  if (!human)
2586  {
2587  l[jss::base_fee] = baseFee.jsonClipped();
2588  l[jss::reserve_base] =
2589  lpClosed->fees().accountReserve(0).jsonClipped();
2590  l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2591  l[jss::close_time] = Json::Value::UInt(
2592  lpClosed->info().closeTime.time_since_epoch().count());
2593  }
2594  else
2595  {
2596  l[jss::base_fee_xrp] = baseFee.decimalXRP();
2597  l[jss::reserve_base_xrp] =
2598  lpClosed->fees().accountReserve(0).decimalXRP();
2599  l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2600 
2601  auto const nowOffset = app_.timeKeeper().nowOffset();
2602  if (std::abs(nowOffset.count()) >= 60)
2603  l[jss::system_time_offset] = nowOffset.count();
2604 
2605  auto const closeOffset = app_.timeKeeper().closeOffset();
2606  if (std::abs(closeOffset.count()) >= 60)
2607  l[jss::close_time_offset] = closeOffset.count();
2608 
2609 #if RIPPLED_REPORTING
2610  std::int64_t const dbAge =
2612  l[jss::age] = Json::UInt(dbAge);
2613 #else
2614  constexpr std::chrono::seconds highAgeThreshold{1000000};
2616  {
2617  auto const age = m_ledgerMaster.getValidatedLedgerAge();
2618  l[jss::age] =
2619  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2620  }
2621  else
2622  {
2623  auto lCloseTime = lpClosed->info().closeTime;
2624  auto closeTime = app_.timeKeeper().closeTime();
2625  if (lCloseTime <= closeTime)
2626  {
2627  using namespace std::chrono_literals;
2628  auto age = closeTime - lCloseTime;
2629  l[jss::age] =
2630  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2631  }
2632  }
2633 #endif
2634  }
2635 
2636  if (valid)
2637  info[jss::validated_ledger] = l;
2638  else
2639  info[jss::closed_ledger] = l;
2640 
2641  auto lpPublished = m_ledgerMaster.getPublishedLedger();
2642  if (!lpPublished)
2643  info[jss::published_ledger] = "none";
2644  else if (lpPublished->info().seq != lpClosed->info().seq)
2645  info[jss::published_ledger] = lpPublished->info().seq;
2646  }
2647 
2648  accounting_.json(info);
2649  info[jss::uptime] = UptimeClock::now().time_since_epoch().count();
2650  if (!app_.config().reporting())
2651  {
2652  info[jss::jq_trans_overflow] =
2654  info[jss::peer_disconnects] =
2656  info[jss::peer_disconnects_resources] =
2658  }
2659  else
2660  {
2661  info["reporting"] = app_.getReportingETL().getInfo();
2662  }
2663 
2664  return info;
2665 }
2666 
2667 void
2669 {
2671 }
2672 
2675 {
2676  return app_.getInboundLedgers().getInfo();
2677 }
2678 
2679 void
2681  std::shared_ptr<ReadView const> const& ledger,
2682  std::shared_ptr<STTx const> const& transaction,
2683  TER result)
2684 {
2685  Json::Value jvObj = transJson(*transaction, result, false, ledger);
2686 
2687  {
2689 
2690  auto it = mStreamMaps[sRTTransactions].begin();
2691  while (it != mStreamMaps[sRTTransactions].end())
2692  {
2693  InfoSub::pointer p = it->second.lock();
2694 
2695  if (p)
2696  {
2697  p->send(jvObj, true);
2698  ++it;
2699  }
2700  else
2701  {
2702  it = mStreamMaps[sRTTransactions].erase(it);
2703  }
2704  }
2705  }
2706 
2707  pubProposedAccountTransaction(ledger, transaction, result);
2708 }
2709 
2710 void
2712 {
2713  // reporting does not forward validated transactions
2714  // validated transactions will be published to the proper streams when the
2715  // etl process writes a validated ledger
2716  if (jvObj[jss::validated].asBool())
2717  return;
2718  {
2720 
2721  auto it = mStreamMaps[sRTTransactions].begin();
2722  while (it != mStreamMaps[sRTTransactions].end())
2723  {
2724  InfoSub::pointer p = it->second.lock();
2725 
2726  if (p)
2727  {
2728  p->send(jvObj, true);
2729  ++it;
2730  }
2731  else
2732  {
2733  it = mStreamMaps[sRTTransactions].erase(it);
2734  }
2735  }
2736  }
2737 
2739 }
2740 
2741 void
2743 {
2745 
2746  for (auto i = mStreamMaps[sValidations].begin();
2747  i != mStreamMaps[sValidations].end();)
2748  {
2749  if (auto p = i->second.lock())
2750  {
2751  p->send(jvObj, true);
2752  ++i;
2753  }
2754  else
2755  {
2756  i = mStreamMaps[sValidations].erase(i);
2757  }
2758  }
2759 }
2760 
2761 void
2763 {
2765 
2766  for (auto i = mStreamMaps[sManifests].begin();
2767  i != mStreamMaps[sManifests].end();)
2768  {
2769  if (auto p = i->second.lock())
2770  {
2771  p->send(jvObj, true);
2772  ++i;
2773  }
2774  else
2775  {
2776  i = mStreamMaps[sManifests].erase(i);
2777  }
2778  }
2779 }
2780 
2781 static void
2783 {
2784  for (auto& jv : jvObj)
2785  {
2786  if (jv.isObject())
2787  {
2788  getAccounts(jv, accounts);
2789  }
2790  else if (jv.isString())
2791  {
2792  auto account = RPC::accountFromStringStrict(jv.asString());
2793  if (account)
2794  accounts.push_back(*account);
2795  }
2796  }
2797 }
2798 
2799 void
2801 {
2803  int iProposed = 0;
2804  // check if there are any subscribers before attempting to parse the JSON
2805  {
2807 
2808  if (mSubRTAccount.empty())
2809  return;
2810  }
2811 
2812  // parse the JSON outside of the lock
2813  std::vector<AccountID> accounts;
2814  if (jvObj.isMember(jss::transaction))
2815  {
2816  try
2817  {
2818  getAccounts(jvObj[jss::transaction], accounts);
2819  }
2820  catch (...)
2821  {
2822  JLOG(m_journal.debug())
2823  << __func__ << " : "
2824  << "error parsing json for accounts affected";
2825  return;
2826  }
2827  }
2828  {
2830 
2831  if (!mSubRTAccount.empty())
2832  {
2833  for (auto const& affectedAccount : accounts)
2834  {
2835  auto simiIt = mSubRTAccount.find(affectedAccount);
2836  if (simiIt != mSubRTAccount.end())
2837  {
2838  auto it = simiIt->second.begin();
2839 
2840  while (it != simiIt->second.end())
2841  {
2842  InfoSub::pointer p = it->second.lock();
2843 
2844  if (p)
2845  {
2846  notify.insert(p);
2847  ++it;
2848  ++iProposed;
2849  }
2850  else
2851  it = simiIt->second.erase(it);
2852  }
2853  }
2854  }
2855  }
2856  }
2857  JLOG(m_journal.trace()) << "forwardProposedAccountTransaction:"
2858  << " iProposed=" << iProposed;
2859 
2860  if (!notify.empty())
2861  {
2862  for (InfoSub::ref isrListener : notify)
2863  isrListener->send(jvObj, true);
2864  }
2865 }
2866 
2867 void
2869 {
2870  // Ledgers are published only when they acquire sufficient validations
2871  // Holes are filled across connection loss or other catastrophe
2872 
2873  std::shared_ptr<AcceptedLedger> alpAccepted =
2874  app_.getAcceptedLedgerCache().fetch(lpAccepted->info().hash);
2875  if (!alpAccepted)
2876  {
2877  alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted, app_);
2878  app_.getAcceptedLedgerCache().canonicalize_replace_client(
2879  lpAccepted->info().hash, alpAccepted);
2880  }
2881 
2882  assert(alpAccepted->getLedger().get() == lpAccepted.get());
2883 
2884  {
2885  JLOG(m_journal.debug())
2886  << "Publishing ledger " << lpAccepted->info().seq << " "
2887  << lpAccepted->info().hash;
2888 
2890 
2891  if (!mStreamMaps[sLedger].empty())
2892  {
2894 
2895  jvObj[jss::type] = "ledgerClosed";
2896  jvObj[jss::ledger_index] = lpAccepted->info().seq;
2897  jvObj[jss::ledger_hash] = to_string(lpAccepted->info().hash);
2898  jvObj[jss::ledger_time] = Json::Value::UInt(
2899  lpAccepted->info().closeTime.time_since_epoch().count());
2900 
2901  if (!lpAccepted->rules().enabled(featureXRPFees))
2902  jvObj[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
2903  jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2904  jvObj[jss::reserve_base] =
2905  lpAccepted->fees().accountReserve(0).jsonClipped();
2906  jvObj[jss::reserve_inc] =
2907  lpAccepted->fees().increment.jsonClipped();
2908 
2909  jvObj[jss::txn_count] = Json::UInt(alpAccepted->size());
2910 
2912  {
2913  jvObj[jss::validated_ledgers] =
2915  }
2916 
2917  auto it = mStreamMaps[sLedger].begin();
2918  while (it != mStreamMaps[sLedger].end())
2919  {
2920  InfoSub::pointer p = it->second.lock();
2921  if (p)
2922  {
2923  p->send(jvObj, true);
2924  ++it;
2925  }
2926  else
2927  it = mStreamMaps[sLedger].erase(it);
2928  }
2929  }
2930 
2931  if (!mStreamMaps[sBookChanges].empty())
2932  {
2933  Json::Value jvObj = ripple::RPC::computeBookChanges(lpAccepted);
2934 
2935  auto it = mStreamMaps[sBookChanges].begin();
2936  while (it != mStreamMaps[sBookChanges].end())
2937  {
2938  InfoSub::pointer p = it->second.lock();
2939  if (p)
2940  {
2941  p->send(jvObj, true);
2942  ++it;
2943  }
2944  else
2945  it = mStreamMaps[sBookChanges].erase(it);
2946  }
2947  }
2948 
2949  {
2950  static bool firstTime = true;
2951  if (firstTime)
2952  {
2953  // First validated ledger, start delayed SubAccountHistory
2954  firstTime = false;
2955  for (auto& outer : mSubAccountHistory)
2956  {
2957  for (auto& inner : outer.second)
2958  {
2959  auto& subInfo = inner.second;
2960  if (subInfo.index_->separationLedgerSeq_ == 0)
2961  {
2963  alpAccepted->getLedger(), subInfo);
2964  }
2965  }
2966  }
2967  }
2968  }
2969  }
2970 
2971  // Don't lock since pubAcceptedTransaction is locking.
2972  for (auto const& accTx : *alpAccepted)
2973  {
2974  JLOG(m_journal.trace()) << "pubAccepted: " << accTx->getJson();
2975  pubValidatedTransaction(lpAccepted, *accTx);
2976  }
2977 }
2978 
2979 void
2981 {
2982  if (app_.config().reporting())
2983  return;
2984  ServerFeeSummary f{
2985  app_.openLedger().current()->fees().base,
2987  app_.getFeeTrack()};
2988 
2989  // only schedule the job if something has changed
2990  if (f != mLastFeeSummary)
2991  {
2993  jtCLIENT_FEE_CHANGE, "reportFeeChange->pubServer", [this]() {
2994  pubServer();
2995  });
2996  }
2997 }
2998 
2999 void
3001 {
3004  "reportConsensusStateChange->pubConsensus",
3005  [this, phase]() { pubConsensus(phase); });
3006 }
3007 
3008 inline void
3010 {
3011  m_localTX->sweep(view);
3012 }
3013 inline std::size_t
3015 {
3016  return m_localTX->size();
3017 }
3018 
3019 // This routine should only be used to publish accepted or validated
3020 // transactions.
3023  const STTx& transaction,
3024  TER result,
3025  bool validated,
3026  std::shared_ptr<ReadView const> const& ledger)
3027 {
3029  std::string sToken;
3030  std::string sHuman;
3031 
3032  transResultInfo(result, sToken, sHuman);
3033 
3034  jvObj[jss::type] = "transaction";
3035  jvObj[jss::transaction] = transaction.getJson(JsonOptions::none);
3036 
3037  if (validated)
3038  {
3039  jvObj[jss::ledger_index] = ledger->info().seq;
3040  jvObj[jss::ledger_hash] = to_string(ledger->info().hash);
3041  jvObj[jss::transaction][jss::date] =
3042  ledger->info().closeTime.time_since_epoch().count();
3043  jvObj[jss::validated] = true;
3044 
3045  // WRITEME: Put the account next seq here
3046  }
3047  else
3048  {
3049  jvObj[jss::validated] = false;
3050  jvObj[jss::ledger_current_index] = ledger->info().seq;
3051  }
3052 
3053  jvObj[jss::status] = validated ? "closed" : "proposed";
3054  jvObj[jss::engine_result] = sToken;
3055  jvObj[jss::engine_result_code] = result;
3056  jvObj[jss::engine_result_message] = sHuman;
3057 
3058  if (transaction.getTxnType() == ttOFFER_CREATE)
3059  {
3060  auto const account = transaction.getAccountID(sfAccount);
3061  auto const amount = transaction.getFieldAmount(sfTakerGets);
3062 
3063  // If the offer create is not self funded then add the owner balance
3064  if (account != amount.issue().account)
3065  {
3066  auto const ownerFunds = accountFunds(
3067  *ledger,
3068  account,
3069  amount,
3071  app_.journal("View"));
3072  jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3073  }
3074  }
3075 
3076  return jvObj;
3077 }
3078 
3079 void
3081  std::shared_ptr<ReadView const> const& ledger,
3082  const AcceptedLedgerTx& transaction)
3083 {
3084  auto const& stTxn = transaction.getTxn();
3085 
3086  Json::Value jvObj =
3087  transJson(*stTxn, transaction.getResult(), true, ledger);
3088 
3089  {
3090  auto const& meta = transaction.getMeta();
3091  jvObj[jss::meta] = meta.getJson(JsonOptions::none);
3092  RPC::insertDeliveredAmount(jvObj[jss::meta], *ledger, stTxn, meta);
3093  }
3094 
3095  {
3097 
3098  auto it = mStreamMaps[sTransactions].begin();
3099  while (it != mStreamMaps[sTransactions].end())
3100  {
3101  InfoSub::pointer p = it->second.lock();
3102 
3103  if (p)
3104  {
3105  p->send(jvObj, true);
3106  ++it;
3107  }
3108  else
3109  it = mStreamMaps[sTransactions].erase(it);
3110  }
3111 
3112  it = mStreamMaps[sRTTransactions].begin();
3113 
3114  while (it != mStreamMaps[sRTTransactions].end())
3115  {
3116  InfoSub::pointer p = it->second.lock();
3117 
3118  if (p)
3119  {
3120  p->send(jvObj, true);
3121  ++it;
3122  }
3123  else
3124  it = mStreamMaps[sRTTransactions].erase(it);
3125  }
3126  }
3127 
3128  if (transaction.getResult() == tesSUCCESS)
3129  app_.getOrderBookDB().processTxn(ledger, transaction, jvObj);
3130 
3131  pubAccountTransaction(ledger, transaction);
3132 }
3133 
3134 void
3136  std::shared_ptr<ReadView const> const& ledger,
3137  AcceptedLedgerTx const& transaction)
3138 {
3140  int iProposed = 0;
3141  int iAccepted = 0;
3142 
3143  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3144  auto const currLedgerSeq = ledger->seq();
3145  {
3147 
3148  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3150  {
3151  for (auto const& affectedAccount : transaction.getAffected())
3152  {
3153  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3154  simiIt != mSubRTAccount.end())
3155  {
3156  auto it = simiIt->second.begin();
3157 
3158  while (it != simiIt->second.end())
3159  {
3160  InfoSub::pointer p = it->second.lock();
3161 
3162  if (p)
3163  {
3164  notify.insert(p);
3165  ++it;
3166  ++iProposed;
3167  }
3168  else
3169  it = simiIt->second.erase(it);
3170  }
3171  }
3172 
3173  if (auto simiIt = mSubAccount.find(affectedAccount);
3174  simiIt != mSubAccount.end())
3175  {
3176  auto it = simiIt->second.begin();
3177  while (it != simiIt->second.end())
3178  {
3179  InfoSub::pointer p = it->second.lock();
3180 
3181  if (p)
3182  {
3183  notify.insert(p);
3184  ++it;
3185  ++iAccepted;
3186  }
3187  else
3188  it = simiIt->second.erase(it);
3189  }
3190  }
3191 
3192  if (auto histoIt = mSubAccountHistory.find(affectedAccount);
3193  histoIt != mSubAccountHistory.end())
3194  {
3195  auto& subs = histoIt->second;
3196  auto it = subs.begin();
3197  while (it != subs.end())
3198  {
3199  SubAccountHistoryInfoWeak const& info = it->second;
3200  if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3201  {
3202  ++it;
3203  continue;
3204  }
3205 
3206  if (auto isSptr = info.sinkWptr_.lock(); isSptr)
3207  {
3208  accountHistoryNotify.emplace_back(
3209  SubAccountHistoryInfo{isSptr, info.index_});
3210  ++it;
3211  }
3212  else
3213  {
3214  it = subs.erase(it);
3215  }
3216  }
3217  if (subs.empty())
3218  mSubAccountHistory.erase(histoIt);
3219  }
3220  }
3221  }
3222  }
3223 
3224  JLOG(m_journal.trace())
3225  << "pubAccountTransaction: "
3226  << "proposed=" << iProposed << ", accepted=" << iAccepted;
3227 
3228  if (!notify.empty() || !accountHistoryNotify.empty())
3229  {
3230  auto const& stTxn = transaction.getTxn();
3231 
3232  Json::Value jvObj =
3233  transJson(*stTxn, transaction.getResult(), true, ledger);
3234 
3235  {
3236  auto const& meta = transaction.getMeta();
3237 
3238  jvObj[jss::meta] = meta.getJson(JsonOptions::none);
3239  RPC::insertDeliveredAmount(jvObj[jss::meta], *ledger, stTxn, meta);
3240  }
3241 
3242  for (InfoSub::ref isrListener : notify)
3243  isrListener->send(jvObj, true);
3244 
3245  assert(!jvObj.isMember(jss::account_history_tx_stream));
3246  for (auto& info : accountHistoryNotify)
3247  {
3248  auto& index = info.index_;
3249  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3250  jvObj[jss::account_history_tx_first] = true;
3251  jvObj[jss::account_history_tx_index] = index->forwardTxIndex_++;
3252  info.sink_->send(jvObj, true);
3253  }
3254  }
3255 }
3256 
3257 void
3259  std::shared_ptr<ReadView const> const& ledger,
3260  std::shared_ptr<STTx const> const& tx,
3261  TER result)
3262 {
3264  int iProposed = 0;
3265 
3266  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3267 
3268  {
3270 
3271  if (mSubRTAccount.empty())
3272  return;
3273 
3274  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3276  {
3277  for (auto const& affectedAccount : tx->getMentionedAccounts())
3278  {
3279  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3280  simiIt != mSubRTAccount.end())
3281  {
3282  auto it = simiIt->second.begin();
3283 
3284  while (it != simiIt->second.end())
3285  {
3286  InfoSub::pointer p = it->second.lock();
3287 
3288  if (p)
3289  {
3290  notify.insert(p);
3291  ++it;
3292  ++iProposed;
3293  }
3294  else
3295  it = simiIt->second.erase(it);
3296  }
3297  }
3298  }
3299  }
3300  }
3301 
3302  JLOG(m_journal.trace()) << "pubProposedAccountTransaction: " << iProposed;
3303 
3304  if (!notify.empty() || !accountHistoryNotify.empty())
3305  {
3306  Json::Value jvObj = transJson(*tx, result, false, ledger);
3307 
3308  for (InfoSub::ref isrListener : notify)
3309  isrListener->send(jvObj, true);
3310 
3311  assert(!jvObj.isMember(jss::account_history_tx_stream));
3312  for (auto& info : accountHistoryNotify)
3313  {
3314  auto& index = info.index_;
3315  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3316  jvObj[jss::account_history_tx_first] = true;
3317  jvObj[jss::account_history_tx_index] = index->forwardTxIndex_++;
3318  info.sink_->send(jvObj, true);
3319  }
3320  }
3321 }
3322 
3323 //
3324 // Monitoring
3325 //
3326 
3327 void
3329  InfoSub::ref isrListener,
3330  hash_set<AccountID> const& vnaAccountIDs,
3331  bool rt)
3332 {
3333  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3334 
3335  for (auto const& naAccountID : vnaAccountIDs)
3336  {
3337  JLOG(m_journal.trace())
3338  << "subAccount: account: " << toBase58(naAccountID);
3339 
3340  isrListener->insertSubAccountInfo(naAccountID, rt);
3341  }
3342 
3344 
3345  for (auto const& naAccountID : vnaAccountIDs)
3346  {
3347  auto simIterator = subMap.find(naAccountID);
3348  if (simIterator == subMap.end())
3349  {
3350  // Not found, note that account has a new single listner.
3351  SubMapType usisElement;
3352  usisElement[isrListener->getSeq()] = isrListener;
3353  // VFALCO NOTE This is making a needless copy of naAccountID
3354  subMap.insert(simIterator, make_pair(naAccountID, usisElement));
3355  }
3356  else
3357  {
3358  // Found, note that the account has another listener.
3359  simIterator->second[isrListener->getSeq()] = isrListener;
3360  }
3361  }
3362 }
3363 
3364 void
3366  InfoSub::ref isrListener,
3367  hash_set<AccountID> const& vnaAccountIDs,
3368  bool rt)
3369 {
3370  for (auto const& naAccountID : vnaAccountIDs)
3371  {
3372  // Remove from the InfoSub
3373  isrListener->deleteSubAccountInfo(naAccountID, rt);
3374  }
3375 
3376  // Remove from the server
3377  unsubAccountInternal(isrListener->getSeq(), vnaAccountIDs, rt);
3378 }
3379 
3380 void
3382  std::uint64_t uSeq,
3383  hash_set<AccountID> const& vnaAccountIDs,
3384  bool rt)
3385 {
3387 
3388  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3389 
3390  for (auto const& naAccountID : vnaAccountIDs)
3391  {
3392  auto simIterator = subMap.find(naAccountID);
3393 
3394  if (simIterator != subMap.end())
3395  {
3396  // Found
3397  simIterator->second.erase(uSeq);
3398 
3399  if (simIterator->second.empty())
3400  {
3401  // Don't need hash entry.
3402  subMap.erase(simIterator);
3403  }
3404  }
3405  }
3406 }
3407 
3408 void
3410 {
3411  enum DatabaseType { Postgres, Sqlite, None };
3412  static const auto databaseType = [&]() -> DatabaseType {
3413 #ifdef RIPPLED_REPORTING
3414  if (app_.config().reporting())
3415  {
3416  // Use a dynamic_cast to return DatabaseType::None
3417  // on failure.
3418  if (dynamic_cast<PostgresDatabase*>(&app_.getRelationalDatabase()))
3419  {
3420  return DatabaseType::Postgres;
3421  }
3422  return DatabaseType::None;
3423  }
3424  else
3425  {
3426  // Use a dynamic_cast to return DatabaseType::None
3427  // on failure.
3428  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3429  {
3430  return DatabaseType::Sqlite;
3431  }
3432  return DatabaseType::None;
3433  }
3434 #else
3435  // Use a dynamic_cast to return DatabaseType::None
3436  // on failure.
3437  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3438  {
3439  return DatabaseType::Sqlite;
3440  }
3441  return DatabaseType::None;
3442 #endif
3443  }();
3444 
3445  if (databaseType == DatabaseType::None)
3446  {
3447  JLOG(m_journal.error())
3448  << "AccountHistory job for account "
3449  << toBase58(subInfo.index_->accountId_) << " no database";
3450  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3451  {
3452  sptr->send(rpcError(rpcINTERNAL), true);
3453  unsubAccountHistory(sptr, subInfo.index_->accountId_, false);
3454  }
3455  return;
3456  }
3457 
3460  "AccountHistoryTxStream",
3461  [this, dbType = databaseType, subInfo]() {
3462  auto const& accountId = subInfo.index_->accountId_;
3463  auto& lastLedgerSeq = subInfo.index_->historyLastLedgerSeq_;
3464  auto& txHistoryIndex = subInfo.index_->historyTxIndex_;
3465 
3466  JLOG(m_journal.trace())
3467  << "AccountHistory job for account " << toBase58(accountId)
3468  << " started. lastLedgerSeq=" << lastLedgerSeq;
3469 
3470  auto isFirstTx = [&](std::shared_ptr<Transaction> const& tx,
3471  std::shared_ptr<TxMeta> const& meta) -> bool {
3472  /*
3473  * genesis account: first tx is the one with seq 1
3474  * other account: first tx is the one created the account
3475  */
3476  if (accountId == genesisAccountId)
3477  {
3478  auto stx = tx->getSTransaction();
3479  if (stx->getAccountID(sfAccount) == accountId &&
3480  stx->getSeqProxy().value() == 1)
3481  return true;
3482  }
3483 
3484  for (auto& node : meta->getNodes())
3485  {
3486  if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3487  continue;
3488 
3489  if (node.isFieldPresent(sfNewFields))
3490  {
3491  if (auto inner = dynamic_cast<const STObject*>(
3492  node.peekAtPField(sfNewFields));
3493  inner)
3494  {
3495  if (inner->isFieldPresent(sfAccount) &&
3496  inner->getAccountID(sfAccount) == accountId)
3497  {
3498  return true;
3499  }
3500  }
3501  }
3502  }
3503 
3504  return false;
3505  };
3506 
3507  auto send = [&](Json::Value const& jvObj,
3508  bool unsubscribe) -> bool {
3509  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3510  {
3511  sptr->send(jvObj, true);
3512  if (unsubscribe)
3513  unsubAccountHistory(sptr, accountId, false);
3514  return true;
3515  }
3516 
3517  return false;
3518  };
3519 
3520  auto getMoreTxns =
3521  [&](std::uint32_t minLedger,
3522  std::uint32_t maxLedger,
3527  switch (dbType)
3528  {
3529  case Postgres: {
3530  auto db = static_cast<PostgresDatabase*>(
3533  args.account = accountId;
3534  LedgerRange range{minLedger, maxLedger};
3535  args.ledger = range;
3536  args.marker = marker;
3537  auto [txResult, status] = db->getAccountTx(args);
3538  if (status != rpcSUCCESS)
3539  {
3540  JLOG(m_journal.debug())
3541  << "AccountHistory job for account "
3542  << toBase58(accountId)
3543  << " getAccountTx failed";
3544  return {};
3545  }
3546 
3547  if (auto txns =
3548  std::get_if<RelationalDatabase::AccountTxs>(
3549  &txResult.transactions);
3550  txns)
3551  {
3552  return std::make_pair(*txns, txResult.marker);
3553  }
3554  else
3555  {
3556  JLOG(m_journal.debug())
3557  << "AccountHistory job for account "
3558  << toBase58(accountId)
3559  << " getAccountTx wrong data";
3560  return {};
3561  }
3562  }
3563  case Sqlite: {
3564  auto db = static_cast<SQLiteDatabase*>(
3567  accountId, minLedger, maxLedger, marker, 0, true};
3568  return db->newestAccountTxPage(options);
3569  }
3570  default: {
3571  assert(false);
3572  return {};
3573  }
3574  }
3575  };
3576 
3577  /*
3578  * search backward until the genesis ledger or asked to stop
3579  */
3580  while (lastLedgerSeq >= 2 && !subInfo.index_->stopHistorical_)
3581  {
3582  int feeChargeCount = 0;
3583  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3584  {
3585  sptr->getConsumer().charge(Resource::feeMediumBurdenRPC);
3586  ++feeChargeCount;
3587  }
3588  else
3589  {
3590  JLOG(m_journal.trace())
3591  << "AccountHistory job for account "
3592  << toBase58(accountId) << " no InfoSub. Fee charged "
3593  << feeChargeCount << " times.";
3594  return;
3595  }
3596 
3597  // try to search in 1024 ledgers till reaching genesis ledgers
3598  auto startLedgerSeq =
3599  (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3600  JLOG(m_journal.trace())
3601  << "AccountHistory job for account " << toBase58(accountId)
3602  << ", working on ledger range [" << startLedgerSeq << ","
3603  << lastLedgerSeq << "]";
3604 
3605  auto haveRange = [&]() -> bool {
3606  std::uint32_t validatedMin = UINT_MAX;
3607  std::uint32_t validatedMax = 0;
3608  auto haveSomeValidatedLedgers =
3610  validatedMin, validatedMax);
3611 
3612  return haveSomeValidatedLedgers &&
3613  validatedMin <= startLedgerSeq &&
3614  lastLedgerSeq <= validatedMax;
3615  }();
3616 
3617  if (!haveRange)
3618  {
3619  JLOG(m_journal.debug())
3620  << "AccountHistory reschedule job for account "
3621  << toBase58(accountId) << ", incomplete ledger range ["
3622  << startLedgerSeq << "," << lastLedgerSeq << "]";
3623  setAccountHistoryJobTimer(subInfo);
3624  return;
3625  }
3626 
3628  while (!subInfo.index_->stopHistorical_)
3629  {
3630  auto dbResult =
3631  getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3632  if (!dbResult)
3633  {
3634  JLOG(m_journal.debug())
3635  << "AccountHistory job for account "
3636  << toBase58(accountId) << " getMoreTxns failed.";
3637  send(rpcError(rpcINTERNAL), true);
3638  return;
3639  }
3640 
3641  auto const& txns = dbResult->first;
3642  marker = dbResult->second;
3643  for (auto const& [tx, meta] : txns)
3644  {
3645  if (!tx || !meta)
3646  {
3647  JLOG(m_journal.debug())
3648  << "AccountHistory job for account "
3649  << toBase58(accountId) << " empty tx or meta.";
3650  send(rpcError(rpcINTERNAL), true);
3651  return;
3652  }
3653  auto curTxLedger =
3655  tx->getLedger());
3656  if (!curTxLedger)
3657  {
3658  JLOG(m_journal.debug())
3659  << "AccountHistory job for account "
3660  << toBase58(accountId) << " no ledger.";
3661  send(rpcError(rpcINTERNAL), true);
3662  return;
3663  }
3665  tx->getSTransaction();
3666  if (!stTxn)
3667  {
3668  JLOG(m_journal.debug())
3669  << "AccountHistory job for account "
3670  << toBase58(accountId)
3671  << " getSTransaction failed.";
3672  send(rpcError(rpcINTERNAL), true);
3673  return;
3674  }
3675  Json::Value jvTx = transJson(
3676  *stTxn, meta->getResultTER(), true, curTxLedger);
3677  jvTx[jss::meta] = meta->getJson(JsonOptions::none);
3678  jvTx[jss::account_history_tx_index] = txHistoryIndex--;
3680  jvTx[jss::meta], *curTxLedger, stTxn, *meta);
3681  if (isFirstTx(tx, meta))
3682  {
3683  jvTx[jss::account_history_tx_first] = true;
3684  send(jvTx, false);
3685 
3686  JLOG(m_journal.trace())
3687  << "AccountHistory job for account "
3688  << toBase58(accountId)
3689  << " done, found last tx.";
3690  return;
3691  }
3692  else
3693  {
3694  send(jvTx, false);
3695  }
3696  }
3697 
3698  if (marker)
3699  {
3700  JLOG(m_journal.trace())
3701  << "AccountHistory job for account "
3702  << toBase58(accountId)
3703  << " paging, marker=" << marker->ledgerSeq << ":"
3704  << marker->txnSeq;
3705  }
3706  else
3707  {
3708  break;
3709  }
3710  }
3711 
3712  if (!subInfo.index_->stopHistorical_)
3713  {
3714  lastLedgerSeq = startLedgerSeq - 1;
3715  if (lastLedgerSeq <= 1)
3716  {
3717  JLOG(m_journal.trace())
3718  << "AccountHistory job for account "
3719  << toBase58(accountId)
3720  << " done, reached genesis ledger.";
3721  return;
3722  }
3723  }
3724  }
3725  });
3726 }
3727 
3728 void
3730  std::shared_ptr<ReadView const> const& ledger,
3731  SubAccountHistoryInfoWeak& subInfo)
3732 {
3733  subInfo.index_->separationLedgerSeq_ = ledger->seq();
3734  auto const& accountId = subInfo.index_->accountId_;
3735  auto const accountKeylet = keylet::account(accountId);
3736  if (!ledger->exists(accountKeylet))
3737  {
3738  JLOG(m_journal.debug())
3739  << "subAccountHistoryStart, no account " << toBase58(accountId)
3740  << ", no need to add AccountHistory job.";
3741  return;
3742  }
3743  if (accountId == genesisAccountId)
3744  {
3745  if (auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3746  {
3747  if (sleAcct->getFieldU32(sfSequence) == 1)
3748  {
3749  JLOG(m_journal.debug())
3750  << "subAccountHistoryStart, genesis account "
3751  << toBase58(accountId)
3752  << " does not have tx, no need to add AccountHistory job.";
3753  return;
3754  }
3755  }
3756  else
3757  {
3758  assert(false);
3759  return;
3760  }
3761  }
3762  subInfo.index_->historyLastLedgerSeq_ = ledger->seq();
3763  subInfo.index_->haveHistorical_ = true;
3764 
3765  JLOG(m_journal.debug())
3766  << "subAccountHistoryStart, add AccountHistory job: accountId="
3767  << toBase58(accountId) << ", currentLedgerSeq=" << ledger->seq();
3768 
3769  addAccountHistoryJob(subInfo);
3770 }
3771 
3774  InfoSub::ref isrListener,
3775  AccountID const& accountId)
3776 {
3777  if (!isrListener->insertSubAccountHistory(accountId))
3778  {
3779  JLOG(m_journal.debug())
3780  << "subAccountHistory, already subscribed to account "
3781  << toBase58(accountId);
3782  return rpcINVALID_PARAMS;
3783  }
3784 
3787  isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3788  auto simIterator = mSubAccountHistory.find(accountId);
3789  if (simIterator == mSubAccountHistory.end())
3790  {
3792  inner.emplace(isrListener->getSeq(), ahi);
3794  simIterator, std::make_pair(accountId, inner));
3795  }
3796  else
3797  {
3798  simIterator->second.emplace(isrListener->getSeq(), ahi);
3799  }
3800 
3801  auto const ledger = app_.getLedgerMaster().getValidatedLedger();
3802  if (ledger)
3803  {
3804  subAccountHistoryStart(ledger, ahi);
3805  }
3806  else
3807  {
3808  // The node does not have validated ledgers, so wait for
3809  // one before start streaming.
3810  // In this case, the subscription is also considered successful.
3811  JLOG(m_journal.debug())
3812  << "subAccountHistory, no validated ledger yet, delay start";
3813  }
3814 
3815  return rpcSUCCESS;
3816 }
3817 
3818 void
3820  InfoSub::ref isrListener,
3821  AccountID const& account,
3822  bool historyOnly)
3823 {
3824  if (!historyOnly)
3825  isrListener->deleteSubAccountHistory(account);
3826  unsubAccountHistoryInternal(isrListener->getSeq(), account, historyOnly);
3827 }
3828 
3829 void
3831  std::uint64_t seq,
3832  const AccountID& account,
3833  bool historyOnly)
3834 {
3836  auto simIterator = mSubAccountHistory.find(account);
3837  if (simIterator != mSubAccountHistory.end())
3838  {
3839  auto& subInfoMap = simIterator->second;
3840  auto subInfoIter = subInfoMap.find(seq);
3841  if (subInfoIter != subInfoMap.end())
3842  {
3843  subInfoIter->second.index_->stopHistorical_ = true;
3844  }
3845 
3846  if (!historyOnly)
3847  {
3848  simIterator->second.erase(seq);
3849  if (simIterator->second.empty())
3850  {
3851  mSubAccountHistory.erase(simIterator);
3852  }
3853  }
3854  JLOG(m_journal.debug())
3855  << "unsubAccountHistory, account " << toBase58(account)
3856  << ", historyOnly = " << (historyOnly ? "true" : "false");
3857  }
3858 }
3859 
3860 bool
3861 NetworkOPsImp::subBook(InfoSub::ref isrListener, Book const& book)
3862 {
3863  if (auto listeners = app_.getOrderBookDB().makeBookListeners(book))
3864  listeners->addSubscriber(isrListener);
3865  else
3866  assert(false);
3867  return true;
3868 }
3869 
3870 bool
3872 {
3873  if (auto listeners = app_.getOrderBookDB().getBookListeners(book))
3874  listeners->removeSubscriber(uSeq);
3875 
3876  return true;
3877 }
3878 
3882 {
3883  // This code-path is exclusively used when the server is in standalone
3884  // mode via `ledger_accept`
3885  assert(m_standalone);
3886 
3887  if (!m_standalone)
3888  Throw<std::runtime_error>(
3889  "Operation only possible in STANDALONE mode.");
3890 
3891  // FIXME Could we improve on this and remove the need for a specialized
3892  // API in Consensus?
3894  mConsensus.simulate(app_.timeKeeper().closeTime(), consensusDelay);
3895  return m_ledgerMaster.getCurrentLedger()->info().seq;
3896 }
3897 
3898 // <-- bool: true=added, false=already there
3899 bool
3901 {
3902  if (auto lpClosed = m_ledgerMaster.getValidatedLedger())
3903  {
3904  jvResult[jss::ledger_index] = lpClosed->info().seq;
3905  jvResult[jss::ledger_hash] = to_string(lpClosed->info().hash);
3906  jvResult[jss::ledger_time] = Json::Value::UInt(
3907  lpClosed->info().closeTime.time_since_epoch().count());
3908  if (!lpClosed->rules().enabled(featureXRPFees))
3909  jvResult[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
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();
3914  }
3915 
3917  {
3918  jvResult[jss::validated_ledgers] =
3920  }
3921 
3923  return mStreamMaps[sLedger]
3924  .emplace(isrListener->getSeq(), isrListener)
3925  .second;
3926 }
3927 
3928 // <-- bool: true=added, false=already there
3929 bool
3931 {
3933  return mStreamMaps[sBookChanges]
3934  .emplace(isrListener->getSeq(), isrListener)
3935  .second;
3936 }
3937 
3938 // <-- bool: true=erased, false=was not there
3939 bool
3941 {
3943  return mStreamMaps[sLedger].erase(uSeq);
3944 }
3945 
3946 // <-- bool: true=erased, false=was not there
3947 bool
3949 {
3951  return mStreamMaps[sBookChanges].erase(uSeq);
3952 }
3953 
3954 // <-- bool: true=added, false=already there
3955 bool
3957 {
3959  return mStreamMaps[sManifests]
3960  .emplace(isrListener->getSeq(), isrListener)
3961  .second;
3962 }
3963 
3964 // <-- bool: true=erased, false=was not there
3965 bool
3967 {
3969  return mStreamMaps[sManifests].erase(uSeq);
3970 }
3971 
3972 // <-- bool: true=added, false=already there
3973 bool
3975  InfoSub::ref isrListener,
3976  Json::Value& jvResult,
3977  bool admin)
3978 {
3979  uint256 uRandom;
3980 
3981  if (m_standalone)
3982  jvResult[jss::stand_alone] = m_standalone;
3983 
3984  // CHECKME: is it necessary to provide a random number here?
3985  beast::rngfill(uRandom.begin(), uRandom.size(), crypto_prng());
3986 
3987  auto const& feeTrack = app_.getFeeTrack();
3988  jvResult[jss::random] = to_string(uRandom);
3989  jvResult[jss::server_status] = strOperatingMode(admin);
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] =
3995 
3997  return mStreamMaps[sServer]
3998  .emplace(isrListener->getSeq(), isrListener)
3999  .second;
4000 }
4001 
4002 // <-- bool: true=erased, false=was not there
4003 bool
4005 {
4007  return mStreamMaps[sServer].erase(uSeq);
4008 }
4009 
4010 // <-- bool: true=added, false=already there
4011 bool
4013 {
4015  return mStreamMaps[sTransactions]
4016  .emplace(isrListener->getSeq(), isrListener)
4017  .second;
4018 }
4019 
4020 // <-- bool: true=erased, false=was not there
4021 bool
4023 {
4025  return mStreamMaps[sTransactions].erase(uSeq);
4026 }
4027 
4028 // <-- bool: true=added, false=already there
4029 bool
4031 {
4034  .emplace(isrListener->getSeq(), isrListener)
4035  .second;
4036 }
4037 
4038 // <-- bool: true=erased, false=was not there
4039 bool
4041 {
4043  return mStreamMaps[sRTTransactions].erase(uSeq);
4044 }
4045 
4046 // <-- bool: true=added, false=already there
4047 bool
4049 {
4051  return mStreamMaps[sValidations]
4052  .emplace(isrListener->getSeq(), isrListener)
4053  .second;
4054 }
4055 
4056 void
4058 {
4059  accounting_.json(obj);
4060 }
4061 
4062 // <-- bool: true=erased, false=was not there
4063 bool
4065 {
4067  return mStreamMaps[sValidations].erase(uSeq);
4068 }
4069 
4070 // <-- bool: true=added, false=already there
4071 bool
4073 {
4075  return mStreamMaps[sPeerStatus]
4076  .emplace(isrListener->getSeq(), isrListener)
4077  .second;
4078 }
4079 
4080 // <-- bool: true=erased, false=was not there
4081 bool
4083 {
4085  return mStreamMaps[sPeerStatus].erase(uSeq);
4086 }
4087 
4088 // <-- bool: true=added, false=already there
4089 bool
4091 {
4094  .emplace(isrListener->getSeq(), isrListener)
4095  .second;
4096 }
4097 
4098 // <-- bool: true=erased, false=was not there
4099 bool
4101 {
4103  return mStreamMaps[sConsensusPhase].erase(uSeq);
4104 }
4105 
4108 {
4110 
4111  subRpcMapType::iterator it = mRpcSubMap.find(strUrl);
4112 
4113  if (it != mRpcSubMap.end())
4114  return it->second;
4115 
4116  return InfoSub::pointer();
4117 }
4118 
4121 {
4123 
4124  mRpcSubMap.emplace(strUrl, rspEntry);
4125 
4126  return rspEntry;
4127 }
4128 
4129 bool
4131 {
4133  auto pInfo = findRpcSub(strUrl);
4134 
4135  if (!pInfo)
4136  return false;
4137 
4138  // check to see if any of the stream maps still hold a weak reference to
4139  // this entry before removing
4140  for (SubMapType const& map : mStreamMaps)
4141  {
4142  if (map.find(pInfo->getSeq()) != map.end())
4143  return false;
4144  }
4145  mRpcSubMap.erase(strUrl);
4146  return true;
4147 }
4148 
4149 #ifndef USE_NEW_BOOK_PAGE
4150 
4151 // NIKB FIXME this should be looked at. There's no reason why this shouldn't
4152 // work, but it demonstrated poor performance.
4153 //
4154 void
4157  Book const& book,
4158  AccountID const& uTakerID,
4159  bool const bProof,
4160  unsigned int iLimit,
4161  Json::Value const& jvMarker,
4162  Json::Value& jvResult)
4163 { // CAUTION: This is the old get book page logic
4164  Json::Value& jvOffers =
4165  (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4166 
4168  const uint256 uBookBase = getBookBase(book);
4169  const uint256 uBookEnd = getQualityNext(uBookBase);
4170  uint256 uTipIndex = uBookBase;
4171 
4172  if (auto stream = m_journal.trace())
4173  {
4174  stream << "getBookPage:" << book;
4175  stream << "getBookPage: uBookBase=" << uBookBase;
4176  stream << "getBookPage: uBookEnd=" << uBookEnd;
4177  stream << "getBookPage: uTipIndex=" << uTipIndex;
4178  }
4179 
4180  ReadView const& view = *lpLedger;
4181 
4182  bool const bGlobalFreeze = isGlobalFrozen(view, book.out.account) ||
4183  isGlobalFrozen(view, book.in.account);
4184 
4185  bool bDone = false;
4186  bool bDirectAdvance = true;
4187 
4188  std::shared_ptr<SLE const> sleOfferDir;
4189  uint256 offerIndex;
4190  unsigned int uBookEntry;
4191  STAmount saDirRate;
4192 
4193  auto const rate = transferRate(view, book.out.account);
4194  auto viewJ = app_.journal("View");
4195 
4196  while (!bDone && iLimit-- > 0)
4197  {
4198  if (bDirectAdvance)
4199  {
4200  bDirectAdvance = false;
4201 
4202  JLOG(m_journal.trace()) << "getBookPage: bDirectAdvance";
4203 
4204  auto const ledgerIndex = view.succ(uTipIndex, uBookEnd);
4205  if (ledgerIndex)
4206  sleOfferDir = view.read(keylet::page(*ledgerIndex));
4207  else
4208  sleOfferDir.reset();
4209 
4210  if (!sleOfferDir)
4211  {
4212  JLOG(m_journal.trace()) << "getBookPage: bDone";
4213  bDone = true;
4214  }
4215  else
4216  {
4217  uTipIndex = sleOfferDir->key();
4218  saDirRate = amountFromQuality(getQuality(uTipIndex));
4219 
4220  cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4221 
4222  JLOG(m_journal.trace())
4223  << "getBookPage: uTipIndex=" << uTipIndex;
4224  JLOG(m_journal.trace())
4225  << "getBookPage: offerIndex=" << offerIndex;
4226  }
4227  }
4228 
4229  if (!bDone)
4230  {
4231  auto sleOffer = view.read(keylet::offer(offerIndex));
4232 
4233  if (sleOffer)
4234  {
4235  auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4236  auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4237  auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4238  STAmount saOwnerFunds;
4239  bool firstOwnerOffer(true);
4240 
4241  if (book.out.account == uOfferOwnerID)
4242  {
4243  // If an offer is selling issuer's own IOUs, it is fully
4244  // funded.
4245  saOwnerFunds = saTakerGets;
4246  }
4247  else if (bGlobalFreeze)
4248  {
4249  // If either asset is globally frozen, consider all offers
4250  // that aren't ours to be totally unfunded
4251  saOwnerFunds.clear(book.out);
4252  }
4253  else
4254  {
4255  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4256  if (umBalanceEntry != umBalance.end())
4257  {
4258  // Found in running balance table.
4259 
4260  saOwnerFunds = umBalanceEntry->second;
4261  firstOwnerOffer = false;
4262  }
4263  else
4264  {
4265  // Did not find balance in table.
4266 
4267  saOwnerFunds = accountHolds(
4268  view,
4269  uOfferOwnerID,
4270  book.out.currency,
4271  book.out.account,
4273  viewJ);
4274 
4275  if (saOwnerFunds < beast::zero)
4276  {
4277  // Treat negative funds as zero.
4278 
4279  saOwnerFunds.clear();
4280  }
4281  }
4282  }
4283 
4284  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4285 
4286  STAmount saTakerGetsFunded;
4287  STAmount saOwnerFundsLimit = saOwnerFunds;
4288  Rate offerRate = parityRate;
4289 
4290  if (rate != parityRate
4291  // Have a tranfer fee.
4292  && uTakerID != book.out.account
4293  // Not taking offers of own IOUs.
4294  && book.out.account != uOfferOwnerID)
4295  // Offer owner not issuing ownfunds
4296  {
4297  // Need to charge a transfer fee to offer owner.
4298  offerRate = rate;
4299  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4300  }
4301 
4302  if (saOwnerFundsLimit >= saTakerGets)
4303  {
4304  // Sufficient funds no shenanigans.
4305  saTakerGetsFunded = saTakerGets;
4306  }
4307  else
4308  {
4309  // Only provide, if not fully funded.
4310 
4311  saTakerGetsFunded = saOwnerFundsLimit;
4312 
4313  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4314  std::min(
4315  saTakerPays,
4316  multiply(
4317  saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4318  .setJson(jvOffer[jss::taker_pays_funded]);
4319  }
4320 
4321  STAmount saOwnerPays = (parityRate == offerRate)
4322  ? saTakerGetsFunded
4323  : std::min(
4324  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4325 
4326  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4327 
4328  // Include all offers funded and unfunded
4329  Json::Value& jvOf = jvOffers.append(jvOffer);
4330  jvOf[jss::quality] = saDirRate.getText();
4331 
4332  if (firstOwnerOffer)
4333  jvOf[jss::owner_funds] = saOwnerFunds.getText();
4334  }
4335  else
4336  {
4337  JLOG(m_journal.warn()) << "Missing offer";
4338  }
4339 
4340  if (!cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4341  {
4342  bDirectAdvance = true;
4343  }
4344  else
4345  {
4346  JLOG(m_journal.trace())
4347  << "getBookPage: offerIndex=" << offerIndex;
4348  }
4349  }
4350  }
4351 
4352  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4353  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4354 }
4355 
4356 #else
4357 
4358 // This is the new code that uses the book iterators
4359 // It has temporarily been disabled
4360 
4361 void
4364  Book const& book,
4365  AccountID const& uTakerID,
4366  bool const bProof,
4367  unsigned int iLimit,
4368  Json::Value const& jvMarker,
4369  Json::Value& jvResult)
4370 {
4371  auto& jvOffers = (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4372 
4374 
4375  MetaView lesActive(lpLedger, tapNONE, true);
4376  OrderBookIterator obIterator(lesActive, book);
4377 
4378  auto const rate = transferRate(lesActive, book.out.account);
4379 
4380  const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.out.account) ||
4381  lesActive.isGlobalFrozen(book.in.account);
4382 
4383  while (iLimit-- > 0 && obIterator.nextOffer())
4384  {
4385  SLE::pointer sleOffer = obIterator.getCurrentOffer();
4386  if (sleOffer)
4387  {
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();
4392  STAmount saOwnerFunds;
4393 
4394  if (book.out.account == uOfferOwnerID)
4395  {
4396  // If offer is selling issuer's own IOUs, it is fully funded.
4397  saOwnerFunds = saTakerGets;
4398  }
4399  else if (bGlobalFreeze)
4400  {
4401  // If either asset is globally frozen, consider all offers
4402  // that aren't ours to be totally unfunded
4403  saOwnerFunds.clear(book.out);
4404  }
4405  else
4406  {
4407  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4408 
4409  if (umBalanceEntry != umBalance.end())
4410  {
4411  // Found in running balance table.
4412 
4413  saOwnerFunds = umBalanceEntry->second;
4414  }
4415  else
4416  {
4417  // Did not find balance in table.
4418 
4419  saOwnerFunds = lesActive.accountHolds(
4420  uOfferOwnerID,
4421  book.out.currency,
4422  book.out.account,
4424 
4425  if (saOwnerFunds.isNegative())
4426  {
4427  // Treat negative funds as zero.
4428 
4429  saOwnerFunds.zero();
4430  }
4431  }
4432  }
4433 
4434  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4435 
4436  STAmount saTakerGetsFunded;
4437  STAmount saOwnerFundsLimit = saOwnerFunds;
4438  Rate offerRate = parityRate;
4439 
4440  if (rate != parityRate
4441  // Have a tranfer fee.
4442  && uTakerID != book.out.account
4443  // Not taking offers of own IOUs.
4444  && book.out.account != uOfferOwnerID)
4445  // Offer owner not issuing ownfunds
4446  {
4447  // Need to charge a transfer fee to offer owner.
4448  offerRate = rate;
4449  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4450  }
4451 
4452  if (saOwnerFundsLimit >= saTakerGets)
4453  {
4454  // Sufficient funds no shenanigans.
4455  saTakerGetsFunded = saTakerGets;
4456  }
4457  else
4458  {
4459  // Only provide, if not fully funded.
4460  saTakerGetsFunded = saOwnerFundsLimit;
4461 
4462  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4463 
4464  // TOOD(tom): The result of this expression is not used - what's
4465  // going on here?
4466  std::min(
4467  saTakerPays,
4468  multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4469  .setJson(jvOffer[jss::taker_pays_funded]);
4470  }
4471 
4472  STAmount saOwnerPays = (parityRate == offerRate)
4473  ? saTakerGetsFunded
4474  : std::min(
4475  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4476 
4477  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4478 
4479  if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4480  {
4481  // Only provide funded offers and offers of the taker.
4482  Json::Value& jvOf = jvOffers.append(jvOffer);
4483  jvOf[jss::quality] = saDirRate.getText();
4484  }
4485  }
4486  }
4487 
4488  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4489  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4490 }
4491 
4492 #endif
4493 
4494 inline void
4496 {
4497  auto [counters, mode, start, initialSync] = accounting_.getCounterData();
4498  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4499  std::chrono::steady_clock::now() - start);
4500  counters[static_cast<std::size_t>(mode)].dur += current;
4501 
4504  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4505  .dur.count());
4507  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4508  .dur.count());
4510  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].dur.count());
4512  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4513  .dur.count());
4515  counters[static_cast<std::size_t>(OperatingMode::FULL)].dur.count());
4516 
4518  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4519  .transitions);
4521  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4522  .transitions);
4524  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].transitions);
4526  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4527  .transitions);
4529  counters[static_cast<std::size_t>(OperatingMode::FULL)].transitions);
4530 }
4531 
4532 void
4534 {
4535  auto now = std::chrono::steady_clock::now();
4536 
4537  std::lock_guard lock(mutex_);
4538  ++counters_[static_cast<std::size_t>(om)].transitions;
4539  if (om == OperatingMode::FULL &&
4540  counters_[static_cast<std::size_t>(om)].transitions == 1)
4541  {
4542  initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4543  now - processStart_)
4544  .count();
4545  }
4546  counters_[static_cast<std::size_t>(mode_)].dur +=
4547  std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4548 
4549  mode_ = om;
4550  start_ = now;
4551 }
4552 
4553 void
4555 {
4556  auto [counters, mode, start, initialSync] = getCounterData();
4557  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4558  std::chrono::steady_clock::now() - start);
4559  counters[static_cast<std::size_t>(mode)].dur += current;
4560 
4561  obj[jss::state_accounting] = Json::objectValue;
4562  for (std::size_t i = static_cast<std::size_t>(OperatingMode::DISCONNECTED);
4563  i <= static_cast<std::size_t>(OperatingMode::FULL);
4564  ++i)
4565  {
4566  obj[jss::state_accounting][states_[i]] = Json::objectValue;
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());
4570  }
4571  obj[jss::server_state_duration_us] = std::to_string(current.count());
4572  if (initialSync)
4573  obj[jss::initial_sync_duration_us] = std::to_string(initialSync);
4574 }
4575 
4576 //------------------------------------------------------------------------------
4577 
4580  Application& app,
4581  NetworkOPs::clock_type& clock,
4582  bool standalone,
4583  std::size_t minPeerCount,
4584  bool startvalid,
4585  JobQueue& job_queue,
4586  LedgerMaster& ledgerMaster,
4587  ValidatorKeys const& validatorKeys,
4588  boost::asio::io_service& io_svc,
4589  beast::Journal journal,
4590  beast::insight::Collector::ptr const& collector)
4591 {
4592  return std::make_unique<NetworkOPsImp>(
4593  app,
4594  clock,
4595  standalone,
4596  minPeerCount,
4597  startvalid,
4598  job_queue,
4599  ledgerMaster,
4600  validatorKeys,
4601  io_svc,
4602  journal,
4603  collector);
4604 }
4605 
4606 } // namespace ripple
ripple::SQLiteDatabase
Definition: SQLiteDatabase.h:27
ripple::NetworkOPsImp::forwardManifest
void forwardManifest(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2762
ripple::NetworkOPsImp::unsubValidations
bool unsubValidations(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4064
ripple::NetworkOPsImp::Stats::hook
beast::insight::Hook hook
Definition: NetworkOPs.cpp:815
ripple::STTx::getTxnType
TxType getTxnType() const
Definition: STTx.h:179
ripple::setup_FeeVote
FeeVote::Setup setup_FeeVote(Section const &section)
Build FeeVote::Setup from a config section.
Definition: FeeVoteImpl.cpp:339
ripple::NetworkOPsImp::subValidations
bool subValidations(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4048
ripple::NetworkOPsImp::processHeartbeatTimer
void processHeartbeatTimer()
Definition: NetworkOPs.cpp:1004
ripple::NetworkOPs
Provides server functionality for clients.
Definition: NetworkOPs.h:86
ripple::sfIndexNext
const SF_UINT64 sfIndexNext
ripple::NetworkOPsImp::SubAccountHistoryIndex::historyLastLedgerSeq_
std::uint32_t historyLastLedgerSeq_
Definition: NetworkOPs.cpp:670
ripple::LedgerMaster::getValidatedRange
bool getValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
Definition: LedgerMaster.cpp:630
ripple::NetworkOPsImp::mapComplete
void mapComplete(std::shared_ptr< SHAMap > const &map, bool fromAcquire) override
Definition: NetworkOPs.cpp:1864
ripple::NetworkOPsImp::setClusterTimer
void setClusterTimer()
Definition: NetworkOPs.cpp:975
ripple::Application
Definition: Application.h:115
ripple::transferRate
Rate transferRate(ReadView const &view, AccountID const &issuer)
Definition: View.cpp:471
ripple::TimeKeeper::nowOffset
virtual std::chrono::duration< std::int32_t > nowOffset() const =0
ripple::cdirNext
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.
Definition: View.cpp:145
ripple::ClusterNode
Definition: ClusterNode.h:30
ripple::NetworkOPsImp::SubTypes
SubTypes
Definition: NetworkOPs.cpp:743
ripple::NetworkOPsImp::unsubConsensus
bool unsubConsensus(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4100
ripple::jtTRANSACTION
@ jtTRANSACTION
Definition: Job.h:63
ripple::Manifest::domain
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition: Manifest.h:95
ripple::Application::getOrderBookDB
virtual OrderBookDB & getOrderBookDB()=0
ripple::NetworkOPsImp::SubAccountHistoryIndex::haveHistorical_
bool haveHistorical_
Definition: NetworkOPs.cpp:672
ripple::RCLCxPeerPos
A peer's signed, proposed position for use in RCLConsensus.
Definition: RCLCxPeerPos.h:43
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
ripple::NetworkOPsImp::processTrustedProposal
bool processTrustedProposal(RCLCxPeerPos proposal) override
Definition: NetworkOPs.cpp:1858
std::lock
T lock(T... args)
ripple::NetworkOPsImp::setAccountHistoryJobTimer
void setAccountHistoryJobTimer(SubAccountHistoryInfoWeak subInfo)
Definition: NetworkOPs.cpp:991
ripple::NetworkOPsImp::pubAccountTransaction
void pubAccountTransaction(std::shared_ptr< ReadView const > const &ledger, AcceptedLedgerTx const &transaction)
Definition: NetworkOPs.cpp:3135
ripple::sfBaseFeeDrops
const SF_AMOUNT sfBaseFeeDrops
ripple::InboundLedgers::getInfo
virtual Json::Value getInfo()=0
ripple::NetworkOPsImp::stateAccounting
void stateAccounting(Json::Value &obj) override
Definition: NetworkOPs.cpp:4057
ripple::LoadManager
Manages load sources.
Definition: LoadManager.h:45
ripple::sfReserveBase
const SF_UINT32 sfReserveBase
ripple::Application::cluster
virtual Cluster & cluster()=0
ripple::NetworkOPsImp::m_journal
beast::Journal m_journal
Definition: NetworkOPs.cpp:712
ripple::LedgerMaster::getPublishedLedger
std::shared_ptr< ReadView const > getPublishedLedger()
Definition: LedgerMaster.cpp:1692
ripple::featureXRPFees
const uint256 featureXRPFees
ripple::NetworkOPsImp::sLastEntry
@ sLastEntry
Definition: NetworkOPs.cpp:754
ripple::Application::getAcceptedLedgerCache
virtual TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache()=0
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
ripple::NetworkOPsImp::TransactionStatus::applied
bool applied
Definition: NetworkOPs.cpp:92
ripple::NetworkOPsImp::mLastFeeSummary
ServerFeeSummary mLastFeeSummary
Definition: NetworkOPs.cpp:759
ripple::ValidatorList::localPublicKey
PublicKey localPublicKey() const
Returns local validator public key.
Definition: ValidatorList.cpp:1412
ripple::NetworkOPsImp::StateAccounting::processStart_
const std::chrono::steady_clock::time_point processStart_
Definition: NetworkOPs.cpp:146
std::string
STL class.
std::shared_ptr< Transaction >
ripple::NetworkOPsImp::heartbeatTimer_
boost::asio::steady_timer heartbeatTimer_
Definition: NetworkOPs.cpp:726
ripple::ManifestCache::getMasterKey
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition: app/misc/impl/Manifest.cpp:299
ripple::RCLConsensus::getJson
Json::Value getJson(bool full) const
Definition: RCLConsensus.cpp:890
ripple::NetworkOPsImp::minPeerCount_
const std::size_t minPeerCount_
Definition: NetworkOPs.cpp:767
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
ripple::rpcError
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
ripple::fhZERO_IF_FROZEN
@ fhZERO_IF_FROZEN
Definition: View.h:76
utility
ripple::Rate
Represents a transfer rate.
Definition: Rate.h:37
std::exception
STL class.
ripple::NetworkOPsImp::setStateTimer
void setStateTimer() override
Called to initially start our timers.
Definition: NetworkOPs.cpp:919
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:536
ripple::NetworkOPsImp::StateAccounting::json
void json(Json::Value &obj) const
Output state counters in JSON format.
Definition: NetworkOPs.cpp:4554
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::STAmount::clear
void clear()
Definition: STAmount.h:409
ripple::sfLedgerSequence
const SF_UINT32 sfLedgerSequence
ripple::AcceptedLedgerTx::getTxn
std::shared_ptr< STTx const > const & getTxn() const
Definition: AcceptedLedgerTx.h:52
ripple::NetworkOPsImp::m_stats
Stats m_stats
Definition: NetworkOPs.cpp:830
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:347
ripple::Book::out
Issue out
Definition: Book.h:37
ripple::make_FeeVote
std::unique_ptr< FeeVote > make_FeeVote(FeeVote::Setup const &setup, beast::Journal journal)
Create an instance of the FeeVote logic.
Definition: FeeVoteImpl.cpp:359
ripple::Resource::feeMediumBurdenRPC
const Charge feeMediumBurdenRPC
ripple::isTesSuccess
bool isTesSuccess(TER x)
Definition: TER.h:594
ripple::TrustChanges
Changes in trusted nodes after updating validator list.
Definition: ValidatorList.h:107
ripple::Resource::Gossip
Data format for exchanging consumption information across peers.
Definition: Gossip.h:29
ripple::NetworkOPsImp::setAmendmentWarned
void setAmendmentWarned() override
Definition: NetworkOPs.cpp:1609
ripple::NetworkOPsImp::pubManifest
void pubManifest(Manifest const &) override
Definition: NetworkOPs.cpp:1948
ripple::RelationalDatabase::AccountTxArgs
Definition: RelationalDatabase.h:96
ripple::Manifest
Definition: Manifest.h:80
ripple::NetworkOPsImp::collect_metrics
void collect_metrics()
Definition: NetworkOPs.cpp:4495
ripple::NetworkOPsImp::subPeerStatus
bool subPeerStatus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4072
std::unordered_set
STL class.
ripple::NetworkOPsImp::mDispatchState
DispatchState mDispatchState
Definition: NetworkOPs.cpp:772
ripple::NetworkOPsImp::DispatchState::none
@ none
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::NetworkOPs::FailHard::no
@ no
ripple::NetworkOPsImp::stop
void stop() override
Definition: NetworkOPs.cpp:564
std::pair
ripple::Overlay::getJqTransOverflow
virtual std::uint64_t getJqTransOverflow() const =0
ripple::NetworkOPsImp::mSubRTAccount
SubInfoMapType mSubRTAccount
Definition: NetworkOPs.cpp:737
ripple::NetworkOPsImp::amendmentWarned_
std::atomic< bool > amendmentWarned_
Definition: NetworkOPs.cpp:722
ripple::NetworkOPsImp::states_
static const std::array< char const *, 5 > states_
Definition: NetworkOPs.cpp:115
ripple::sfSequence
const SF_UINT32 sfSequence
ripple::LedgerMaster
Definition: LedgerMaster.h:70
ripple::Application::getAmendmentTable
virtual AmendmentTable & getAmendmentTable()=0
ripple::NetworkOPsImp::setMode
void setMode(OperatingMode om) override
Definition: NetworkOPs.cpp:2244
ripple::ClusterNode::name
std::string const & name() const
Definition: ClusterNode.h:45
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
Json::UInt
unsigned int UInt
Definition: json_forwards.h:27
Json::Compact
Decorator for streaming out compact json.
Definition: json_writer.h:316
ripple::getBookBase
uint256 getBookBase(Book const &book)
Definition: Indexes.cpp:82
ripple::NetworkOPsImp::StateAccounting::Counters::dur
std::chrono::microseconds dur
Definition: NetworkOPs.cpp:138
ripple::Manifest::signingKey
PublicKey signingKey
The ephemeral key associated with this manifest.
Definition: Manifest.h:89
ripple::NetworkOPsImp::pubProposedAccountTransaction
void pubProposedAccountTransaction(std::shared_ptr< ReadView const > const &ledger, std::shared_ptr< STTx const > const &transaction, TER result)
Definition: NetworkOPs.cpp:3258
std::vector
STL class.
ripple::NetworkOPsImp::isUNLBlocked
bool isUNLBlocked() override
Definition: NetworkOPs.cpp:1621
std::unordered_map::find
T find(T... args)
ripple::ReportingETL::getInfo
Json::Value getInfo()
Definition: ReportingETL.h:310
ripple::Manifest::serialized
std::string serialized
The manifest in serialized form.
Definition: Manifest.h:83
ripple::NetworkOPsImp::setNeedNetworkLedger
void setNeedNetworkLedger() override
Definition: NetworkOPs.cpp:876
ripple::NetworkOPsImp::tryRemoveRpcSub
bool tryRemoveRpcSub(std::string const &strUrl) override
Definition: NetworkOPs.cpp:4130
ripple::Manifest::masterKey
PublicKey masterKey
The master key associated with this manifest.
Definition: Manifest.h:86
ripple::accountHolds
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
Definition: View.cpp:223
ripple::PublicKey::empty
bool empty() const noexcept
Definition: PublicKey.h:117
ripple::STAmount::getText
std::string getText() const override
Definition: STAmount.cpp:550
ripple::NetworkOPsImp::recvValidation
bool recvValidation(std::shared_ptr< STValidation > const &val, std::string const &source) override
Definition: NetworkOPs.cpp:2273
ripple::jtNETOP_CLUSTER
@ jtNETOP_CLUSTER
Definition: Job.h:76
ripple::NetworkOPsImp::getHostId
std::string getHostId(bool forAdmin)
Definition: NetworkOPs.cpp:900
ripple::NetworkOPsImp::forwardProposedTransaction
void forwardProposedTransaction(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2711
ripple::NetworkOPsImp::sValidations
@ sValidations
Definition: NetworkOPs.cpp:749
std::chrono::microseconds
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:29
ripple::Config::NODE_SIZE
std::size_t NODE_SIZE
Definition: Config.h:199
ripple::crypto_prng
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
Definition: csprng.cpp:99
ripple::keylet::offer
Keylet offer(AccountID const &id, std::uint32_t seq) noexcept
An offer from an account.
Definition: Indexes.cpp:222
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::JobQueue::getJson
Json::Value getJson(int c=0)
Definition: JobQueue.cpp:196
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
ripple::NetworkOPsImp::Stats::disconnected_duration
beast::insight::Gauge disconnected_duration
Definition: NetworkOPs.cpp:816
ripple::NetworkOPsImp::StateAccounting::Counters
Definition: NetworkOPs.cpp:133
std::optional::emplace
T emplace(T... args)
ripple::makeRulesGivenLedger
Rules makeRulesGivenLedger(DigestAwareReadView const &ledger, std::unordered_set< uint256, beast::uhash<>> const &presets)
Definition: ReadView.cpp:69
ripple::HELD
@ HELD
Definition: Transaction.h:51
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
std::recursive_mutex
STL class.
std::shared_ptr::get
T get(T... args)
ripple::NetworkOPsImp::consensusViewChange
void consensusViewChange() override
Definition: NetworkOPs.cpp:1939
std::lock_guard
STL class.
ripple::RPC::computeBookChanges
Json::Value computeBookChanges(std::shared_ptr< L const > const &lpAccepted)
Definition: BookChanges.h:38
ripple::NetworkOPsImp::accounting_
StateAccounting accounting_
Definition: NetworkOPs.cpp:775
ripple::ConsensusParms::ledgerGRANULARITY
std::chrono::milliseconds ledgerGRANULARITY
How often we check state or change positions.
Definition: ConsensusParms.h:95
ripple::NetworkOPsImp::unsubAccountHistoryInternal
void unsubAccountHistoryInternal(std::uint64_t seq, AccountID const &account, bool historyOnly) override
Definition: NetworkOPs.cpp:3830
ripple::Application::getShardStore
virtual NodeStore::DatabaseShard * getShardStore()=0
ripple::NetworkOPsImp::DispatchState::scheduled
@ scheduled
ripple::sfCloseTime
const SF_UINT32 sfCloseTime
tuple
ripple::NetworkOPsImp::SubAccountHistoryInfo::index_
std::shared_ptr< SubAccountHistoryIndex > index_
Definition: NetworkOPs.cpp:689
ripple::Overlay::size
virtual std::size_t size() const =0
Returns the number of active peers.
ripple::NetworkOPsImp::apply
void apply(std::unique_lock< std::mutex > &batchLock)
Attempt to apply transactions and post-process based on the results.
Definition: NetworkOPs.cpp:1311
ripple::JobQueue::addJob
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition: JobQueue.h:166
ripple::jtCLIENT_CONSENSUS
@ jtCLIENT_CONSENSUS
Definition: Job.h:48
ripple::make_NetworkOPs
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)
Definition: NetworkOPs.cpp:4579
ripple::NetworkOPsImp::Stats::syncing_transitions
beast::insight::Gauge syncing_transitions
Definition: NetworkOPs.cpp:824
std::function
ripple::LoadFeeTrack::getLoadBase
std::uint32_t getLoadBase() const
Definition: LoadFeeTrack.h:89
ripple::NetworkOPsImp::unlBlocked_
std::atomic< bool > unlBlocked_
Definition: NetworkOPs.cpp:723
ripple::NetworkOPsImp::SubAccountHistoryIndex::SubAccountHistoryIndex
SubAccountHistoryIndex(AccountID const &accountId)
Definition: NetworkOPs.cpp:675
ripple::getQualityNext
uint256 getQualityNext(uint256 const &uBase)
Definition: Indexes.cpp:100
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::NetworkOPsImp::forwardProposedAccountTransaction
void forwardProposedAccountTransaction(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2800
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::NetworkOPsImp::pubLedger
void pubLedger(std::shared_ptr< ReadView const > const &lpAccepted) override
Definition: NetworkOPs.cpp:2868
ripple::RelationalDatabase::AccountTxArgs::account
AccountID account
Definition: RelationalDatabase.h:98
ripple::NetworkOPsImp::switchLastClosedLedger
void switchLastClosedLedger(std::shared_ptr< Ledger const > const &newLCL)
Definition: NetworkOPs.cpp:1745
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:30
ripple::NetworkOPsImp::setUNLBlocked
void setUNLBlocked() override
Definition: NetworkOPs.cpp:1627
ripple::NetworkOPsImp::SubAccountHistoryInfo
Definition: NetworkOPs.cpp:686
ripple::NetworkOPsImp::doTransactionAsync
void doTransactionAsync(std::shared_ptr< Transaction > transaction, bool bUnlimited, FailHard failtype)
For transactions not submitted by a locally connected client, fire and forget.
Definition: NetworkOPs.cpp:1232
ripple::TxQ::Metrics
Structure returned by TxQ::getMetrics, expressed in reference fee level units.
Definition: TxQ.h:161
ripple::RCLValidatedLedger
Wraps a ledger instance for use in generic Validations LedgerTrie.
Definition: RCLValidations.h:153
ripple::parityRate
const Rate parityRate(QUALITY_ONE)
A transfer rate signifying a 1:1 exchange.
Definition: Rate.h:101
std::shared_ptr::reset
T reset(T... args)
ripple::NetworkOPsImp::TransactionStatus::result
TER result
Definition: NetworkOPs.cpp:93
ripple::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition: SecretKey.cpp:351
ripple::error_code_i
error_code_i
Definition: ErrorCodes.h:40
ripple::ValidatorKeys
Validator keys and manifest as set in configuration file.
Definition: ValidatorKeys.h:36
std::unordered_map::clear
T clear(T... args)
ripple::CanonicalTXSet
Holds transactions which were deferred to the next pass of consensus.
Definition: CanonicalTXSet.h:38
ripple::Application::getInboundLedgers
virtual InboundLedgers & getInboundLedgers()=0
ripple::Application::getFeeTrack
virtual LoadFeeTrack & getFeeTrack()=0
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:518
ripple::LedgerMaster::getCompleteLedgers
std::string getCompleteLedgers()
Definition: LedgerMaster.cpp:1699
ripple::ltDIR_NODE
@ ltDIR_NODE
A ledger object which contains a list of object identifiers.
Definition: LedgerFormats.h:66
ripple::send_always
Sends a message to all peers.
Definition: predicates.h:31
ripple::OperatingMode::SYNCING
@ SYNCING
fallen slightly behind
ripple::NetworkOPsImp::processClusterTimer
void processClusterTimer()
Definition: NetworkOPs.cpp:1062
ripple::NetworkOPsImp::unsubTransactions
bool unsubTransactions(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4022
std::unique_lock::unlock
T unlock(T... args)
ripple::Serializer::data
void const * data() const noexcept
Definition: Serializer.h:75
ripple::terQUEUED
@ terQUEUED
Definition: TER.h:203
ripple::sfIndexes
const SF_VECTOR256 sfIndexes
ripple::NetworkOPsImp::StateAccounting::mutex_
std::mutex mutex_
Definition: NetworkOPs.cpp:143
ripple::RCLConsensus::simulate
void simulate(NetClock::time_point const &now, std::optional< std::chrono::milliseconds > consensusDelay)
Definition: RCLConsensus.cpp:936
std::vector::push_back
T push_back(T... args)
ripple::NetworkOPsImp::ServerFeeSummary::loadFactorServer
std::uint32_t loadFactorServer
Definition: NetworkOPs.cpp:208
ripple::divide
STAmount divide(STAmount const &amount, Rate const &rate)
Definition: Rate2.cpp:86
ripple::NetworkOPsImp::~NetworkOPsImp
~NetworkOPsImp() override
Definition: NetworkOPs.cpp:253
ripple::isTerRetry
bool isTerRetry(TER x)
Definition: TER.h:588
ripple::LoadFeeTrack::getRemoteFee
std::uint32_t getRemoteFee() const
Definition: LoadFeeTrack.h:68
ripple::jtBATCH
@ jtBATCH
Definition: Job.h:66
ripple::sfValidatedHash
const SF_UINT256 sfValidatedHash
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:81
ripple::sfTakerPays
const SF_AMOUNT sfTakerPays
ripple::INCLUDED
@ INCLUDED
Definition: Transaction.h:48
ripple::getAccounts
static void getAccounts(Json::Value const &jvObj, std::vector< AccountID > &accounts)
Definition: NetworkOPs.cpp:2782
ripple::RCLConsensus
Manages the generic consensus algorithm for use by the RCL.
Definition: RCLConsensus.h:50
ripple::warnRPC_AMENDMENT_BLOCKED
@ warnRPC_AMENDMENT_BLOCKED
Definition: ErrorCodes.h:155
ripple::NetworkOPsImp::SubAccountHistoryIndex
Definition: NetworkOPs.cpp:662
ripple::NetworkOPsImp::m_statsMutex
std::mutex m_statsMutex
Definition: NetworkOPs.cpp:829
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::isGlobalFrozen
bool isGlobalFrozen(ReadView const &view, AccountID const &issuer)
Definition: View.cpp:188
ripple::NetworkOPsImp::Stats::syncing_duration
beast::insight::Gauge syncing_duration
Definition: NetworkOPs.cpp:818
ripple::NetworkOPsImp::isAmendmentBlocked
bool isAmendmentBlocked() override
Definition: NetworkOPs.cpp:1590
ripple::NetworkOPsImp::addRpcSub
InfoSub::pointer addRpcSub(std::string const &strUrl, InfoSub::ref) override
Definition: NetworkOPs.cpp:4120
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
ripple::NetworkOPsImp::forwardValidation
void forwardValidation(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2742
ripple::NetworkOPsImp::TransactionStatus::failType
const FailHard failType
Definition: NetworkOPs.cpp:91
ripple::ltOFFER
@ ltOFFER
A ledger object which describes an offer on the DEX.
Definition: LedgerFormats.h:92
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::Config::reporting
bool reporting() const
Definition: Config.h:318
ripple::Application::getReportingETL
virtual ReportingETL & getReportingETL()=0
ripple::OperatingMode::DISCONNECTED
@ DISCONNECTED
not ready to process requests
ripple::NetworkOPsImp::TransactionStatus::local
const bool local
Definition: NetworkOPs.cpp:90
ripple::NetworkOPsImp::clearAmendmentWarned
void clearAmendmentWarned() override
Definition: NetworkOPs.cpp:1615
ripple::STAmount::setJson
void setJson(Json::Value &) const
Definition: STAmount.cpp:496
ripple::UptimeClock::now
static time_point now()
Definition: UptimeClock.cpp:63
ripple::NetworkOPsImp::subAccountHistoryStart
void subAccountHistoryStart(std::shared_ptr< ReadView const > const &ledger, SubAccountHistoryInfoWeak &subInfo)
Definition: NetworkOPs.cpp:3729
ripple::jtTXN_PROC
@ jtTXN_PROC
Definition: Job.h:83
ripple::OrderBookDB::processTxn
void processTxn(std::shared_ptr< ReadView const > const &ledger, const AcceptedLedgerTx &alTx, Json::Value const &jvObj)
Definition: OrderBookDB.cpp:234
ripple::Application::getIOLatency
virtual std::chrono::milliseconds getIOLatency()=0
ripple::NetworkOPsImp::SubAccountHistoryInfo::sink_
InfoSub::pointer sink_
Definition: NetworkOPs.cpp:688
ripple::NetworkOPsImp::getOwnerInfo
Json::Value getOwnerInfo(std::shared_ptr< ReadView const > lpLedger, AccountID const &account) override
Definition: NetworkOPs.cpp:1518
ripple::sfServerVersion
const SF_UINT64 sfServerVersion
ripple::checkValidity
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules, Config const &config)
Checks transaction signature and local checks.
Definition: apply.cpp:37
ripple::NetworkOPsImp::reportFeeChange
void reportFeeChange() override
Definition: NetworkOPs.cpp:2980
ripple::LoadFeeTrack::getLocalFee
std::uint32_t getLocalFee() const
Definition: LoadFeeTrack.h:75
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:531
ripple::OperatingMode::CONNECTED
@ CONNECTED
convinced we are talking to the network
ripple::OBSOLETE
@ OBSOLETE
Definition: Transaction.h:53
ripple::NetworkOPsImp::StateAccounting::Counters::transitions
std::uint64_t transitions
Definition: NetworkOPs.cpp:137
ripple::InfoSub::pointer
std::shared_ptr< InfoSub > pointer
Definition: InfoSub.h:54
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::XRPAmount::decimalXRP
constexpr double decimalXRP() const
Definition: XRPAmount.h:253
ripple::sfLoadFee
const SF_UINT32 sfLoadFee
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::NetworkOPsImp::addAccountHistoryJob
void addAccountHistoryJob(SubAccountHistoryInfoWeak subInfo)
Definition: NetworkOPs.cpp:3409
ripple::NetworkOPsImp::isBlocked
bool isBlocked() override
Definition: NetworkOPs.cpp:1584
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
ripple::OperatingMode::TRACKING
@ TRACKING
convinced we agree with the network
ripple::NetworkOPsImp::SubAccountHistoryIndex::separationLedgerSeq_
std::uint32_t separationLedgerSeq_
Definition: NetworkOPs.cpp:668
ripple::STObject::getAccountID
AccountID getAccountID(SField const &field) const
Definition: STObject.cpp:589
ripple::sfNewFields
const SField sfNewFields
ripple::NetworkOPsImp::SubAccountHistoryInfoWeak::sinkWptr_
InfoSub::wptr sinkWptr_
Definition: NetworkOPs.cpp:693
ripple::sfReserveIncrement
const SF_UINT32 sfReserveIncrement
ripple::NetworkOPsImp::setTimer
void setTimer(boost::asio::steady_timer &timer, std::chrono::milliseconds const &expiry_time, std::function< void()> onExpire, std::function< void()> onError)
Definition: NetworkOPs.cpp:929
ripple::JsonOptions::none
@ none
ripple::NetworkOPsImp::DispatchState
DispatchState
Synchronization states for transaction batches.
Definition: NetworkOPs.cpp:109
ripple::NetworkOPsImp::sServer
@ sServer
Definition: NetworkOPs.cpp:746
ripple::Application::config
virtual Config & config()=0
ripple::peer_in_cluster
Select all peers (except optional excluded) that are in our cluster.
Definition: predicates.h:136
ripple::NetworkOPsImp::StateAccounting::start_
std::chrono::steady_clock::time_point start_
Definition: NetworkOPs.cpp:144
ripple::TERSubset< CanCvtToTER >
ripple::TrustChanges::removed
hash_set< NodeID > removed
Definition: ValidatorList.h:112
ripple::RCLTxSet
Represents a set of transactions in RCLConsensus.
Definition: RCLCxTx.h:65
ripple::keylet::page
Keylet page(uint256 const &key, std::uint64_t index) noexcept
A page in a directory.
Definition: Indexes.cpp:309
ripple::NetworkOPsImp::endConsensus
void endConsensus() override
Definition: NetworkOPs.cpp:1883
ripple::RelationalDatabase::AccountTxArgs::marker
std::optional< AccountTxMarker > marker
Definition: RelationalDatabase.h:103
std::unique_lock
STL class.
ripple::sfCookie
const SF_UINT64 sfCookie
ripple::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition: AccountID.cpp:158
ripple::NetworkOPsImp::unsubAccount
void unsubAccount(InfoSub::ref ispListener, hash_set< AccountID > const &vnaAccountIDs, bool rt) override
Definition: NetworkOPs.cpp:3365
ripple::Application::getRelationalDatabase
virtual RelationalDatabase & getRelationalDatabase()=0
ripple::Application::nodeIdentity
virtual std::pair< PublicKey, SecretKey > const & nodeIdentity()=0
ripple::NetworkOPsImp::unsubRTTransactions
bool unsubRTTransactions(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4040
ripple::Application::getTxQ
virtual TxQ & getTxQ()=0
ripple::LoadFeeTrack
Manages the current fee schedule.
Definition: LoadFeeTrack.h:44
ripple::Manifest::getSignature
std::optional< Blob > getSignature() const
Returns manifest signature.
Definition: app/misc/impl/Manifest.cpp:222
ripple::NetworkOPsImp::pubValidatedTransaction
void pubValidatedTransaction(std::shared_ptr< ReadView const > const &ledger, AcceptedLedgerTx const &transaction)
Definition: NetworkOPs.cpp:3080
std::to_string
T to_string(T... args)
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::NetworkOPsImp::subManifests
bool subManifests(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:3956
ripple::AcceptedLedgerTx
A transaction that is in a closed ledger.
Definition: AcceptedLedgerTx.h:43
ripple::AmendmentTable::firstUnsupportedExpected
virtual std::optional< NetClock::time_point > firstUnsupportedExpected() const =0
ripple::Resource::Gossip::items
std::vector< Item > items
Definition: Gossip.h:42
ripple::NetworkOPsImp::TransactionStatus::transaction
const std::shared_ptr< Transaction > transaction
Definition: NetworkOPs.cpp:88
std::array
STL class.
ripple::NetworkOPsImp::clearUNLBlocked
void clearUNLBlocked() override
Definition: NetworkOPs.cpp:1634
ripple::NetworkOPsImp::ServerFeeSummary
Server fees published on server subscription.
Definition: NetworkOPs.cpp:191
ripple::NetworkOPsImp::m_localTX
std::unique_ptr< LocalTxs > m_localTX
Definition: NetworkOPs.cpp:714
ripple::NetworkOPsImp::NetworkOPsImp
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)
Definition: NetworkOPs.cpp:215
ripple::NetworkOPsImp::DispatchState::running
@ running
ripple::NetworkOPsImp::StateAccounting::CounterData::start
decltype(start_) start
Definition: NetworkOPs.cpp:178
ripple::ConsensusPhase
ConsensusPhase
Phases of consensus for a single ledger round.
Definition: ConsensusTypes.h:103
ripple::STAmount
Definition: STAmount.h:45
ripple::NetworkOPsImp::StateAccounting::Counters::Counters
Counters()=default
ripple::warnRPC_EXPIRED_VALIDATOR_LIST
@ warnRPC_EXPIRED_VALIDATOR_LIST
Definition: ErrorCodes.h:156
beast::Journal::error
Stream error() const
Definition: Journal.h:333
beast::Journal::info
Stream info() const
Definition: Journal.h:321
ripple::NetworkOPsImp::m_job_queue
JobQueue & m_job_queue
Definition: NetworkOPs.cpp:761
std::unordered_map::erase
T erase(T... args)
ripple::BuildInfo::getVersionString
std::string const & getVersionString()
Server version.
Definition: BuildInfo.cpp:65
ripple::sfTakerGets
const SF_AMOUNT sfTakerGets
ripple::NetworkOPsImp::subBookChanges
bool subBookChanges(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:3930
ripple::STTx
Definition: STTx.h:45
ripple::LedgerMaster::getLedgerBySeq
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
Definition: LedgerMaster.cpp:1816
ripple::AcceptedLedgerTx::getAffected
boost::container::flat_set< AccountID > const & getAffected() const
Definition: AcceptedLedgerTx.h:63
ripple::NetworkOPsImp::StateAccounting::CounterData::counters
decltype(counters_) counters
Definition: NetworkOPs.cpp:176
ripple::NetworkOPsImp::Stats::tracking_duration
beast::insight::Gauge tracking_duration
Definition: NetworkOPs.cpp:819
ripple::warnRPC_UNSUPPORTED_MAJORITY
@ warnRPC_UNSUPPORTED_MAJORITY
Definition: ErrorCodes.h:154
ripple::NetworkOPsImp::subTransactions
bool subTransactions(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4012
ripple::TimeKeeper::closeTime
virtual time_point closeTime() const =0
Returns the close time, in network time.
ripple::ValStatus::current
@ current
This was a new validation and was added.
ripple::ClosureCounter
The role of a ClosureCounter is to assist in shutdown by letting callers wait for the completion of c...
Definition: ClosureCounter.h:54
ripple::NetworkOPsImp::StateAccounting::counters_
std::array< Counters, 5 > counters_
Definition: NetworkOPs.cpp:142
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
ripple::NetworkOPsImp::unsubLedger
bool unsubLedger(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:3940
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::NetworkOPsImp::isAmendmentWarned
bool isAmendmentWarned() override
Definition: NetworkOPs.cpp:1603
std::uint64_t
ripple::NetworkOPsImp::needNetworkLedger_
std::atomic< bool > needNetworkLedger_
Definition: NetworkOPs.cpp:720
ripple::temBAD_SIGNATURE
@ temBAD_SIGNATURE
Definition: TER.h:100
ripple::ReadView::succ
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.
ripple::Manifest::getMasterSignature
Blob getMasterSignature() const
Returns manifest master key signature.
Definition: app/misc/impl/Manifest.cpp:233
std::atomic< bool >
ripple::NetworkOPsImp::ServerFeeSummary::ServerFeeSummary
ServerFeeSummary()=default
ripple::NetworkOPsImp::StateAccounting::mode_
OperatingMode mode_
Definition: NetworkOPs.cpp:141
std::map
STL class.
ripple::LoadFeeTrack::getClusterFee
std::uint32_t getClusterFee() const
Definition: LoadFeeTrack.h:82
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:53
ripple::Application::getValidationPublicKey
virtual PublicKey const & getValidationPublicKey() const =0
ripple::NetworkOPsImp::pubValidation
void pubValidation(std::shared_ptr< STValidation > const &val) override
Definition: NetworkOPs.cpp:2122
ripple::amountFromQuality
STAmount amountFromQuality(std::uint64_t rate)
Definition: STAmount.cpp:831
ripple::OrderBookDB::makeBookListeners
BookListeners::pointer makeBookListeners(Book const &)
Definition: OrderBookDB.cpp:202
ripple::NetworkOPs::FailHard
FailHard
Definition: NetworkOPs.h:91
ripple::sfReserveIncrementDrops
const SF_AMOUNT sfReserveIncrementDrops
ripple::NetworkOPsImp::subAccount
void subAccount(InfoSub::ref ispListener, hash_set< AccountID > const &vnaAccountIDs, bool rt) override
Definition: NetworkOPs.cpp:3328
ripple::NetworkOPsImp::m_standalone
const bool m_standalone
Definition: NetworkOPs.cpp:764
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::LedgerMaster::getCurrentLedger
std::shared_ptr< ReadView const > getCurrentLedger()
Definition: LedgerMaster.cpp:1652
Json::Int
int Int
Definition: json_forwards.h:26
ripple::NetworkOPsImp::Stats
Definition: NetworkOPs.cpp:778
ripple::AcceptedLedgerTx::getResult
TER getResult() const
Definition: AcceptedLedgerTx.h:79
ripple::RCLConsensus::parms
ConsensusParms const & parms() const
Definition: RCLConsensus.h:518
ripple::Cluster::size
std::size_t size() const
The number of nodes in the cluster list.
Definition: Cluster.cpp:50
ripple::NetworkOPsImp::StateAccounting::CounterData::initialSyncUs
decltype(initialSyncUs_) initialSyncUs
Definition: NetworkOPs.cpp:179
ripple::STTx::getJson
Json::Value getJson(JsonOptions options) const override
Definition: STTx.cpp:229
beast::abstract_clock< std::chrono::steady_clock >
ripple::sfReserveBaseDrops
const SF_AMOUNT sfReserveBaseDrops
ripple::NetworkOPsImp::StateAccounting::CounterData::mode
decltype(mode_) mode
Definition: NetworkOPs.cpp:177
ripple::Config::FEE_UNITS_DEPRECATED
static constexpr std::uint32_t FEE_UNITS_DEPRECATED
Definition: Config.h:144
ripple::NetworkOPsImp::StateAccounting::CounterData
Definition: NetworkOPs.cpp:174
ripple::accountFunds
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
Definition: View.cpp:267
ripple::ttOFFER_CREATE
@ ttOFFER_CREATE
This transaction type creates an offer to trade one asset for another.
Definition: TxFormats.h:80
Json::Value::UInt
Json::UInt UInt
Definition: json_value.h:153
ripple::NetworkOPsImp::SubAccountHistoryIndex::historyTxIndex_
std::int32_t historyTxIndex_
Definition: NetworkOPs.cpp:671
ripple::NetworkOPsImp::TransactionStatus
Transaction with input flags and results to be applied in batches.
Definition: NetworkOPs.cpp:85
ripple::jtCLIENT_ACCT_HIST
@ jtCLIENT_ACCT_HIST
Definition: Job.h:49
ripple::Application::validators
virtual ValidatorList & validators()=0
beast::insight::Gauge
A metric for measuring an integral value.
Definition: Gauge.h:39
ripple::NetworkOPsImp::transactionBatch
void transactionBatch()
Apply transactions in batches.
Definition: NetworkOPs.cpp:1297
ripple::NetworkOPsImp::isNeedNetworkLedger
bool isNeedNetworkLedger() override
Definition: NetworkOPs.cpp:888
ripple::LoadManager::resetDeadlockDetector
void resetDeadlockDetector()
Reset the deadlock detection timer.
Definition: LoadManager.cpp:63
ripple::NetworkOPsImp::ServerFeeSummary::operator!=
bool operator!=(ServerFeeSummary const &b) const
Definition: NetworkOPs.cpp:1998
ripple::jtCLIENT_FEE_CHANGE
@ jtCLIENT_FEE_CHANGE
Definition: Job.h:47
ripple::NetworkOPsImp::TransactionStatus::TransactionStatus
TransactionStatus(std::shared_ptr< Transaction > t, bool a, bool l, FailHard f)
Definition: NetworkOPs.cpp:95
ripple::KeyType::secp256k1
@ secp256k1
ripple::NetworkOPsImp::setStandAlone
void setStandAlone() override
Definition: NetworkOPs.cpp:870
ripple::JobQueue
A pool of threads to perform work.
Definition: JobQueue.h:55
ripple::NetworkOPsImp::mSubLock
std::recursive_mutex mSubLock
Definition: NetworkOPs.cpp:716
std::vector::swap
T swap(T... args)
ripple::ValidatorList::expires
std::optional< TimeKeeper::time_point > expires() const
Return the time when the validator list will expire.
Definition: ValidatorList.cpp:1500
ripple::NetworkOPsImp::ServerFeeSummary::operator==
bool operator==(ServerFeeSummary const &b) const
Definition: NetworkOPs.cpp:203
std::weak_ptr< InfoSub >
ripple::rpcINTERNAL
@ rpcINTERNAL
Definition: ErrorCodes.h:130
ripple::multiply
STAmount multiply(STAmount const &amount, Rate const &rate)
Definition: Rate2.cpp:47
std::min
T min(T... args)
ripple::OrderBookDB::getBookListeners
BookListeners::pointer getBookListeners(Book const &)
Definition: OrderBookDB.cpp:219
ripple::NetworkOPsImp::SubAccountHistoryIndex::forwardTxIndex_
std::uint32_t forwardTxIndex_
Definition: NetworkOPs.cpp:666
ripple::Serializer
Definition: Serializer.h:39
ripple::Manifest::sequence
std::uint32_t sequence
The sequence number of this manifest.
Definition: Manifest.h:92
ripple::LedgerMaster::getFetchPackCacheSize
std::size_t getFetchPackCacheSize() const
Definition: LedgerMaster.cpp:2356
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:291
ripple::NetworkOPsImp::sConsensusPhase
@ sConsensusPhase
Definition: NetworkOPs.cpp:751
ripple::NetworkOPsImp::mMutex
std::mutex mMutex
Definition: NetworkOPs.cpp:771
ripple::sfBaseFee
const SF_UINT64 sfBaseFee
ripple::NetworkOPsImp::Stats::tracking_transitions
beast::insight::Gauge tracking_transitions
Definition: NetworkOPs.cpp:825
ripple::LedgerMaster::haveValidated
bool haveValidated()
Whether we have ever fully validated a ledger.
Definition: LedgerMaster.h:286
ripple::LedgerMaster::getValidatedLedgerAge
std::chrono::seconds getValidatedLedgerAge()
Definition: LedgerMaster.cpp:274
ripple::generateSeed
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition: Seed.cpp:69
ripple::LedgerMaster::getClosedLedger
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:98
ripple::NetworkOPsImp::Stats::connected_transitions
beast::insight::Gauge connected_transitions
Definition: NetworkOPs.cpp:823
ripple::NetworkOPsImp::clusterTimer_
boost::asio::steady_timer clusterTimer_
Definition: NetworkOPs.cpp:727
ripple::STObject
Definition: STObject.h:51
ripple::perf::PerfLog::countersJson
virtual Json::Value countersJson() const =0
Render performance counters in Json.
ripple::NetworkOPsImp::mTransactions
std::vector< TransactionStatus > mTransactions
Definition: NetworkOPs.cpp:773
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
ripple::NetworkOPsImp::reportConsensusStateChange
void reportConsensusStateChange(ConsensusPhase phase)
Definition: NetworkOPs.cpp:3000
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::transResultInfo
bool transResultInfo(TER code, std::string &token, std::string &text)
Definition: TER.cpp:192
ripple::NetworkOPsImp::unsubServer
bool unsubServer(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4004
ripple::RCLConsensus::prevRoundTime
std::chrono::milliseconds prevRoundTime() const
Get duration of the previous round.
Definition: RCLConsensus.h:456
ripple::sterilize
std::shared_ptr< STTx const > sterilize(STTx const &stx)
Sterilize a transaction.
Definition: STTx.cpp:550
ripple::NetworkOPsImp::Stats::Stats
Stats(Handler const &handler, beast::insight::Collector::ptr const &collector)
Definition: NetworkOPs.cpp:781
ripple::NetworkOPsImp::setHeartbeatTimer
void setHeartbeatTimer()
Definition: NetworkOPs.cpp:961
ripple::NetworkOPsImp::unsubBookChanges
bool unsubBookChanges(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:3948
ripple::Application::getNodeStore
virtual NodeStore::Database & getNodeStore()=0
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::Application::validatorManifests
virtual ManifestCache & validatorManifests()=0
ripple::NetworkOPsImp::getLocalTxCount
std::size_t getLocalTxCount() override
Definition: NetworkOPs.cpp:3014
ripple::NetworkOPsImp::StateAccounting::initialSyncUs_
std::uint64_t initialSyncUs_
Definition: NetworkOPs.cpp:147
ripple::NetworkOPsImp::mStreamMaps
std::array< SubMapType, SubTypes::sLastEntry+1 > mStreamMaps
Definition: NetworkOPs.cpp:757
ripple::Serializer::size
std::size_t size() const noexcept
Definition: Serializer.h:69
ripple::LoadFeeTrack::getLoadFactor
std::uint32_t getLoadFactor() const
Definition: LoadFeeTrack.h:95
ripple::NetworkOPsImp::getLedgerFetchInfo
Json::Value getLedgerFetchInfo() override
Definition: NetworkOPs.cpp:2674
ripple::tapUNLIMITED
@ tapUNLIMITED
Definition: ApplyView.h:41
ripple::NetworkOPsImp::sManifests
@ sManifests
Definition: NetworkOPs.cpp:745
ripple::sfLedgerEntryType
const SF_UINT16 sfLedgerEntryType
ripple::NetworkOPsImp::StateAccounting::StateAccounting
StateAccounting()
Definition: NetworkOPs.cpp:151
ripple::NetworkOPsImp::SubAccountHistoryInfoWeak
Definition: NetworkOPs.cpp:691
ripple::INVALID
@ INVALID
Definition: Transaction.h:47
ripple::NetworkOPsImp::pubServer
void pubServer()
Definition: NetworkOPs.cpp:2027
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:132
ripple::tefPAST_SEQ
@ tefPAST_SEQ
Definition: TER.h:154
ripple::NetworkOPsImp::unsubBook
bool unsubBook(std::uint64_t uListener, Book const &) override
Definition: NetworkOPs.cpp:3871
ripple::NetworkOPsImp::acceptLedger
std::uint32_t acceptLedger(std::optional< std::chrono::milliseconds > consensusDelay) override
Accepts the current transaction tree, return the new ledger's sequence.
Definition: NetworkOPs.cpp:3880
ripple::NetworkOPsImp::sTransactions
@ sTransactions
Definition: NetworkOPs.cpp:747
ripple::NetworkOPsImp::mSubAccount
SubInfoMapType mSubAccount
Definition: NetworkOPs.cpp:736
ripple::Config::SERVER_DOMAIN
std::string SERVER_DOMAIN
Definition: Config.h:265
ripple::AcceptedLedgerTx::getMeta
TxMeta const & getMeta() const
Definition: AcceptedLedgerTx.h:57
ripple::NetworkOPsImp::clearNeedNetworkLedger
void clearNeedNetworkLedger() override
Definition: NetworkOPs.cpp:882
ripple::NetworkOPsImp::sBookChanges
@ sBookChanges
Definition: NetworkOPs.cpp:752
beast::rngfill
void rngfill(void *buffer, std::size_t bytes, Generator &g)
Definition: rngfill.h:33
Json::StaticString
Lightweight wrapper to tag static string.
Definition: json_value.h:60
ripple::NetworkOPsImp::TransactionStatus::admin
const bool admin
Definition: NetworkOPs.cpp:89
std
STL namespace.
ripple::featureNegativeUNL
const uint256 featureNegativeUNL
ripple::ltACCOUNT_ROOT
@ ltACCOUNT_ROOT
A ledger object which describes an account.
Definition: LedgerFormats.h:59
ripple::NetworkOPsImp::checkLastClosedLedger
bool checkLastClosedLedger(const Overlay::PeerSequence &, uint256 &networkClosed)
Definition: NetworkOPs.cpp:1640
std::unordered_set::insert
T insert(T... args)
ripple::NetworkOPsImp::strOperatingMode
std::string strOperatingMode(OperatingMode const mode, bool const admin) const override
Definition: NetworkOPs.cpp:1110
ripple::NetworkOPsImp::getBookPage
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
Definition: NetworkOPs.cpp:4155
ripple::NetworkOPsImp::ServerFeeSummary::baseFee
XRPAmount baseFee
Definition: NetworkOPs.cpp:210
ripple::RPC::insertDeliveredAmount
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.
Definition: DeliveredAmount.cpp:143
ripple::NetworkOPsImp::pubPeerStatus
void pubPeerStatus(std::function< Json::Value(void)> const &) override
Definition: NetworkOPs.cpp:2215
ripple::NetworkOPsImp::mCond
std::condition_variable mCond
Definition: NetworkOPs.cpp:770
ripple::NetworkOPsImp::isFull
bool isFull() override
Definition: NetworkOPs.cpp:894
ripple::PostgresDatabase
Definition: PostgresDatabase.h:27
ripple::NodeStore::Database::getCountsJson
void getCountsJson(Json::Value &obj)
Definition: Database.cpp:378
ripple::NetworkOPsImp::subLedger
bool subLedger(InfoSub::ref ispListener, Json::Value &jvResult) override
Definition: NetworkOPs.cpp:3900
std::condition_variable
ripple::NetworkOPsImp::Stats::full_transitions
beast::insight::Gauge full_transitions
Definition: NetworkOPs.cpp:826
ripple::Config::RELAY_UNTRUSTED_VALIDATIONS
int RELAY_UNTRUSTED_VALIDATIONS
Definition: Config.h:153
ripple::stateNames
static const std::array< char const *, 5 > stateNames
Definition: NetworkOPs.cpp:839
ripple::NetworkOPsImp::sLedger
@ sLedger
Definition: NetworkOPs.cpp:744
ripple::TimeKeeper::now
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
ripple::NetworkOPsImp::subAccountHistory
error_code_i subAccountHistory(InfoSub::ref ispListener, AccountID const &account) override
subscribe an account's new transactions and retrieve the account's historical transactions
Definition: NetworkOPs.cpp:3773
ripple::NetworkOPsImp::mConsensus
RCLConsensus mConsensus
Definition: NetworkOPs.cpp:730
ripple::RCLConsensus::prevProposers
std::size_t prevProposers() const
Get the number of proposing peers that participated in the previous round.
Definition: RCLConsensus.h:443
ripple::Application::overlay
virtual Overlay & overlay()=0
ripple::NetworkOPsImp::sPeerStatus
@ sPeerStatus
Definition: NetworkOPs.cpp:750
std::chrono::milliseconds::count
T count(T... args)
ripple::NetworkOPsImp::mMode
std::atomic< OperatingMode > mMode
Definition: NetworkOPs.cpp:718
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1662
ripple::NetworkOPsImp::unsubManifests
bool unsubManifests(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:3966
ripple::tapFAIL_HARD
@ tapFAIL_HARD
Definition: ApplyView.h:34
ripple::TrustChanges::added
hash_set< NodeID > added
Definition: ValidatorList.h:111
ripple::NetworkOPsImp::amendmentBlocked_
std::atomic< bool > amendmentBlocked_
Definition: NetworkOPs.cpp:721
ripple::NetworkOPsImp::submitTransaction
void submitTransaction(std::shared_ptr< STTx const > const &) override
Definition: NetworkOPs.cpp:1130
std::string::empty
T empty(T... args)
ripple::OperatingMode
OperatingMode
Specifies the mode under which the server believes it's operating.
Definition: NetworkOPs.h:66
ripple::fhIGNORE_FREEZE
@ fhIGNORE_FREEZE
Definition: View.h:76
ripple::Overlay::networkID
virtual std::optional< std::uint32_t > networkID() const =0
Returns the ID of the network this server is configured for, if any.
ripple::InboundLedgers::clearFailures
virtual void clearFailures()=0
ripple::TokenType::NodePublic
@ NodePublic
ripple::NetworkOPsImp::transJson
Json::Value transJson(const STTx &transaction, TER result, bool validated, std::shared_ptr< ReadView const > const &ledger)
Definition: NetworkOPs.cpp:3022
ripple::ClosureCounter::join
void join(char const *name, std::chrono::milliseconds wait, beast::Journal j)
Returns once all counted in-flight closures are destroyed.
Definition: ClosureCounter.h:166
ripple::NetworkOPsImp::mLastConsensusPhase
ConsensusPhase mLastConsensusPhase
Definition: NetworkOPs.cpp:732
ripple::NetworkOPsImp::updateLocalTx
void updateLocalTx(ReadView const &view) override
Definition: NetworkOPs.cpp:3009
std::optional
mutex
ripple::NetworkOPsImp::sRTTransactions
@ sRTTransactions
Definition: NetworkOPs.cpp:748
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::NetworkOPsImp::pubConsensus
void pubConsensus(ConsensusPhase phase)
Definition: NetworkOPs.cpp:2095
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::NetworkOPsImp::subRTTransactions
bool subRTTransactions(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4030
ripple::Book
Specifies an order book.
Definition: Book.h:33
ripple::ClusterNode::getReportTime
NetClock::time_point getReportTime() const
Definition: ClusterNode.h:57
ripple::NetworkOPsImp::Stats::disconnected_transitions
beast::insight::Gauge disconnected_transitions
Definition: NetworkOPs.cpp:822
ripple::genesisAccountId
static const auto genesisAccountId
Definition: NetworkOPs.cpp:852
std::make_pair
T make_pair(T... args)
ripple::sfAccount
const SF_ACCOUNT sfAccount
ripple::NetworkOPsImp::pubProposedTransaction
void pubProposedTransaction(std::shared_ptr< ReadView const > const &ledger, std::shared_ptr< STTx const > const &transaction, TER result) override
Definition: NetworkOPs.cpp:2680
ripple::ltRIPPLE_STATE
@ ltRIPPLE_STATE
A ledger object which describes a bidirectional trust line.
Definition: LedgerFormats.h:74
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
std::unordered_map::end
T end(T... args)
ripple::mulDiv
std::pair< bool, Dest > mulDiv(Source1 value, Dest mul, Source2 div)
Definition: FeeUnits.h:468
ripple::NetworkOPsImp::getServerInfo
Json::Value getServerInfo(bool human, bool admin, bool counters) override
Definition: NetworkOPs.cpp:2296
ripple::perf::PerfLog::currentJson
virtual Json::Value currentJson() const =0
Render currently executing jobs and RPC calls and durations in Json.
ripple::NetworkOPsImp::m_ledgerMaster
LedgerMaster & m_ledgerMaster
Definition: NetworkOPs.cpp:734
ripple::NetworkOPsImp::subServer
bool subServer(InfoSub::ref ispListener, Json::Value &jvResult, bool admin) override
Definition: NetworkOPs.cpp:3974
ripple::NetworkOPsImp::SubAccountHistoryInfoWeak::index_
std::shared_ptr< SubAccountHistoryIndex > index_
Definition: NetworkOPs.cpp:694
ripple::RelationalDatabase::AccountTxArgs::ledger
std::optional< LedgerSpecifier > ledger
Definition: RelationalDatabase.h:99
ripple::LedgerRange
Definition: RelationalDatabase.h:42
std::numeric_limits::max
T max(T... args)
ripple::NetworkOPsImp::accountHistoryTxTimer_
boost::asio::steady_timer accountHistoryTxTimer_
Definition: NetworkOPs.cpp:728
ripple::make_LocalTxs
std::unique_ptr< LocalTxs > make_LocalTxs()
Definition: LocalTxs.cpp:197
ripple::TxQ::getMetrics
Metrics getMetrics(OpenView const &view) const
Returns fee metrics in reference fee level units.
Definition: TxQ.cpp:1747
ripple::NetworkOPsImp::doTransactionSync
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...
Definition: NetworkOPs.cpp:1257
ripple::NetworkOPsImp::StateAccounting::getCounterData
CounterData getCounterData() const
Definition: NetworkOPs.cpp:183
ripple::NetworkOPsImp::Stats::full_duration
beast::insight::Gauge full_duration
Definition: NetworkOPs.cpp:820
ripple::Application::getPerfLog
virtual perf::PerfLog & getPerfLog()=0
ripple::send_if
send_if_pred< Predicate > send_if(std::shared_ptr< Message > const &m, Predicate const &f)
Helper function to aid in type deduction.
Definition: predicates.h:75
ripple::Overlay::getPeerDisconnect
virtual std::uint64_t getPeerDisconnect() const =0
ripple::NetworkOPsImp::subBook
bool subBook(InfoSub::ref ispListener, Book const &) override
Definition: NetworkOPs.cpp:3861
ripple::NetworkOPsImp::subConsensus
bool subConsensus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4090
ripple::NetworkOPsImp::getConsensusInfo
Json::Value getConsensusInfo() override
Definition: NetworkOPs.cpp:2290
ripple::NetworkOPsImp::Stats::connected_duration
beast::insight::Gauge connected_duration
Definition: NetworkOPs.cpp:817
ripple::ValidatorList::count
std::size_t count() const
Return the number of configured validator list sites.
Definition: ValidatorList.cpp:1459
ripple::NetworkOPsImp::waitHandlerCounter_
ClosureCounter< void, boost::system::error_code const & > waitHandlerCounter_
Definition: NetworkOPs.cpp:725
std::unique_ptr
STL class.
ripple::cdirFirst
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.
Definition: View.cpp:134
ripple::NetworkOPsImp::SubAccountHistoryIndex::stopHistorical_
std::atomic< bool > stopHistorical_
Definition: NetworkOPs.cpp:673
ripple::NetworkOPsImp
Definition: NetworkOPs.cpp:79
ripple::NetworkOPsImp::mSubAccountHistory
SubAccountHistoryMapType mSubAccountHistory
Definition: NetworkOPs.cpp:741
ripple::NetworkOPsImp::StateAccounting::mode
void mode(OperatingMode om)
Record state transition.
Definition: NetworkOPs.cpp:4533
ripple::RPC::accountFromStringStrict
std::optional< AccountID > accountFromStringStrict(std::string const &account)
Get an AccountID from an account ID or public key.
Definition: RPCHelpers.cpp:41
unordered_map
ripple::NetworkOPsImp::StateAccounting::states_
static const std::array< Json::StaticString const, 5 > states_
Definition: NetworkOPs.cpp:148
ripple::RFC1751::getWordFromBlob
static std::string getWordFromBlob(void const *blob, size_t bytes)
Chooses a single dictionary word from the data.
Definition: RFC1751.cpp:494
ripple::NetworkOPsImp::unsubAccountInternal
void unsubAccountInternal(std::uint64_t seq, hash_set< AccountID > const &vnaAccountIDs, bool rt) override
Definition: NetworkOPs.cpp:3381
ripple::sfSigningTime
const SF_UINT32 sfSigningTime
ripple::NetworkOPsImp::unsubAccountHistory
void unsubAccountHistory(InfoSub::ref ispListener, AccountID const &account, bool historyOnly) override
unsubscribe an account's transactions
Definition: NetworkOPs.cpp:3819
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:219
ripple::NetworkOPsImp::StateAccounting
State accounting records two attributes for each possible server state: 1) Amount of time spent in ea...
Definition: NetworkOPs.cpp:131
beast::insight::Hook
A reference to a handler for performing polled collection.
Definition: Hook.h:31
ripple::getQuality
std::uint64_t getQuality(uint256 const &uBase)
Definition: Indexes.cpp:108
ripple::Overlay::getPeerDisconnectCharges
virtual std::uint64_t getPeerDisconnectCharges() const =0
ripple::STObject::getFieldAmount
STAmount const & getFieldAmount(SField const &field) const
Definition: STObject.cpp:603
ripple::NetworkOPsImp::unsubPeerStatus
bool unsubPeerStatus(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4082
ripple::NetworkOPsImp::app_
Application & app_
Definition: NetworkOPs.cpp:711
ripple::handleNewValidation
void handleNewValidation(Application &app, std::shared_ptr< STValidation > const &val, std::string const &source)
Handle a new validation.
Definition: RCLValidations.cpp:152
ripple::NetworkOPsImp::SubAccountHistoryIndex::accountId_
const AccountID accountId_
Definition: NetworkOPs.cpp:664
ripple::isTemMalformed
bool isTemMalformed(TER x)
Definition: TER.h:576
ripple::trunc32
static std::uint32_t trunc32(std::uint64_t v)
Definition: NetworkOPs.cpp:2019
ripple::XRPAmount::jsonClipped
Json::Value jsonClipped() const
Definition: XRPAmount.h:209
ripple::Book::in
Issue in
Definition: Book.h:36
ripple::RelationalDatabase::AccountTxPageOptions
Definition: RelationalDatabase.h:74
ripple::NetworkOPsImp::getOperatingMode
OperatingMode getOperatingMode() const override
Definition: NetworkOPs.cpp:858
ripple::Issue::account
AccountID account
Definition: Issue.h:38
ripple::ClusterNode::identity
PublicKey const & identity() const
Definition: ClusterNode.h:63
ripple::NetworkOPsImp::ServerFeeSummary::em
std::optional< TxQ::Metrics > em
Definition: NetworkOPs.cpp:211
ripple::NetworkOPsImp::mRpcSubMap
subRpcMapType mRpcSubMap
Definition: NetworkOPs.cpp:739
ripple::ValidatorList::quorum
std::size_t quorum() const
Get quorum value for current trusted key set.
Definition: ValidatorList.h:492
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::sfAmendments
const SF_VECTOR256 sfAmendments
ripple::TimeKeeper::closeOffset
virtual std::chrono::duration< std::int32_t > closeOffset() const =0
ripple::NetworkOPsImp::findRpcSub
InfoSub::pointer findRpcSub(std::string const &strUrl) override
Definition: NetworkOPs.cpp:4107
beast::insight::Gauge::set
void set(value_type value) const
Set the value on the gauge.
Definition: Gauge.h:68
ripple::NetworkOPsImp::ServerFeeSummary::loadBaseServer
std::uint32_t loadBaseServer
Definition: NetworkOPs.cpp:209
ripple::XRPAmount
Definition: XRPAmount.h:46
ripple::NetworkOPsImp::clearLedgerFetch
void clearLedgerFetch() override
Definition: NetworkOPs.cpp:2668
ripple::ClusterNode::getLoadFee
std::uint32_t getLoadFee() const
Definition: ClusterNode.h:51
ripple::ClosureCounter::wrap
std::optional< Substitute< Closure > > wrap(Closure &&closure)
Wrap the passed closure with a reference counter.
Definition: ClosureCounter.h:192
ripple::test::jtx::rate
Json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
Definition: rate.cpp:30
ripple::root
Number root(Number f, unsigned d)
Definition: Number.cpp:624
ripple::NetworkOPsImp::beginConsensus
bool beginConsensus(uint256 const &networkClosed) override
Definition: NetworkOPs.cpp:1799
ripple::NetworkOPsImp::setAmendmentBlocked
void setAmendmentBlocked() override
Definition: NetworkOPs.cpp:1596
ripple::NetworkOPsImp::processTransaction
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.
Definition: NetworkOPs.cpp:1183
beast
Definition: base_uint.h:677
string
ripple::OperatingMode::FULL
@ FULL
we have the ledger and can even validate
std::chrono::steady_clock::now
T now(T... args)