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