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