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] = baseFeeXRP->xrp().jsonClipped();
2188 
2189  if (auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops);
2190  reserveBaseXRP && reserveBaseXRP->native())
2191  jvObj[jss::reserve_base] = reserveBaseXRP->xrp().jsonClipped();
2192 
2193  if (auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops);
2194  reserveIncXRP && reserveIncXRP->native())
2195  jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped();
2196 
2197  for (auto i = mStreamMaps[sValidations].begin();
2198  i != mStreamMaps[sValidations].end();)
2199  {
2200  if (auto p = i->second.lock())
2201  {
2202  p->send(jvObj, true);
2203  ++i;
2204  }
2205  else
2206  {
2207  i = mStreamMaps[sValidations].erase(i);
2208  }
2209  }
2210  }
2211 }
2212 
2213 void
2215 {
2217 
2218  if (!mStreamMaps[sPeerStatus].empty())
2219  {
2220  Json::Value jvObj(func());
2221 
2222  jvObj[jss::type] = "peerStatusChange";
2223 
2224  for (auto i = mStreamMaps[sPeerStatus].begin();
2225  i != mStreamMaps[sPeerStatus].end();)
2226  {
2227  InfoSub::pointer p = i->second.lock();
2228 
2229  if (p)
2230  {
2231  p->send(jvObj, true);
2232  ++i;
2233  }
2234  else
2235  {
2236  i = mStreamMaps[sPeerStatus].erase(i);
2237  }
2238  }
2239  }
2240 }
2241 
2242 void
2244 {
2245  using namespace std::chrono_literals;
2246  if (om == OperatingMode::CONNECTED)
2247  {
2250  }
2251  else if (om == OperatingMode::SYNCING)
2252  {
2253  if (app_.getLedgerMaster().getValidatedLedgerAge() >= 1min)
2255  }
2256 
2257  if ((om > OperatingMode::CONNECTED) && isBlocked())
2259 
2260  if (mMode == om)
2261  return;
2262 
2263  mMode = om;
2264 
2265  accounting_.mode(om);
2266 
2267  JLOG(m_journal.info()) << "STATE->" << strOperatingMode();
2268  pubServer();
2269 }
2270 
2271 bool
2273  std::shared_ptr<STValidation> const& val,
2274  std::string const& source)
2275 {
2276  JLOG(m_journal.trace())
2277  << "recvValidation " << val->getLedgerHash() << " from " << source;
2278 
2279  handleNewValidation(app_, val, source);
2280 
2281  pubValidation(val);
2282 
2283  // We will always relay trusted validations; if configured, we will
2284  // also relay all untrusted validations.
2285  return app_.config().RELAY_UNTRUSTED_VALIDATIONS == 1 || val->isTrusted();
2286 }
2287 
2290 {
2291  return mConsensus.getJson(true);
2292 }
2293 
2295 NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters)
2296 {
2298 
2299  // System-level warnings
2300  {
2301  Json::Value warnings{Json::arrayValue};
2302  if (isAmendmentBlocked())
2303  {
2304  Json::Value& w = warnings.append(Json::objectValue);
2305  w[jss::id] = warnRPC_AMENDMENT_BLOCKED;
2306  w[jss::message] =
2307  "This server is amendment blocked, and must be updated to be "
2308  "able to stay in sync with the network.";
2309  }
2310  if (isUNLBlocked())
2311  {
2312  Json::Value& w = warnings.append(Json::objectValue);
2313  w[jss::id] = warnRPC_EXPIRED_VALIDATOR_LIST;
2314  w[jss::message] =
2315  "This server has an expired validator list. validators.txt "
2316  "may be incorrectly configured or some [validator_list_sites] "
2317  "may be unreachable.";
2318  }
2319  if (admin && isAmendmentWarned())
2320  {
2321  Json::Value& w = warnings.append(Json::objectValue);
2322  w[jss::id] = warnRPC_UNSUPPORTED_MAJORITY;
2323  w[jss::message] =
2324  "One or more unsupported amendments have reached majority. "
2325  "Upgrade to the latest version before they are activated "
2326  "to avoid being amendment blocked.";
2327  if (auto const expected =
2329  {
2330  auto& d = w[jss::details] = Json::objectValue;
2331  d[jss::expected_date] = expected->time_since_epoch().count();
2332  d[jss::expected_date_UTC] = to_string(*expected);
2333  }
2334  }
2335 
2336  if (warnings.size())
2337  info[jss::warnings] = std::move(warnings);
2338  }
2339 
2340  // hostid: unique string describing the machine
2341  if (human)
2342  info[jss::hostid] = getHostId(admin);
2343 
2344  // domain: if configured with a domain, report it:
2345  if (!app_.config().SERVER_DOMAIN.empty())
2346  info[jss::server_domain] = app_.config().SERVER_DOMAIN;
2347 
2348  info[jss::build_version] = BuildInfo::getVersionString();
2349 
2350  info[jss::server_state] = strOperatingMode(admin);
2351 
2352  info[jss::time] = to_string(std::chrono::floor<std::chrono::microseconds>(
2354 
2355  if (needNetworkLedger_)
2356  info[jss::network_ledger] = "waiting";
2357 
2358  info[jss::validation_quorum] =
2359  static_cast<Json::UInt>(app_.validators().quorum());
2360 
2361  if (admin)
2362  {
2363  switch (app_.config().NODE_SIZE)
2364  {
2365  case 0:
2366  info[jss::node_size] = "tiny";
2367  break;
2368  case 1:
2369  info[jss::node_size] = "small";
2370  break;
2371  case 2:
2372  info[jss::node_size] = "medium";
2373  break;
2374  case 3:
2375  info[jss::node_size] = "large";
2376  break;
2377  case 4:
2378  info[jss::node_size] = "huge";
2379  break;
2380  }
2381 
2382  auto when = app_.validators().expires();
2383 
2384  if (!human)
2385  {
2386  if (when)
2387  info[jss::validator_list_expires] =
2388  safe_cast<Json::UInt>(when->time_since_epoch().count());
2389  else
2390  info[jss::validator_list_expires] = 0;
2391  }
2392  else
2393  {
2394  auto& x = (info[jss::validator_list] = Json::objectValue);
2395 
2396  x[jss::count] = static_cast<Json::UInt>(app_.validators().count());
2397 
2398  if (when)
2399  {
2400  if (*when == TimeKeeper::time_point::max())
2401  {
2402  x[jss::expiration] = "never";
2403  x[jss::status] = "active";
2404  }
2405  else
2406  {
2407  x[jss::expiration] = to_string(*when);
2408 
2409  if (*when > app_.timeKeeper().now())
2410  x[jss::status] = "active";
2411  else
2412  x[jss::status] = "expired";
2413  }
2414  }
2415  else
2416  {
2417  x[jss::status] = "unknown";
2418  x[jss::expiration] = "unknown";
2419  }
2420  }
2421  }
2422  info[jss::io_latency_ms] =
2423  static_cast<Json::UInt>(app_.getIOLatency().count());
2424 
2425  if (admin)
2426  {
2428  {
2429  info[jss::pubkey_validator] = toBase58(
2431  }
2432  else
2433  {
2434  info[jss::pubkey_validator] = "none";
2435  }
2436  }
2437 
2438  if (counters)
2439  {
2440  info[jss::counters] = app_.getPerfLog().countersJson();
2441 
2442  Json::Value nodestore(Json::objectValue);
2443  if (app_.getShardStore())
2444  app_.getShardStore()->getCountsJson(nodestore);
2445  else
2446  app_.getNodeStore().getCountsJson(nodestore);
2447  info[jss::counters][jss::nodestore] = nodestore;
2448  info[jss::current_activities] = app_.getPerfLog().currentJson();
2449  }
2450 
2451  info[jss::pubkey_node] =
2453 
2454  info[jss::complete_ledgers] = app_.getLedgerMaster().getCompleteLedgers();
2455 
2456  if (amendmentBlocked_)
2457  info[jss::amendment_blocked] = true;
2458 
2459  auto const fp = m_ledgerMaster.getFetchPackCacheSize();
2460 
2461  if (fp != 0)
2462  info[jss::fetch_pack] = Json::UInt(fp);
2463 
2464  if (!app_.config().reporting())
2465  info[jss::peers] = Json::UInt(app_.overlay().size());
2466 
2467  Json::Value lastClose = Json::objectValue;
2468  lastClose[jss::proposers] = Json::UInt(mConsensus.prevProposers());
2469 
2470  if (human)
2471  {
2472  lastClose[jss::converge_time_s] =
2474  }
2475  else
2476  {
2477  lastClose[jss::converge_time] =
2479  }
2480 
2481  info[jss::last_close] = lastClose;
2482 
2483  // info[jss::consensus] = mConsensus.getJson();
2484 
2485  if (admin)
2486  info[jss::load] = m_job_queue.getJson();
2487 
2488  if (!app_.config().reporting())
2489  {
2490  if (auto const netid = app_.overlay().networkID())
2491  info[jss::network_id] = static_cast<Json::UInt>(*netid);
2492 
2493  auto const escalationMetrics =
2495 
2496  auto const loadFactorServer = app_.getFeeTrack().getLoadFactor();
2497  auto const loadBaseServer = app_.getFeeTrack().getLoadBase();
2498  /* Scale the escalated fee level to unitless "load factor".
2499  In practice, this just strips the units, but it will continue
2500  to work correctly if either base value ever changes. */
2501  auto const loadFactorFeeEscalation =
2502  mulDiv(
2503  escalationMetrics.openLedgerFeeLevel,
2504  loadBaseServer,
2505  escalationMetrics.referenceFeeLevel)
2506  .second;
2507 
2508  auto const loadFactor = std::max(
2509  safe_cast<std::uint64_t>(loadFactorServer),
2510  loadFactorFeeEscalation);
2511 
2512  if (!human)
2513  {
2514  info[jss::load_base] = loadBaseServer;
2515  info[jss::load_factor] = trunc32(loadFactor);
2516  info[jss::load_factor_server] = loadFactorServer;
2517 
2518  /* Json::Value doesn't support uint64, so clamp to max
2519  uint32 value. This is mostly theoretical, since there
2520  probably isn't enough extant XRP to drive the factor
2521  that high.
2522  */
2523  info[jss::load_factor_fee_escalation] =
2524  escalationMetrics.openLedgerFeeLevel.jsonClipped();
2525  info[jss::load_factor_fee_queue] =
2526  escalationMetrics.minProcessingFeeLevel.jsonClipped();
2527  info[jss::load_factor_fee_reference] =
2528  escalationMetrics.referenceFeeLevel.jsonClipped();
2529  }
2530  else
2531  {
2532  info[jss::load_factor] =
2533  static_cast<double>(loadFactor) / loadBaseServer;
2534 
2535  if (loadFactorServer != loadFactor)
2536  info[jss::load_factor_server] =
2537  static_cast<double>(loadFactorServer) / loadBaseServer;
2538 
2539  if (admin)
2540  {
2542  if (fee != loadBaseServer)
2543  info[jss::load_factor_local] =
2544  static_cast<double>(fee) / loadBaseServer;
2545  fee = app_.getFeeTrack().getRemoteFee();
2546  if (fee != loadBaseServer)
2547  info[jss::load_factor_net] =
2548  static_cast<double>(fee) / loadBaseServer;
2549  fee = app_.getFeeTrack().getClusterFee();
2550  if (fee != loadBaseServer)
2551  info[jss::load_factor_cluster] =
2552  static_cast<double>(fee) / loadBaseServer;
2553  }
2554  if (escalationMetrics.openLedgerFeeLevel !=
2555  escalationMetrics.referenceFeeLevel &&
2556  (admin || loadFactorFeeEscalation != loadFactor))
2557  info[jss::load_factor_fee_escalation] =
2558  escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2559  escalationMetrics.referenceFeeLevel);
2560  if (escalationMetrics.minProcessingFeeLevel !=
2561  escalationMetrics.referenceFeeLevel)
2562  info[jss::load_factor_fee_queue] =
2563  escalationMetrics.minProcessingFeeLevel
2564  .decimalFromReference(
2565  escalationMetrics.referenceFeeLevel);
2566  }
2567  }
2568 
2569  bool valid = false;
2570  auto lpClosed = m_ledgerMaster.getValidatedLedger();
2571 
2572  if (lpClosed)
2573  valid = true;
2574  else if (!app_.config().reporting())
2575  lpClosed = m_ledgerMaster.getClosedLedger();
2576 
2577  if (lpClosed)
2578  {
2579  XRPAmount const baseFee = lpClosed->fees().base;
2581  l[jss::seq] = Json::UInt(lpClosed->info().seq);
2582  l[jss::hash] = to_string(lpClosed->info().hash);
2583 
2584  if (!human)
2585  {
2586  l[jss::base_fee] = baseFee.jsonClipped();
2587  l[jss::reserve_base] =
2588  lpClosed->fees().accountReserve(0).jsonClipped();
2589  l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2590  l[jss::close_time] = Json::Value::UInt(
2591  lpClosed->info().closeTime.time_since_epoch().count());
2592  }
2593  else
2594  {
2595  l[jss::base_fee_xrp] = baseFee.decimalXRP();
2596  l[jss::reserve_base_xrp] =
2597  lpClosed->fees().accountReserve(0).decimalXRP();
2598  l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2599 
2600  auto const nowOffset = app_.timeKeeper().nowOffset();
2601  if (std::abs(nowOffset.count()) >= 60)
2602  l[jss::system_time_offset] = nowOffset.count();
2603 
2604  auto const closeOffset = app_.timeKeeper().closeOffset();
2605  if (std::abs(closeOffset.count()) >= 60)
2606  l[jss::close_time_offset] = closeOffset.count();
2607 
2608 #if RIPPLED_REPORTING
2609  std::int64_t const dbAge =
2611  l[jss::age] = Json::UInt(dbAge);
2612 #else
2613  constexpr std::chrono::seconds highAgeThreshold{1000000};
2615  {
2616  auto const age = m_ledgerMaster.getValidatedLedgerAge();
2617  l[jss::age] =
2618  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2619  }
2620  else
2621  {
2622  auto lCloseTime = lpClosed->info().closeTime;
2623  auto closeTime = app_.timeKeeper().closeTime();
2624  if (lCloseTime <= closeTime)
2625  {
2626  using namespace std::chrono_literals;
2627  auto age = closeTime - lCloseTime;
2628  l[jss::age] =
2629  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2630  }
2631  }
2632 #endif
2633  }
2634 
2635  if (valid)
2636  info[jss::validated_ledger] = l;
2637  else
2638  info[jss::closed_ledger] = l;
2639 
2640  auto lpPublished = m_ledgerMaster.getPublishedLedger();
2641  if (!lpPublished)
2642  info[jss::published_ledger] = "none";
2643  else if (lpPublished->info().seq != lpClosed->info().seq)
2644  info[jss::published_ledger] = lpPublished->info().seq;
2645  }
2646 
2647  accounting_.json(info);
2648  info[jss::uptime] = UptimeClock::now().time_since_epoch().count();
2649  if (!app_.config().reporting())
2650  {
2651  info[jss::jq_trans_overflow] =
2653  info[jss::peer_disconnects] =
2655  info[jss::peer_disconnects_resources] =
2657  }
2658  else
2659  {
2660  info["reporting"] = app_.getReportingETL().getInfo();
2661  }
2662 
2663  return info;
2664 }
2665 
2666 void
2668 {
2670 }
2671 
2674 {
2675  return app_.getInboundLedgers().getInfo();
2676 }
2677 
2678 void
2680  std::shared_ptr<ReadView const> const& ledger,
2681  std::shared_ptr<STTx const> const& transaction,
2682  TER result)
2683 {
2684  Json::Value jvObj = transJson(*transaction, result, false, ledger);
2685 
2686  {
2688 
2689  auto it = mStreamMaps[sRTTransactions].begin();
2690  while (it != mStreamMaps[sRTTransactions].end())
2691  {
2692  InfoSub::pointer p = it->second.lock();
2693 
2694  if (p)
2695  {
2696  p->send(jvObj, true);
2697  ++it;
2698  }
2699  else
2700  {
2701  it = mStreamMaps[sRTTransactions].erase(it);
2702  }
2703  }
2704  }
2705 
2706  pubProposedAccountTransaction(ledger, transaction, result);
2707 }
2708 
2709 void
2711 {
2712  // reporting does not forward validated transactions
2713  // validated transactions will be published to the proper streams when the
2714  // etl process writes a validated ledger
2715  if (jvObj[jss::validated].asBool())
2716  return;
2717  {
2719 
2720  auto it = mStreamMaps[sRTTransactions].begin();
2721  while (it != mStreamMaps[sRTTransactions].end())
2722  {
2723  InfoSub::pointer p = it->second.lock();
2724 
2725  if (p)
2726  {
2727  p->send(jvObj, true);
2728  ++it;
2729  }
2730  else
2731  {
2732  it = mStreamMaps[sRTTransactions].erase(it);
2733  }
2734  }
2735  }
2736 
2738 }
2739 
2740 void
2742 {
2744 
2745  for (auto i = mStreamMaps[sValidations].begin();
2746  i != mStreamMaps[sValidations].end();)
2747  {
2748  if (auto p = i->second.lock())
2749  {
2750  p->send(jvObj, true);
2751  ++i;
2752  }
2753  else
2754  {
2755  i = mStreamMaps[sValidations].erase(i);
2756  }
2757  }
2758 }
2759 
2760 void
2762 {
2764 
2765  for (auto i = mStreamMaps[sManifests].begin();
2766  i != mStreamMaps[sManifests].end();)
2767  {
2768  if (auto p = i->second.lock())
2769  {
2770  p->send(jvObj, true);
2771  ++i;
2772  }
2773  else
2774  {
2775  i = mStreamMaps[sManifests].erase(i);
2776  }
2777  }
2778 }
2779 
2780 static void
2782 {
2783  for (auto& jv : jvObj)
2784  {
2785  if (jv.isObject())
2786  {
2787  getAccounts(jv, accounts);
2788  }
2789  else if (jv.isString())
2790  {
2791  auto account = RPC::accountFromStringStrict(jv.asString());
2792  if (account)
2793  accounts.push_back(*account);
2794  }
2795  }
2796 }
2797 
2798 void
2800 {
2802  int iProposed = 0;
2803  // check if there are any subscribers before attempting to parse the JSON
2804  {
2806 
2807  if (mSubRTAccount.empty())
2808  return;
2809  }
2810 
2811  // parse the JSON outside of the lock
2812  std::vector<AccountID> accounts;
2813  if (jvObj.isMember(jss::transaction))
2814  {
2815  try
2816  {
2817  getAccounts(jvObj[jss::transaction], accounts);
2818  }
2819  catch (...)
2820  {
2821  JLOG(m_journal.debug())
2822  << __func__ << " : "
2823  << "error parsing json for accounts affected";
2824  return;
2825  }
2826  }
2827  {
2829 
2830  if (!mSubRTAccount.empty())
2831  {
2832  for (auto const& affectedAccount : accounts)
2833  {
2834  auto simiIt = mSubRTAccount.find(affectedAccount);
2835  if (simiIt != mSubRTAccount.end())
2836  {
2837  auto it = simiIt->second.begin();
2838 
2839  while (it != simiIt->second.end())
2840  {
2841  InfoSub::pointer p = it->second.lock();
2842 
2843  if (p)
2844  {
2845  notify.insert(p);
2846  ++it;
2847  ++iProposed;
2848  }
2849  else
2850  it = simiIt->second.erase(it);
2851  }
2852  }
2853  }
2854  }
2855  }
2856  JLOG(m_journal.trace()) << "forwardProposedAccountTransaction:"
2857  << " iProposed=" << iProposed;
2858 
2859  if (!notify.empty())
2860  {
2861  for (InfoSub::ref isrListener : notify)
2862  isrListener->send(jvObj, true);
2863  }
2864 }
2865 
2866 void
2868 {
2869  // Ledgers are published only when they acquire sufficient validations
2870  // Holes are filled across connection loss or other catastrophe
2871 
2872  std::shared_ptr<AcceptedLedger> alpAccepted =
2873  app_.getAcceptedLedgerCache().fetch(lpAccepted->info().hash);
2874  if (!alpAccepted)
2875  {
2876  alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted, app_);
2877  app_.getAcceptedLedgerCache().canonicalize_replace_client(
2878  lpAccepted->info().hash, alpAccepted);
2879  }
2880 
2881  assert(alpAccepted->getLedger().get() == lpAccepted.get());
2882 
2883  {
2884  JLOG(m_journal.debug())
2885  << "Publishing ledger " << lpAccepted->info().seq << " "
2886  << lpAccepted->info().hash;
2887 
2889 
2890  if (!mStreamMaps[sLedger].empty())
2891  {
2893 
2894  jvObj[jss::type] = "ledgerClosed";
2895  jvObj[jss::ledger_index] = lpAccepted->info().seq;
2896  jvObj[jss::ledger_hash] = to_string(lpAccepted->info().hash);
2897  jvObj[jss::ledger_time] = Json::Value::UInt(
2898  lpAccepted->info().closeTime.time_since_epoch().count());
2899 
2900  if (!lpAccepted->rules().enabled(featureXRPFees))
2901  jvObj[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
2902  jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2903  jvObj[jss::reserve_base] =
2904  lpAccepted->fees().accountReserve(0).jsonClipped();
2905  jvObj[jss::reserve_inc] =
2906  lpAccepted->fees().increment.jsonClipped();
2907 
2908  jvObj[jss::txn_count] = Json::UInt(alpAccepted->size());
2909 
2911  {
2912  jvObj[jss::validated_ledgers] =
2914  }
2915 
2916  auto it = mStreamMaps[sLedger].begin();
2917  while (it != mStreamMaps[sLedger].end())
2918  {
2919  InfoSub::pointer p = it->second.lock();
2920  if (p)
2921  {
2922  p->send(jvObj, true);
2923  ++it;
2924  }
2925  else
2926  it = mStreamMaps[sLedger].erase(it);
2927  }
2928  }
2929 
2930  if (!mStreamMaps[sBookChanges].empty())
2931  {
2932  Json::Value jvObj = ripple::RPC::computeBookChanges(lpAccepted);
2933 
2934  auto it = mStreamMaps[sBookChanges].begin();
2935  while (it != mStreamMaps[sBookChanges].end())
2936  {
2937  InfoSub::pointer p = it->second.lock();
2938  if (p)
2939  {
2940  p->send(jvObj, true);
2941  ++it;
2942  }
2943  else
2944  it = mStreamMaps[sBookChanges].erase(it);
2945  }
2946  }
2947 
2948  {
2949  static bool firstTime = true;
2950  if (firstTime)
2951  {
2952  // First validated ledger, start delayed SubAccountHistory
2953  firstTime = false;
2954  for (auto& outer : mSubAccountHistory)
2955  {
2956  for (auto& inner : outer.second)
2957  {
2958  auto& subInfo = inner.second;
2959  if (subInfo.index_->separationLedgerSeq_ == 0)
2960  {
2962  alpAccepted->getLedger(), subInfo);
2963  }
2964  }
2965  }
2966  }
2967  }
2968  }
2969 
2970  // Don't lock since pubAcceptedTransaction is locking.
2971  for (auto const& accTx : *alpAccepted)
2972  {
2973  JLOG(m_journal.trace()) << "pubAccepted: " << accTx->getJson();
2974  pubValidatedTransaction(lpAccepted, *accTx);
2975  }
2976 }
2977 
2978 void
2980 {
2981  if (app_.config().reporting())
2982  return;
2983  ServerFeeSummary f{
2984  app_.openLedger().current()->fees().base,
2986  app_.getFeeTrack()};
2987 
2988  // only schedule the job if something has changed
2989  if (f != mLastFeeSummary)
2990  {
2992  jtCLIENT_FEE_CHANGE, "reportFeeChange->pubServer", [this]() {
2993  pubServer();
2994  });
2995  }
2996 }
2997 
2998 void
3000 {
3003  "reportConsensusStateChange->pubConsensus",
3004  [this, phase]() { pubConsensus(phase); });
3005 }
3006 
3007 inline void
3009 {
3010  m_localTX->sweep(view);
3011 }
3012 inline std::size_t
3014 {
3015  return m_localTX->size();
3016 }
3017 
3018 // This routine should only be used to publish accepted or validated
3019 // transactions.
3022  const STTx& transaction,
3023  TER result,
3024  bool validated,
3025  std::shared_ptr<ReadView const> const& ledger)
3026 {
3028  std::string sToken;
3029  std::string sHuman;
3030 
3031  transResultInfo(result, sToken, sHuman);
3032 
3033  jvObj[jss::type] = "transaction";
3034  jvObj[jss::transaction] = transaction.getJson(JsonOptions::none);
3035 
3036  if (validated)
3037  {
3038  jvObj[jss::ledger_index] = ledger->info().seq;
3039  jvObj[jss::ledger_hash] = to_string(ledger->info().hash);
3040  jvObj[jss::transaction][jss::date] =
3041  ledger->info().closeTime.time_since_epoch().count();
3042  jvObj[jss::validated] = true;
3043 
3044  // WRITEME: Put the account next seq here
3045  }
3046  else
3047  {
3048  jvObj[jss::validated] = false;
3049  jvObj[jss::ledger_current_index] = ledger->info().seq;
3050  }
3051 
3052  jvObj[jss::status] = validated ? "closed" : "proposed";
3053  jvObj[jss::engine_result] = sToken;
3054  jvObj[jss::engine_result_code] = result;
3055  jvObj[jss::engine_result_message] = sHuman;
3056 
3057  if (transaction.getTxnType() == ttOFFER_CREATE)
3058  {
3059  auto const account = transaction.getAccountID(sfAccount);
3060  auto const amount = transaction.getFieldAmount(sfTakerGets);
3061 
3062  // If the offer create is not self funded then add the owner balance
3063  if (account != amount.issue().account)
3064  {
3065  auto const ownerFunds = accountFunds(
3066  *ledger,
3067  account,
3068  amount,
3070  app_.journal("View"));
3071  jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3072  }
3073  }
3074 
3075  return jvObj;
3076 }
3077 
3078 void
3080  std::shared_ptr<ReadView const> const& ledger,
3081  const AcceptedLedgerTx& transaction)
3082 {
3083  auto const& stTxn = transaction.getTxn();
3084 
3085  Json::Value jvObj =
3086  transJson(*stTxn, transaction.getResult(), true, ledger);
3087 
3088  {
3089  auto const& meta = transaction.getMeta();
3090  jvObj[jss::meta] = meta.getJson(JsonOptions::none);
3091  RPC::insertDeliveredAmount(jvObj[jss::meta], *ledger, stTxn, meta);
3092  }
3093 
3094  {
3096 
3097  auto it = mStreamMaps[sTransactions].begin();
3098  while (it != mStreamMaps[sTransactions].end())
3099  {
3100  InfoSub::pointer p = it->second.lock();
3101 
3102  if (p)
3103  {
3104  p->send(jvObj, true);
3105  ++it;
3106  }
3107  else
3108  it = mStreamMaps[sTransactions].erase(it);
3109  }
3110 
3111  it = mStreamMaps[sRTTransactions].begin();
3112 
3113  while (it != mStreamMaps[sRTTransactions].end())
3114  {
3115  InfoSub::pointer p = it->second.lock();
3116 
3117  if (p)
3118  {
3119  p->send(jvObj, true);
3120  ++it;
3121  }
3122  else
3123  it = mStreamMaps[sRTTransactions].erase(it);
3124  }
3125  }
3126 
3127  if (transaction.getResult() == tesSUCCESS)
3128  app_.getOrderBookDB().processTxn(ledger, transaction, jvObj);
3129 
3130  pubAccountTransaction(ledger, transaction);
3131 }
3132 
3133 void
3135  std::shared_ptr<ReadView const> const& ledger,
3136  AcceptedLedgerTx const& transaction)
3137 {
3139  int iProposed = 0;
3140  int iAccepted = 0;
3141 
3142  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3143  auto const currLedgerSeq = ledger->seq();
3144  {
3146 
3147  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3149  {
3150  for (auto const& affectedAccount : transaction.getAffected())
3151  {
3152  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3153  simiIt != mSubRTAccount.end())
3154  {
3155  auto it = simiIt->second.begin();
3156 
3157  while (it != simiIt->second.end())
3158  {
3159  InfoSub::pointer p = it->second.lock();
3160 
3161  if (p)
3162  {
3163  notify.insert(p);
3164  ++it;
3165  ++iProposed;
3166  }
3167  else
3168  it = simiIt->second.erase(it);
3169  }
3170  }
3171 
3172  if (auto simiIt = mSubAccount.find(affectedAccount);
3173  simiIt != mSubAccount.end())
3174  {
3175  auto it = simiIt->second.begin();
3176  while (it != simiIt->second.end())
3177  {
3178  InfoSub::pointer p = it->second.lock();
3179 
3180  if (p)
3181  {
3182  notify.insert(p);
3183  ++it;
3184  ++iAccepted;
3185  }
3186  else
3187  it = simiIt->second.erase(it);
3188  }
3189  }
3190 
3191  if (auto histoIt = mSubAccountHistory.find(affectedAccount);
3192  histoIt != mSubAccountHistory.end())
3193  {
3194  auto& subs = histoIt->second;
3195  auto it = subs.begin();
3196  while (it != subs.end())
3197  {
3198  SubAccountHistoryInfoWeak const& info = it->second;
3199  if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3200  {
3201  ++it;
3202  continue;
3203  }
3204 
3205  if (auto isSptr = info.sinkWptr_.lock(); isSptr)
3206  {
3207  accountHistoryNotify.emplace_back(
3208  SubAccountHistoryInfo{isSptr, info.index_});
3209  ++it;
3210  }
3211  else
3212  {
3213  it = subs.erase(it);
3214  }
3215  }
3216  if (subs.empty())
3217  mSubAccountHistory.erase(histoIt);
3218  }
3219  }
3220  }
3221  }
3222 
3223  JLOG(m_journal.trace())
3224  << "pubAccountTransaction: "
3225  << "proposed=" << iProposed << ", accepted=" << iAccepted;
3226 
3227  if (!notify.empty() || !accountHistoryNotify.empty())
3228  {
3229  auto const& stTxn = transaction.getTxn();
3230 
3231  Json::Value jvObj =
3232  transJson(*stTxn, transaction.getResult(), true, ledger);
3233 
3234  {
3235  auto const& meta = transaction.getMeta();
3236 
3237  jvObj[jss::meta] = meta.getJson(JsonOptions::none);
3238  RPC::insertDeliveredAmount(jvObj[jss::meta], *ledger, stTxn, meta);
3239  }
3240 
3241  for (InfoSub::ref isrListener : notify)
3242  isrListener->send(jvObj, true);
3243 
3244  assert(!jvObj.isMember(jss::account_history_tx_stream));
3245  for (auto& info : accountHistoryNotify)
3246  {
3247  auto& index = info.index_;
3248  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3249  jvObj[jss::account_history_tx_first] = true;
3250  jvObj[jss::account_history_tx_index] = index->forwardTxIndex_++;
3251  info.sink_->send(jvObj, true);
3252  }
3253  }
3254 }
3255 
3256 void
3258  std::shared_ptr<ReadView const> const& ledger,
3259  std::shared_ptr<STTx const> const& tx,
3260  TER result)
3261 {
3263  int iProposed = 0;
3264 
3265  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3266 
3267  {
3269 
3270  if (mSubRTAccount.empty())
3271  return;
3272 
3273  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3275  {
3276  for (auto const& affectedAccount : tx->getMentionedAccounts())
3277  {
3278  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3279  simiIt != mSubRTAccount.end())
3280  {
3281  auto it = simiIt->second.begin();
3282 
3283  while (it != simiIt->second.end())
3284  {
3285  InfoSub::pointer p = it->second.lock();
3286 
3287  if (p)
3288  {
3289  notify.insert(p);
3290  ++it;
3291  ++iProposed;
3292  }
3293  else
3294  it = simiIt->second.erase(it);
3295  }
3296  }
3297  }
3298  }
3299  }
3300 
3301  JLOG(m_journal.trace()) << "pubProposedAccountTransaction: " << iProposed;
3302 
3303  if (!notify.empty() || !accountHistoryNotify.empty())
3304  {
3305  Json::Value jvObj = transJson(*tx, result, false, ledger);
3306 
3307  for (InfoSub::ref isrListener : notify)
3308  isrListener->send(jvObj, true);
3309 
3310  assert(!jvObj.isMember(jss::account_history_tx_stream));
3311  for (auto& info : accountHistoryNotify)
3312  {
3313  auto& index = info.index_;
3314  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3315  jvObj[jss::account_history_tx_first] = true;
3316  jvObj[jss::account_history_tx_index] = index->forwardTxIndex_++;
3317  info.sink_->send(jvObj, true);
3318  }
3319  }
3320 }
3321 
3322 //
3323 // Monitoring
3324 //
3325 
3326 void
3328  InfoSub::ref isrListener,
3329  hash_set<AccountID> const& vnaAccountIDs,
3330  bool rt)
3331 {
3332  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3333 
3334  for (auto const& naAccountID : vnaAccountIDs)
3335  {
3336  JLOG(m_journal.trace())
3337  << "subAccount: account: " << toBase58(naAccountID);
3338 
3339  isrListener->insertSubAccountInfo(naAccountID, rt);
3340  }
3341 
3343 
3344  for (auto const& naAccountID : vnaAccountIDs)
3345  {
3346  auto simIterator = subMap.find(naAccountID);
3347  if (simIterator == subMap.end())
3348  {
3349  // Not found, note that account has a new single listner.
3350  SubMapType usisElement;
3351  usisElement[isrListener->getSeq()] = isrListener;
3352  // VFALCO NOTE This is making a needless copy of naAccountID
3353  subMap.insert(simIterator, make_pair(naAccountID, usisElement));
3354  }
3355  else
3356  {
3357  // Found, note that the account has another listener.
3358  simIterator->second[isrListener->getSeq()] = isrListener;
3359  }
3360  }
3361 }
3362 
3363 void
3365  InfoSub::ref isrListener,
3366  hash_set<AccountID> const& vnaAccountIDs,
3367  bool rt)
3368 {
3369  for (auto const& naAccountID : vnaAccountIDs)
3370  {
3371  // Remove from the InfoSub
3372  isrListener->deleteSubAccountInfo(naAccountID, rt);
3373  }
3374 
3375  // Remove from the server
3376  unsubAccountInternal(isrListener->getSeq(), vnaAccountIDs, rt);
3377 }
3378 
3379 void
3381  std::uint64_t uSeq,
3382  hash_set<AccountID> const& vnaAccountIDs,
3383  bool rt)
3384 {
3386 
3387  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3388 
3389  for (auto const& naAccountID : vnaAccountIDs)
3390  {
3391  auto simIterator = subMap.find(naAccountID);
3392 
3393  if (simIterator != subMap.end())
3394  {
3395  // Found
3396  simIterator->second.erase(uSeq);
3397 
3398  if (simIterator->second.empty())
3399  {
3400  // Don't need hash entry.
3401  subMap.erase(simIterator);
3402  }
3403  }
3404  }
3405 }
3406 
3407 void
3409 {
3410  enum DatabaseType { Postgres, Sqlite, None };
3411  static const auto databaseType = [&]() -> DatabaseType {
3412 #ifdef RIPPLED_REPORTING
3413  if (app_.config().reporting())
3414  {
3415  // Use a dynamic_cast to return DatabaseType::None
3416  // on failure.
3417  if (dynamic_cast<PostgresDatabase*>(&app_.getRelationalDatabase()))
3418  {
3419  return DatabaseType::Postgres;
3420  }
3421  return DatabaseType::None;
3422  }
3423  else
3424  {
3425  // Use a dynamic_cast to return DatabaseType::None
3426  // on failure.
3427  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3428  {
3429  return DatabaseType::Sqlite;
3430  }
3431  return DatabaseType::None;
3432  }
3433 #else
3434  // Use a dynamic_cast to return DatabaseType::None
3435  // on failure.
3436  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3437  {
3438  return DatabaseType::Sqlite;
3439  }
3440  return DatabaseType::None;
3441 #endif
3442  }();
3443 
3444  if (databaseType == DatabaseType::None)
3445  {
3446  JLOG(m_journal.error())
3447  << "AccountHistory job for account "
3448  << toBase58(subInfo.index_->accountId_) << " no database";
3449  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3450  {
3451  sptr->send(rpcError(rpcINTERNAL), true);
3452  unsubAccountHistory(sptr, subInfo.index_->accountId_, false);
3453  }
3454  return;
3455  }
3456 
3459  "AccountHistoryTxStream",
3460  [this, dbType = databaseType, subInfo]() {
3461  auto const& accountId = subInfo.index_->accountId_;
3462  auto& lastLedgerSeq = subInfo.index_->historyLastLedgerSeq_;
3463  auto& txHistoryIndex = subInfo.index_->historyTxIndex_;
3464 
3465  JLOG(m_journal.trace())
3466  << "AccountHistory job for account " << toBase58(accountId)
3467  << " started. lastLedgerSeq=" << lastLedgerSeq;
3468 
3469  auto isFirstTx = [&](std::shared_ptr<Transaction> const& tx,
3470  std::shared_ptr<TxMeta> const& meta) -> bool {
3471  /*
3472  * genesis account: first tx is the one with seq 1
3473  * other account: first tx is the one created the account
3474  */
3475  if (accountId == genesisAccountId)
3476  {
3477  auto stx = tx->getSTransaction();
3478  if (stx->getAccountID(sfAccount) == accountId &&
3479  stx->getSeqProxy().value() == 1)
3480  return true;
3481  }
3482 
3483  for (auto& node : meta->getNodes())
3484  {
3485  if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3486  continue;
3487 
3488  if (node.isFieldPresent(sfNewFields))
3489  {
3490  if (auto inner = dynamic_cast<const STObject*>(
3491  node.peekAtPField(sfNewFields));
3492  inner)
3493  {
3494  if (inner->isFieldPresent(sfAccount) &&
3495  inner->getAccountID(sfAccount) == accountId)
3496  {
3497  return true;
3498  }
3499  }
3500  }
3501  }
3502 
3503  return false;
3504  };
3505 
3506  auto send = [&](Json::Value const& jvObj,
3507  bool unsubscribe) -> bool {
3508  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3509  {
3510  sptr->send(jvObj, true);
3511  if (unsubscribe)
3512  unsubAccountHistory(sptr, accountId, false);
3513  return true;
3514  }
3515 
3516  return false;
3517  };
3518 
3519  auto getMoreTxns =
3520  [&](std::uint32_t minLedger,
3521  std::uint32_t maxLedger,
3526  switch (dbType)
3527  {
3528  case Postgres: {
3529  auto db = static_cast<PostgresDatabase*>(
3532  args.account = accountId;
3533  LedgerRange range{minLedger, maxLedger};
3534  args.ledger = range;
3535  args.marker = marker;
3536  auto [txResult, status] = db->getAccountTx(args);
3537  if (status != rpcSUCCESS)
3538  {
3539  JLOG(m_journal.debug())
3540  << "AccountHistory job for account "
3541  << toBase58(accountId)
3542  << " getAccountTx failed";
3543  return {};
3544  }
3545 
3546  if (auto txns =
3547  std::get_if<RelationalDatabase::AccountTxs>(
3548  &txResult.transactions);
3549  txns)
3550  {
3551  return std::make_pair(*txns, txResult.marker);
3552  }
3553  else
3554  {
3555  JLOG(m_journal.debug())
3556  << "AccountHistory job for account "
3557  << toBase58(accountId)
3558  << " getAccountTx wrong data";
3559  return {};
3560  }
3561  }
3562  case Sqlite: {
3563  auto db = static_cast<SQLiteDatabase*>(
3566  accountId, minLedger, maxLedger, marker, 0, true};
3567  return db->newestAccountTxPage(options);
3568  }
3569  default: {
3570  assert(false);
3571  return {};
3572  }
3573  }
3574  };
3575 
3576  /*
3577  * search backward until the genesis ledger or asked to stop
3578  */
3579  while (lastLedgerSeq >= 2 && !subInfo.index_->stopHistorical_)
3580  {
3581  int feeChargeCount = 0;
3582  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3583  {
3584  sptr->getConsumer().charge(Resource::feeMediumBurdenRPC);
3585  ++feeChargeCount;
3586  }
3587  else
3588  {
3589  JLOG(m_journal.trace())
3590  << "AccountHistory job for account "
3591  << toBase58(accountId) << " no InfoSub. Fee charged "
3592  << feeChargeCount << " times.";
3593  return;
3594  }
3595 
3596  // try to search in 1024 ledgers till reaching genesis ledgers
3597  auto startLedgerSeq =
3598  (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3599  JLOG(m_journal.trace())
3600  << "AccountHistory job for account " << toBase58(accountId)
3601  << ", working on ledger range [" << startLedgerSeq << ","
3602  << lastLedgerSeq << "]";
3603 
3604  auto haveRange = [&]() -> bool {
3605  std::uint32_t validatedMin = UINT_MAX;
3606  std::uint32_t validatedMax = 0;
3607  auto haveSomeValidatedLedgers =
3609  validatedMin, validatedMax);
3610 
3611  return haveSomeValidatedLedgers &&
3612  validatedMin <= startLedgerSeq &&
3613  lastLedgerSeq <= validatedMax;
3614  }();
3615 
3616  if (!haveRange)
3617  {
3618  JLOG(m_journal.debug())
3619  << "AccountHistory reschedule job for account "
3620  << toBase58(accountId) << ", incomplete ledger range ["
3621  << startLedgerSeq << "," << lastLedgerSeq << "]";
3622  setAccountHistoryJobTimer(subInfo);
3623  return;
3624  }
3625 
3627  while (!subInfo.index_->stopHistorical_)
3628  {
3629  auto dbResult =
3630  getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3631  if (!dbResult)
3632  {
3633  JLOG(m_journal.debug())
3634  << "AccountHistory job for account "
3635  << toBase58(accountId) << " getMoreTxns failed.";
3636  send(rpcError(rpcINTERNAL), true);
3637  return;
3638  }
3639 
3640  auto const& txns = dbResult->first;
3641  marker = dbResult->second;
3642  for (auto const& [tx, meta] : txns)
3643  {
3644  if (!tx || !meta)
3645  {
3646  JLOG(m_journal.debug())
3647  << "AccountHistory job for account "
3648  << toBase58(accountId) << " empty tx or meta.";
3649  send(rpcError(rpcINTERNAL), true);
3650  return;
3651  }
3652  auto curTxLedger =
3654  tx->getLedger());
3655  if (!curTxLedger)
3656  {
3657  JLOG(m_journal.debug())
3658  << "AccountHistory job for account "
3659  << toBase58(accountId) << " no ledger.";
3660  send(rpcError(rpcINTERNAL), true);
3661  return;
3662  }
3664  tx->getSTransaction();
3665  if (!stTxn)
3666  {
3667  JLOG(m_journal.debug())
3668  << "AccountHistory job for account "
3669  << toBase58(accountId)
3670  << " getSTransaction failed.";
3671  send(rpcError(rpcINTERNAL), true);
3672  return;
3673  }
3674  Json::Value jvTx = transJson(
3675  *stTxn, meta->getResultTER(), true, curTxLedger);
3676  jvTx[jss::meta] = meta->getJson(JsonOptions::none);
3677  jvTx[jss::account_history_tx_index] = txHistoryIndex--;
3679  jvTx[jss::meta], *curTxLedger, stTxn, *meta);
3680  if (isFirstTx(tx, meta))
3681  {
3682  jvTx[jss::account_history_tx_first] = true;
3683  send(jvTx, false);
3684 
3685  JLOG(m_journal.trace())
3686  << "AccountHistory job for account "
3687  << toBase58(accountId)
3688  << " done, found last tx.";
3689  return;
3690  }
3691  else
3692  {
3693  send(jvTx, false);
3694  }
3695  }
3696 
3697  if (marker)
3698  {
3699  JLOG(m_journal.trace())
3700  << "AccountHistory job for account "
3701  << toBase58(accountId)
3702  << " paging, marker=" << marker->ledgerSeq << ":"
3703  << marker->txnSeq;
3704  }
3705  else
3706  {
3707  break;
3708  }
3709  }
3710 
3711  if (!subInfo.index_->stopHistorical_)
3712  {
3713  lastLedgerSeq = startLedgerSeq - 1;
3714  if (lastLedgerSeq <= 1)
3715  {
3716  JLOG(m_journal.trace())
3717  << "AccountHistory job for account "
3718  << toBase58(accountId)
3719  << " done, reached genesis ledger.";
3720  return;
3721  }
3722  }
3723  }
3724  });
3725 }
3726 
3727 void
3729  std::shared_ptr<ReadView const> const& ledger,
3730  SubAccountHistoryInfoWeak& subInfo)
3731 {
3732  subInfo.index_->separationLedgerSeq_ = ledger->seq();
3733  auto const& accountId = subInfo.index_->accountId_;
3734  auto const accountKeylet = keylet::account(accountId);
3735  if (!ledger->exists(accountKeylet))
3736  {
3737  JLOG(m_journal.debug())
3738  << "subAccountHistoryStart, no account " << toBase58(accountId)
3739  << ", no need to add AccountHistory job.";
3740  return;
3741  }
3742  if (accountId == genesisAccountId)
3743  {
3744  if (auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3745  {
3746  if (sleAcct->getFieldU32(sfSequence) == 1)
3747  {
3748  JLOG(m_journal.debug())
3749  << "subAccountHistoryStart, genesis account "
3750  << toBase58(accountId)
3751  << " does not have tx, no need to add AccountHistory job.";
3752  return;
3753  }
3754  }
3755  else
3756  {
3757  assert(false);
3758  return;
3759  }
3760  }
3761  subInfo.index_->historyLastLedgerSeq_ = ledger->seq();
3762  subInfo.index_->haveHistorical_ = true;
3763 
3764  JLOG(m_journal.debug())
3765  << "subAccountHistoryStart, add AccountHistory job: accountId="
3766  << toBase58(accountId) << ", currentLedgerSeq=" << ledger->seq();
3767 
3768  addAccountHistoryJob(subInfo);
3769 }
3770 
3773  InfoSub::ref isrListener,
3774  AccountID const& accountId)
3775 {
3776  if (!isrListener->insertSubAccountHistory(accountId))
3777  {
3778  JLOG(m_journal.debug())
3779  << "subAccountHistory, already subscribed to account "
3780  << toBase58(accountId);
3781  return rpcINVALID_PARAMS;
3782  }
3783 
3786  isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3787  auto simIterator = mSubAccountHistory.find(accountId);
3788  if (simIterator == mSubAccountHistory.end())
3789  {
3791  inner.emplace(isrListener->getSeq(), ahi);
3793  simIterator, std::make_pair(accountId, inner));
3794  }
3795  else
3796  {
3797  simIterator->second.emplace(isrListener->getSeq(), ahi);
3798  }
3799 
3800  auto const ledger = app_.getLedgerMaster().getValidatedLedger();
3801  if (ledger)
3802  {
3803  subAccountHistoryStart(ledger, ahi);
3804  }
3805  else
3806  {
3807  // The node does not have validated ledgers, so wait for
3808  // one before start streaming.
3809  // In this case, the subscription is also considered successful.
3810  JLOG(m_journal.debug())
3811  << "subAccountHistory, no validated ledger yet, delay start";
3812  }
3813 
3814  return rpcSUCCESS;
3815 }
3816 
3817 void
3819  InfoSub::ref isrListener,
3820  AccountID const& account,
3821  bool historyOnly)
3822 {
3823  if (!historyOnly)
3824  isrListener->deleteSubAccountHistory(account);
3825  unsubAccountHistoryInternal(isrListener->getSeq(), account, historyOnly);
3826 }
3827 
3828 void
3830  std::uint64_t seq,
3831  const AccountID& account,
3832  bool historyOnly)
3833 {
3835  auto simIterator = mSubAccountHistory.find(account);
3836  if (simIterator != mSubAccountHistory.end())
3837  {
3838  auto& subInfoMap = simIterator->second;
3839  auto subInfoIter = subInfoMap.find(seq);
3840  if (subInfoIter != subInfoMap.end())
3841  {
3842  subInfoIter->second.index_->stopHistorical_ = true;
3843  }
3844 
3845  if (!historyOnly)
3846  {
3847  simIterator->second.erase(seq);
3848  if (simIterator->second.empty())
3849  {
3850  mSubAccountHistory.erase(simIterator);
3851  }
3852  }
3853  JLOG(m_journal.debug())
3854  << "unsubAccountHistory, account " << toBase58(account)
3855  << ", historyOnly = " << (historyOnly ? "true" : "false");
3856  }
3857 }
3858 
3859 bool
3860 NetworkOPsImp::subBook(InfoSub::ref isrListener, Book const& book)
3861 {
3862  if (auto listeners = app_.getOrderBookDB().makeBookListeners(book))
3863  listeners->addSubscriber(isrListener);
3864  else
3865  assert(false);
3866  return true;
3867 }
3868 
3869 bool
3871 {
3872  if (auto listeners = app_.getOrderBookDB().getBookListeners(book))
3873  listeners->removeSubscriber(uSeq);
3874 
3875  return true;
3876 }
3877 
3881 {
3882  // This code-path is exclusively used when the server is in standalone
3883  // mode via `ledger_accept`
3884  assert(m_standalone);
3885 
3886  if (!m_standalone)
3887  Throw<std::runtime_error>(
3888  "Operation only possible in STANDALONE mode.");
3889 
3890  // FIXME Could we improve on this and remove the need for a specialized
3891  // API in Consensus?
3893  mConsensus.simulate(app_.timeKeeper().closeTime(), consensusDelay);
3894  return m_ledgerMaster.getCurrentLedger()->info().seq;
3895 }
3896 
3897 // <-- bool: true=added, false=already there
3898 bool
3900 {
3901  if (auto lpClosed = m_ledgerMaster.getValidatedLedger())
3902  {
3903  jvResult[jss::ledger_index] = lpClosed->info().seq;
3904  jvResult[jss::ledger_hash] = to_string(lpClosed->info().hash);
3905  jvResult[jss::ledger_time] = Json::Value::UInt(
3906  lpClosed->info().closeTime.time_since_epoch().count());
3907  if (!lpClosed->rules().enabled(featureXRPFees))
3908  jvResult[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
3909  jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
3910  jvResult[jss::reserve_base] =
3911  lpClosed->fees().accountReserve(0).jsonClipped();
3912  jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
3913  }
3914 
3916  {
3917  jvResult[jss::validated_ledgers] =
3919  }
3920 
3922  return mStreamMaps[sLedger]
3923  .emplace(isrListener->getSeq(), isrListener)
3924  .second;
3925 }
3926 
3927 // <-- bool: true=added, false=already there
3928 bool
3930 {
3932  return mStreamMaps[sBookChanges]
3933  .emplace(isrListener->getSeq(), isrListener)
3934  .second;
3935 }
3936 
3937 // <-- bool: true=erased, false=was not there
3938 bool
3940 {
3942  return mStreamMaps[sLedger].erase(uSeq);
3943 }
3944 
3945 // <-- bool: true=erased, false=was not there
3946 bool
3948 {
3950  return mStreamMaps[sBookChanges].erase(uSeq);
3951 }
3952 
3953 // <-- bool: true=added, false=already there
3954 bool
3956 {
3958  return mStreamMaps[sManifests]
3959  .emplace(isrListener->getSeq(), isrListener)
3960  .second;
3961 }
3962 
3963 // <-- bool: true=erased, false=was not there
3964 bool
3966 {
3968  return mStreamMaps[sManifests].erase(uSeq);
3969 }
3970 
3971 // <-- bool: true=added, false=already there
3972 bool
3974  InfoSub::ref isrListener,
3975  Json::Value& jvResult,
3976  bool admin)
3977 {
3978  uint256 uRandom;
3979 
3980  if (m_standalone)
3981  jvResult[jss::stand_alone] = m_standalone;
3982 
3983  // CHECKME: is it necessary to provide a random number here?
3984  beast::rngfill(uRandom.begin(), uRandom.size(), crypto_prng());
3985 
3986  auto const& feeTrack = app_.getFeeTrack();
3987  jvResult[jss::random] = to_string(uRandom);
3988  jvResult[jss::server_status] = strOperatingMode(admin);
3989  jvResult[jss::load_base] = feeTrack.getLoadBase();
3990  jvResult[jss::load_factor] = feeTrack.getLoadFactor();
3991  jvResult[jss::hostid] = getHostId(admin);
3992  jvResult[jss::pubkey_node] =
3994 
3996  return mStreamMaps[sServer]
3997  .emplace(isrListener->getSeq(), isrListener)
3998  .second;
3999 }
4000 
4001 // <-- bool: true=erased, false=was not there
4002 bool
4004 {
4006  return mStreamMaps[sServer].erase(uSeq);
4007 }
4008 
4009 // <-- bool: true=added, false=already there
4010 bool
4012 {
4014  return mStreamMaps[sTransactions]
4015  .emplace(isrListener->getSeq(), isrListener)
4016  .second;
4017 }
4018 
4019 // <-- bool: true=erased, false=was not there
4020 bool
4022 {
4024  return mStreamMaps[sTransactions].erase(uSeq);
4025 }
4026 
4027 // <-- bool: true=added, false=already there
4028 bool
4030 {
4033  .emplace(isrListener->getSeq(), isrListener)
4034  .second;
4035 }
4036 
4037 // <-- bool: true=erased, false=was not there
4038 bool
4040 {
4042  return mStreamMaps[sRTTransactions].erase(uSeq);
4043 }
4044 
4045 // <-- bool: true=added, false=already there
4046 bool
4048 {
4050  return mStreamMaps[sValidations]
4051  .emplace(isrListener->getSeq(), isrListener)
4052  .second;
4053 }
4054 
4055 void
4057 {
4058  accounting_.json(obj);
4059 }
4060 
4061 // <-- bool: true=erased, false=was not there
4062 bool
4064 {
4066  return mStreamMaps[sValidations].erase(uSeq);
4067 }
4068 
4069 // <-- bool: true=added, false=already there
4070 bool
4072 {
4074  return mStreamMaps[sPeerStatus]
4075  .emplace(isrListener->getSeq(), isrListener)
4076  .second;
4077 }
4078 
4079 // <-- bool: true=erased, false=was not there
4080 bool
4082 {
4084  return mStreamMaps[sPeerStatus].erase(uSeq);
4085 }
4086 
4087 // <-- bool: true=added, false=already there
4088 bool
4090 {
4093  .emplace(isrListener->getSeq(), isrListener)
4094  .second;
4095 }
4096 
4097 // <-- bool: true=erased, false=was not there
4098 bool
4100 {
4102  return mStreamMaps[sConsensusPhase].erase(uSeq);
4103 }
4104 
4107 {
4109 
4110  subRpcMapType::iterator it = mRpcSubMap.find(strUrl);
4111 
4112  if (it != mRpcSubMap.end())
4113  return it->second;
4114 
4115  return InfoSub::pointer();
4116 }
4117 
4120 {
4122 
4123  mRpcSubMap.emplace(strUrl, rspEntry);
4124 
4125  return rspEntry;
4126 }
4127 
4128 bool
4130 {
4132  auto pInfo = findRpcSub(strUrl);
4133 
4134  if (!pInfo)
4135  return false;
4136 
4137  // check to see if any of the stream maps still hold a weak reference to
4138  // this entry before removing
4139  for (SubMapType const& map : mStreamMaps)
4140  {
4141  if (map.find(pInfo->getSeq()) != map.end())
4142  return false;
4143  }
4144  mRpcSubMap.erase(strUrl);
4145  return true;
4146 }
4147 
4148 #ifndef USE_NEW_BOOK_PAGE
4149 
4150 // NIKB FIXME this should be looked at. There's no reason why this shouldn't
4151 // work, but it demonstrated poor performance.
4152 //
4153 void
4156  Book const& book,
4157  AccountID const& uTakerID,
4158  bool const bProof,
4159  unsigned int iLimit,
4160  Json::Value const& jvMarker,
4161  Json::Value& jvResult)
4162 { // CAUTION: This is the old get book page logic
4163  Json::Value& jvOffers =
4164  (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4165 
4167  const uint256 uBookBase = getBookBase(book);
4168  const uint256 uBookEnd = getQualityNext(uBookBase);
4169  uint256 uTipIndex = uBookBase;
4170 
4171  if (auto stream = m_journal.trace())
4172  {
4173  stream << "getBookPage:" << book;
4174  stream << "getBookPage: uBookBase=" << uBookBase;
4175  stream << "getBookPage: uBookEnd=" << uBookEnd;
4176  stream << "getBookPage: uTipIndex=" << uTipIndex;
4177  }
4178 
4179  ReadView const& view = *lpLedger;
4180 
4181  bool const bGlobalFreeze = isGlobalFrozen(view, book.out.account) ||
4182  isGlobalFrozen(view, book.in.account);
4183 
4184  bool bDone = false;
4185  bool bDirectAdvance = true;
4186 
4187  std::shared_ptr<SLE const> sleOfferDir;
4188  uint256 offerIndex;
4189  unsigned int uBookEntry;
4190  STAmount saDirRate;
4191 
4192  auto const rate = transferRate(view, book.out.account);
4193  auto viewJ = app_.journal("View");
4194 
4195  while (!bDone && iLimit-- > 0)
4196  {
4197  if (bDirectAdvance)
4198  {
4199  bDirectAdvance = false;
4200 
4201  JLOG(m_journal.trace()) << "getBookPage: bDirectAdvance";
4202 
4203  auto const ledgerIndex = view.succ(uTipIndex, uBookEnd);
4204  if (ledgerIndex)
4205  sleOfferDir = view.read(keylet::page(*ledgerIndex));
4206  else
4207  sleOfferDir.reset();
4208 
4209  if (!sleOfferDir)
4210  {
4211  JLOG(m_journal.trace()) << "getBookPage: bDone";
4212  bDone = true;
4213  }
4214  else
4215  {
4216  uTipIndex = sleOfferDir->key();
4217  saDirRate = amountFromQuality(getQuality(uTipIndex));
4218 
4219  cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4220 
4221  JLOG(m_journal.trace())
4222  << "getBookPage: uTipIndex=" << uTipIndex;
4223  JLOG(m_journal.trace())
4224  << "getBookPage: offerIndex=" << offerIndex;
4225  }
4226  }
4227 
4228  if (!bDone)
4229  {
4230  auto sleOffer = view.read(keylet::offer(offerIndex));
4231 
4232  if (sleOffer)
4233  {
4234  auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4235  auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4236  auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4237  STAmount saOwnerFunds;
4238  bool firstOwnerOffer(true);
4239 
4240  if (book.out.account == uOfferOwnerID)
4241  {
4242  // If an offer is selling issuer's own IOUs, it is fully
4243  // funded.
4244  saOwnerFunds = saTakerGets;
4245  }
4246  else if (bGlobalFreeze)
4247  {
4248  // If either asset is globally frozen, consider all offers
4249  // that aren't ours to be totally unfunded
4250  saOwnerFunds.clear(book.out);
4251  }
4252  else
4253  {
4254  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4255  if (umBalanceEntry != umBalance.end())
4256  {
4257  // Found in running balance table.
4258 
4259  saOwnerFunds = umBalanceEntry->second;
4260  firstOwnerOffer = false;
4261  }
4262  else
4263  {
4264  // Did not find balance in table.
4265 
4266  saOwnerFunds = accountHolds(
4267  view,
4268  uOfferOwnerID,
4269  book.out.currency,
4270  book.out.account,
4272  viewJ);
4273 
4274  if (saOwnerFunds < beast::zero)
4275  {
4276  // Treat negative funds as zero.
4277 
4278  saOwnerFunds.clear();
4279  }
4280  }
4281  }
4282 
4283  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4284 
4285  STAmount saTakerGetsFunded;
4286  STAmount saOwnerFundsLimit = saOwnerFunds;
4287  Rate offerRate = parityRate;
4288 
4289  if (rate != parityRate
4290  // Have a tranfer fee.
4291  && uTakerID != book.out.account
4292  // Not taking offers of own IOUs.
4293  && book.out.account != uOfferOwnerID)
4294  // Offer owner not issuing ownfunds
4295  {
4296  // Need to charge a transfer fee to offer owner.
4297  offerRate = rate;
4298  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4299  }
4300 
4301  if (saOwnerFundsLimit >= saTakerGets)
4302  {
4303  // Sufficient funds no shenanigans.
4304  saTakerGetsFunded = saTakerGets;
4305  }
4306  else
4307  {
4308  // Only provide, if not fully funded.
4309 
4310  saTakerGetsFunded = saOwnerFundsLimit;
4311 
4312  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4313  std::min(
4314  saTakerPays,
4315  multiply(
4316  saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4317  .setJson(jvOffer[jss::taker_pays_funded]);
4318  }
4319 
4320  STAmount saOwnerPays = (parityRate == offerRate)
4321  ? saTakerGetsFunded
4322  : std::min(
4323  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4324 
4325  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4326 
4327  // Include all offers funded and unfunded
4328  Json::Value& jvOf = jvOffers.append(jvOffer);
4329  jvOf[jss::quality] = saDirRate.getText();
4330 
4331  if (firstOwnerOffer)
4332  jvOf[jss::owner_funds] = saOwnerFunds.getText();
4333  }
4334  else
4335  {
4336  JLOG(m_journal.warn()) << "Missing offer";
4337  }
4338 
4339  if (!cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4340  {
4341  bDirectAdvance = true;
4342  }
4343  else
4344  {
4345  JLOG(m_journal.trace())
4346  << "getBookPage: offerIndex=" << offerIndex;
4347  }
4348  }
4349  }
4350 
4351  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4352  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4353 }
4354 
4355 #else
4356 
4357 // This is the new code that uses the book iterators
4358 // It has temporarily been disabled
4359 
4360 void
4363  Book const& book,
4364  AccountID const& uTakerID,
4365  bool const bProof,
4366  unsigned int iLimit,
4367  Json::Value const& jvMarker,
4368  Json::Value& jvResult)
4369 {
4370  auto& jvOffers = (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4371 
4373 
4374  MetaView lesActive(lpLedger, tapNONE, true);
4375  OrderBookIterator obIterator(lesActive, book);
4376 
4377  auto const rate = transferRate(lesActive, book.out.account);
4378 
4379  const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.out.account) ||
4380  lesActive.isGlobalFrozen(book.in.account);
4381 
4382  while (iLimit-- > 0 && obIterator.nextOffer())
4383  {
4384  SLE::pointer sleOffer = obIterator.getCurrentOffer();
4385  if (sleOffer)
4386  {
4387  auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4388  auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4389  auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4390  STAmount saDirRate = obIterator.getCurrentRate();
4391  STAmount saOwnerFunds;
4392 
4393  if (book.out.account == uOfferOwnerID)
4394  {
4395  // If offer is selling issuer's own IOUs, it is fully funded.
4396  saOwnerFunds = saTakerGets;
4397  }
4398  else if (bGlobalFreeze)
4399  {
4400  // If either asset is globally frozen, consider all offers
4401  // that aren't ours to be totally unfunded
4402  saOwnerFunds.clear(book.out);
4403  }
4404  else
4405  {
4406  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4407 
4408  if (umBalanceEntry != umBalance.end())
4409  {
4410  // Found in running balance table.
4411 
4412  saOwnerFunds = umBalanceEntry->second;
4413  }
4414  else
4415  {
4416  // Did not find balance in table.
4417 
4418  saOwnerFunds = lesActive.accountHolds(
4419  uOfferOwnerID,
4420  book.out.currency,
4421  book.out.account,
4423 
4424  if (saOwnerFunds.isNegative())
4425  {
4426  // Treat negative funds as zero.
4427 
4428  saOwnerFunds.zero();
4429  }
4430  }
4431  }
4432 
4433  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4434 
4435  STAmount saTakerGetsFunded;
4436  STAmount saOwnerFundsLimit = saOwnerFunds;
4437  Rate offerRate = parityRate;
4438 
4439  if (rate != parityRate
4440  // Have a tranfer fee.
4441  && uTakerID != book.out.account
4442  // Not taking offers of own IOUs.
4443  && book.out.account != uOfferOwnerID)
4444  // Offer owner not issuing ownfunds
4445  {
4446  // Need to charge a transfer fee to offer owner.
4447  offerRate = rate;
4448  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4449  }
4450 
4451  if (saOwnerFundsLimit >= saTakerGets)
4452  {
4453  // Sufficient funds no shenanigans.
4454  saTakerGetsFunded = saTakerGets;
4455  }
4456  else
4457  {
4458  // Only provide, if not fully funded.
4459  saTakerGetsFunded = saOwnerFundsLimit;
4460 
4461  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4462 
4463  // TOOD(tom): The result of this expression is not used - what's
4464  // going on here?
4465  std::min(
4466  saTakerPays,
4467  multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4468  .setJson(jvOffer[jss::taker_pays_funded]);
4469  }
4470 
4471  STAmount saOwnerPays = (parityRate == offerRate)
4472  ? saTakerGetsFunded
4473  : std::min(
4474  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4475 
4476  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4477 
4478  if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4479  {
4480  // Only provide funded offers and offers of the taker.
4481  Json::Value& jvOf = jvOffers.append(jvOffer);
4482  jvOf[jss::quality] = saDirRate.getText();
4483  }
4484  }
4485  }
4486 
4487  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4488  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4489 }
4490 
4491 #endif
4492 
4493 inline void
4495 {
4496  auto [counters, mode, start, initialSync] = accounting_.getCounterData();
4497  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4498  std::chrono::steady_clock::now() - start);
4499  counters[static_cast<std::size_t>(mode)].dur += current;
4500 
4503  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4504  .dur.count());
4506  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4507  .dur.count());
4509  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].dur.count());
4511  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4512  .dur.count());
4514  counters[static_cast<std::size_t>(OperatingMode::FULL)].dur.count());
4515 
4517  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4518  .transitions);
4520  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4521  .transitions);
4523  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].transitions);
4525  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4526  .transitions);
4528  counters[static_cast<std::size_t>(OperatingMode::FULL)].transitions);
4529 }
4530 
4531 void
4533 {
4534  auto now = std::chrono::steady_clock::now();
4535 
4536  std::lock_guard lock(mutex_);
4537  ++counters_[static_cast<std::size_t>(om)].transitions;
4538  if (om == OperatingMode::FULL &&
4539  counters_[static_cast<std::size_t>(om)].transitions == 1)
4540  {
4541  initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4542  now - processStart_)
4543  .count();
4544  }
4545  counters_[static_cast<std::size_t>(mode_)].dur +=
4546  std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4547 
4548  mode_ = om;
4549  start_ = now;
4550 }
4551 
4552 void
4554 {
4555  auto [counters, mode, start, initialSync] = getCounterData();
4556  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4557  std::chrono::steady_clock::now() - start);
4558  counters[static_cast<std::size_t>(mode)].dur += current;
4559 
4560  obj[jss::state_accounting] = Json::objectValue;
4561  for (std::size_t i = static_cast<std::size_t>(OperatingMode::DISCONNECTED);
4562  i <= static_cast<std::size_t>(OperatingMode::FULL);
4563  ++i)
4564  {
4565  obj[jss::state_accounting][states_[i]] = Json::objectValue;
4566  auto& state = obj[jss::state_accounting][states_[i]];
4567  state[jss::transitions] = std::to_string(counters[i].transitions);
4568  state[jss::duration_us] = std::to_string(counters[i].dur.count());
4569  }
4570  obj[jss::server_state_duration_us] = std::to_string(current.count());
4571  if (initialSync)
4572  obj[jss::initial_sync_duration_us] = std::to_string(initialSync);
4573 }
4574 
4575 //------------------------------------------------------------------------------
4576 
4579  Application& app,
4580  NetworkOPs::clock_type& clock,
4581  bool standalone,
4582  std::size_t minPeerCount,
4583  bool startvalid,
4584  JobQueue& job_queue,
4585  LedgerMaster& ledgerMaster,
4586  ValidatorKeys const& validatorKeys,
4587  boost::asio::io_service& io_svc,
4588  beast::Journal journal,
4589  beast::insight::Collector::ptr const& collector)
4590 {
4591  return std::make_unique<NetworkOPsImp>(
4592  app,
4593  clock,
4594  standalone,
4595  minPeerCount,
4596  startvalid,
4597  job_queue,
4598  ledgerMaster,
4599  validatorKeys,
4600  io_svc,
4601  journal,
4602  collector);
4603 }
4604 
4605 } // namespace ripple
ripple::SQLiteDatabase
Definition: SQLiteDatabase.h:27
ripple::NetworkOPsImp::forwardManifest
void forwardManifest(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2761
ripple::NetworkOPsImp::unsubValidations
bool unsubValidations(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4063
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:4047
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:4099
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:3134
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:4056
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:4553
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:4494
ripple::NetworkOPsImp::subPeerStatus
bool subPeerStatus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4071
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:2243
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:3257
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:4129
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:2272
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:2710
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:3829
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:4578
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:2799
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::NetworkOPsImp::pubLedger
void pubLedger(std::shared_ptr< ReadView const > const &lpAccepted) override
Definition: NetworkOPs.cpp:2867
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:4021
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:2781
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:4119
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
ripple::NetworkOPsImp::forwardValidation
void forwardValidation(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2741
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:3728
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:2979
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:3408
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:3364
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:4039
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:3079
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:3955
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:3929
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:4011
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:3939
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:3327
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:2999
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:4003
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:3947
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:3013
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:2673
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:3870
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:3879
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:4154
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:2214
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:3899
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:3772
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:3965
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:3021
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:3008
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:4029
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:2679
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:2295
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:3973
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:3860
ripple::NetworkOPsImp::subConsensus
bool subConsensus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4089
ripple::NetworkOPsImp::getConsensusInfo
Json::Value getConsensusInfo() override
Definition: NetworkOPs.cpp:2289
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:4532
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:3380
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:3818
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:4081
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:4106
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:2667
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)