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