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)
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  {
2459  if (auto const localPubKey = app_.validators().localPublicKey();
2460  localPubKey && app_.getValidationPublicKey())
2461  {
2462  info[jss::pubkey_validator] =
2463  toBase58(TokenType::NodePublic, localPubKey.value());
2464  }
2465  else
2466  {
2467  info[jss::pubkey_validator] = "none";
2468  }
2469  }
2470 
2471  if (counters)
2472  {
2473  info[jss::counters] = app_.getPerfLog().countersJson();
2474 
2475  Json::Value nodestore(Json::objectValue);
2476  if (app_.getShardStore())
2477  app_.getShardStore()->getCountsJson(nodestore);
2478  else
2479  app_.getNodeStore().getCountsJson(nodestore);
2480  info[jss::counters][jss::nodestore] = nodestore;
2481  info[jss::current_activities] = app_.getPerfLog().currentJson();
2482  }
2483 
2484  info[jss::pubkey_node] =
2486 
2487  info[jss::complete_ledgers] = app_.getLedgerMaster().getCompleteLedgers();
2488 
2489  if (amendmentBlocked_)
2490  info[jss::amendment_blocked] = true;
2491 
2492  auto const fp = m_ledgerMaster.getFetchPackCacheSize();
2493 
2494  if (fp != 0)
2495  info[jss::fetch_pack] = Json::UInt(fp);
2496 
2497  if (!app_.config().reporting())
2498  info[jss::peers] = Json::UInt(app_.overlay().size());
2499 
2500  Json::Value lastClose = Json::objectValue;
2501  lastClose[jss::proposers] = Json::UInt(mConsensus.prevProposers());
2502 
2503  if (human)
2504  {
2505  lastClose[jss::converge_time_s] =
2507  }
2508  else
2509  {
2510  lastClose[jss::converge_time] =
2512  }
2513 
2514  info[jss::last_close] = lastClose;
2515 
2516  // info[jss::consensus] = mConsensus.getJson();
2517 
2518  if (admin)
2519  info[jss::load] = m_job_queue.getJson();
2520 
2521  if (!app_.config().reporting())
2522  {
2523  if (auto const netid = app_.overlay().networkID())
2524  info[jss::network_id] = static_cast<Json::UInt>(*netid);
2525 
2526  auto const escalationMetrics =
2528 
2529  auto const loadFactorServer = app_.getFeeTrack().getLoadFactor();
2530  auto const loadBaseServer = app_.getFeeTrack().getLoadBase();
2531  /* Scale the escalated fee level to unitless "load factor".
2532  In practice, this just strips the units, but it will continue
2533  to work correctly if either base value ever changes. */
2534  auto const loadFactorFeeEscalation =
2535  mulDiv(
2536  escalationMetrics.openLedgerFeeLevel,
2537  loadBaseServer,
2538  escalationMetrics.referenceFeeLevel)
2539  .value_or(ripple::muldiv_max);
2540 
2541  auto const loadFactor = std::max(
2542  safe_cast<std::uint64_t>(loadFactorServer),
2543  loadFactorFeeEscalation);
2544 
2545  if (!human)
2546  {
2547  info[jss::load_base] = loadBaseServer;
2548  info[jss::load_factor] = trunc32(loadFactor);
2549  info[jss::load_factor_server] = loadFactorServer;
2550 
2551  /* Json::Value doesn't support uint64, so clamp to max
2552  uint32 value. This is mostly theoretical, since there
2553  probably isn't enough extant XRP to drive the factor
2554  that high.
2555  */
2556  info[jss::load_factor_fee_escalation] =
2557  escalationMetrics.openLedgerFeeLevel.jsonClipped();
2558  info[jss::load_factor_fee_queue] =
2559  escalationMetrics.minProcessingFeeLevel.jsonClipped();
2560  info[jss::load_factor_fee_reference] =
2561  escalationMetrics.referenceFeeLevel.jsonClipped();
2562  }
2563  else
2564  {
2565  info[jss::load_factor] =
2566  static_cast<double>(loadFactor) / loadBaseServer;
2567 
2568  if (loadFactorServer != loadFactor)
2569  info[jss::load_factor_server] =
2570  static_cast<double>(loadFactorServer) / loadBaseServer;
2571 
2572  if (admin)
2573  {
2575  if (fee != loadBaseServer)
2576  info[jss::load_factor_local] =
2577  static_cast<double>(fee) / loadBaseServer;
2578  fee = app_.getFeeTrack().getRemoteFee();
2579  if (fee != loadBaseServer)
2580  info[jss::load_factor_net] =
2581  static_cast<double>(fee) / loadBaseServer;
2582  fee = app_.getFeeTrack().getClusterFee();
2583  if (fee != loadBaseServer)
2584  info[jss::load_factor_cluster] =
2585  static_cast<double>(fee) / loadBaseServer;
2586  }
2587  if (escalationMetrics.openLedgerFeeLevel !=
2588  escalationMetrics.referenceFeeLevel &&
2589  (admin || loadFactorFeeEscalation != loadFactor))
2590  info[jss::load_factor_fee_escalation] =
2591  escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2592  escalationMetrics.referenceFeeLevel);
2593  if (escalationMetrics.minProcessingFeeLevel !=
2594  escalationMetrics.referenceFeeLevel)
2595  info[jss::load_factor_fee_queue] =
2596  escalationMetrics.minProcessingFeeLevel
2597  .decimalFromReference(
2598  escalationMetrics.referenceFeeLevel);
2599  }
2600  }
2601 
2602  bool valid = false;
2603  auto lpClosed = m_ledgerMaster.getValidatedLedger();
2604 
2605  if (lpClosed)
2606  valid = true;
2607  else if (!app_.config().reporting())
2608  lpClosed = m_ledgerMaster.getClosedLedger();
2609 
2610  if (lpClosed)
2611  {
2612  XRPAmount const baseFee = lpClosed->fees().base;
2614  l[jss::seq] = Json::UInt(lpClosed->info().seq);
2615  l[jss::hash] = to_string(lpClosed->info().hash);
2616 
2617  if (!human)
2618  {
2619  l[jss::base_fee] = baseFee.jsonClipped();
2620  l[jss::reserve_base] =
2621  lpClosed->fees().accountReserve(0).jsonClipped();
2622  l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2623  l[jss::close_time] = Json::Value::UInt(
2624  lpClosed->info().closeTime.time_since_epoch().count());
2625  }
2626  else
2627  {
2628  l[jss::base_fee_xrp] = baseFee.decimalXRP();
2629  l[jss::reserve_base_xrp] =
2630  lpClosed->fees().accountReserve(0).decimalXRP();
2631  l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2632 
2633  if (auto const closeOffset = app_.timeKeeper().closeOffset();
2634  std::abs(closeOffset.count()) >= 60)
2635  l[jss::close_time_offset] =
2636  static_cast<std::uint32_t>(closeOffset.count());
2637 
2638 #if RIPPLED_REPORTING
2639  std::int64_t const dbAge =
2641  l[jss::age] = Json::UInt(dbAge);
2642 #else
2643  constexpr std::chrono::seconds highAgeThreshold{1000000};
2645  {
2646  auto const age = m_ledgerMaster.getValidatedLedgerAge();
2647  l[jss::age] =
2648  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2649  }
2650  else
2651  {
2652  auto lCloseTime = lpClosed->info().closeTime;
2653  auto closeTime = app_.timeKeeper().closeTime();
2654  if (lCloseTime <= closeTime)
2655  {
2656  using namespace std::chrono_literals;
2657  auto age = closeTime - lCloseTime;
2658  l[jss::age] =
2659  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2660  }
2661  }
2662 #endif
2663  }
2664 
2665  if (valid)
2666  info[jss::validated_ledger] = l;
2667  else
2668  info[jss::closed_ledger] = l;
2669 
2670  auto lpPublished = m_ledgerMaster.getPublishedLedger();
2671  if (!lpPublished)
2672  info[jss::published_ledger] = "none";
2673  else if (lpPublished->info().seq != lpClosed->info().seq)
2674  info[jss::published_ledger] = lpPublished->info().seq;
2675  }
2676 
2677  accounting_.json(info);
2678  info[jss::uptime] = UptimeClock::now().time_since_epoch().count();
2679  if (!app_.config().reporting())
2680  {
2681  info[jss::jq_trans_overflow] =
2683  info[jss::peer_disconnects] =
2685  info[jss::peer_disconnects_resources] =
2687  }
2688  else
2689  {
2690  info["reporting"] = app_.getReportingETL().getInfo();
2691  }
2692 
2693  // This array must be sorted in increasing order.
2694  static constexpr std::array<std::string_view, 7> protocols{
2695  "http", "https", "peer", "ws", "ws2", "wss", "wss2"};
2696  static_assert(std::is_sorted(std::begin(protocols), std::end(protocols)));
2697  {
2699  for (auto const& port : app_.getServerHandler().setup().ports)
2700  {
2701  // Don't publish admin ports for non-admin users
2702  if (!admin &&
2703  !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() &&
2704  port.admin_user.empty() && port.admin_password.empty()))
2705  continue;
2708  std::begin(port.protocol),
2709  std::end(port.protocol),
2710  std::begin(protocols),
2711  std::end(protocols),
2712  std::back_inserter(proto));
2713  if (!proto.empty())
2714  {
2715  auto& jv = ports.append(Json::Value(Json::objectValue));
2716  jv[jss::port] = std::to_string(port.port);
2717  jv[jss::protocol] = Json::Value{Json::arrayValue};
2718  for (auto const& p : proto)
2719  jv[jss::protocol].append(p);
2720  }
2721  }
2722 
2723  if (app_.config().exists(SECTION_PORT_GRPC))
2724  {
2725  auto const& grpcSection = app_.config().section(SECTION_PORT_GRPC);
2726  auto const optPort = grpcSection.get("port");
2727  if (optPort && grpcSection.get("ip"))
2728  {
2729  auto& jv = ports.append(Json::Value(Json::objectValue));
2730  jv[jss::port] = *optPort;
2731  jv[jss::protocol] = Json::Value{Json::arrayValue};
2732  jv[jss::protocol].append("grpc");
2733  }
2734  }
2735  info[jss::ports] = std::move(ports);
2736  }
2737 
2738  return info;
2739 }
2740 
2741 void
2743 {
2745 }
2746 
2749 {
2750  return app_.getInboundLedgers().getInfo();
2751 }
2752 
2753 void
2755  std::shared_ptr<ReadView const> const& ledger,
2756  std::shared_ptr<STTx const> const& transaction,
2757  TER result)
2758 {
2759  MultiApiJson jvObj =
2760  transJson(transaction, result, false, ledger, std::nullopt);
2761 
2762  {
2764 
2765  auto it = mStreamMaps[sRTTransactions].begin();
2766  while (it != mStreamMaps[sRTTransactions].end())
2767  {
2768  InfoSub::pointer p = it->second.lock();
2769 
2770  if (p)
2771  {
2772  p->send(
2773  jvObj.select(apiVersionSelector(p->getApiVersion())), true);
2774  ++it;
2775  }
2776  else
2777  {
2778  it = mStreamMaps[sRTTransactions].erase(it);
2779  }
2780  }
2781  }
2782 
2783  pubProposedAccountTransaction(ledger, transaction, result);
2784 }
2785 
2786 void
2788 {
2789  // reporting does not forward validated transactions
2790  // validated transactions will be published to the proper streams when the
2791  // etl process writes a validated ledger
2792  if (jvObj[jss::validated].asBool())
2793  return;
2794  {
2796 
2797  auto it = mStreamMaps[sRTTransactions].begin();
2798  while (it != mStreamMaps[sRTTransactions].end())
2799  {
2800  InfoSub::pointer p = it->second.lock();
2801 
2802  if (p)
2803  {
2804  p->send(jvObj, true);
2805  ++it;
2806  }
2807  else
2808  {
2809  it = mStreamMaps[sRTTransactions].erase(it);
2810  }
2811  }
2812  }
2813 
2815 }
2816 
2817 void
2819 {
2821 
2822  for (auto i = mStreamMaps[sValidations].begin();
2823  i != mStreamMaps[sValidations].end();)
2824  {
2825  if (auto p = i->second.lock())
2826  {
2827  p->send(jvObj, true);
2828  ++i;
2829  }
2830  else
2831  {
2832  i = mStreamMaps[sValidations].erase(i);
2833  }
2834  }
2835 }
2836 
2837 void
2839 {
2841 
2842  for (auto i = mStreamMaps[sManifests].begin();
2843  i != mStreamMaps[sManifests].end();)
2844  {
2845  if (auto p = i->second.lock())
2846  {
2847  p->send(jvObj, true);
2848  ++i;
2849  }
2850  else
2851  {
2852  i = mStreamMaps[sManifests].erase(i);
2853  }
2854  }
2855 }
2856 
2857 static void
2859 {
2860  for (auto& jv : jvObj)
2861  {
2862  if (jv.isObject())
2863  {
2864  getAccounts(jv, accounts);
2865  }
2866  else if (jv.isString())
2867  {
2868  auto account = RPC::accountFromStringStrict(jv.asString());
2869  if (account)
2870  accounts.push_back(*account);
2871  }
2872  }
2873 }
2874 
2875 void
2877 {
2879  int iProposed = 0;
2880  // check if there are any subscribers before attempting to parse the JSON
2881  {
2883 
2884  if (mSubRTAccount.empty())
2885  return;
2886  }
2887 
2888  // parse the JSON outside of the lock
2889  std::vector<AccountID> accounts;
2890  if (jvObj.isMember(jss::transaction))
2891  {
2892  try
2893  {
2894  getAccounts(jvObj[jss::transaction], accounts);
2895  }
2896  catch (...)
2897  {
2898  JLOG(m_journal.debug())
2899  << __func__ << " : "
2900  << "error parsing json for accounts affected";
2901  return;
2902  }
2903  }
2904  {
2906 
2907  if (!mSubRTAccount.empty())
2908  {
2909  for (auto const& affectedAccount : accounts)
2910  {
2911  auto simiIt = mSubRTAccount.find(affectedAccount);
2912  if (simiIt != mSubRTAccount.end())
2913  {
2914  auto it = simiIt->second.begin();
2915 
2916  while (it != simiIt->second.end())
2917  {
2918  InfoSub::pointer p = it->second.lock();
2919 
2920  if (p)
2921  {
2922  notify.insert(p);
2923  ++it;
2924  ++iProposed;
2925  }
2926  else
2927  it = simiIt->second.erase(it);
2928  }
2929  }
2930  }
2931  }
2932  }
2933  JLOG(m_journal.trace()) << "forwardProposedAccountTransaction:"
2934  << " iProposed=" << iProposed;
2935 
2936  if (!notify.empty())
2937  {
2938  for (InfoSub::ref isrListener : notify)
2939  isrListener->send(jvObj, true);
2940  }
2941 }
2942 
2943 void
2945 {
2946  // Ledgers are published only when they acquire sufficient validations
2947  // Holes are filled across connection loss or other catastrophe
2948 
2949  std::shared_ptr<AcceptedLedger> alpAccepted =
2950  app_.getAcceptedLedgerCache().fetch(lpAccepted->info().hash);
2951  if (!alpAccepted)
2952  {
2953  alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted, app_);
2954  app_.getAcceptedLedgerCache().canonicalize_replace_client(
2955  lpAccepted->info().hash, alpAccepted);
2956  }
2957 
2958  assert(alpAccepted->getLedger().get() == lpAccepted.get());
2959 
2960  {
2961  JLOG(m_journal.debug())
2962  << "Publishing ledger " << lpAccepted->info().seq << " "
2963  << lpAccepted->info().hash;
2964 
2966 
2967  if (!mStreamMaps[sLedger].empty())
2968  {
2970 
2971  jvObj[jss::type] = "ledgerClosed";
2972  jvObj[jss::ledger_index] = lpAccepted->info().seq;
2973  jvObj[jss::ledger_hash] = to_string(lpAccepted->info().hash);
2974  jvObj[jss::ledger_time] = Json::Value::UInt(
2975  lpAccepted->info().closeTime.time_since_epoch().count());
2976 
2977  if (!lpAccepted->rules().enabled(featureXRPFees))
2978  jvObj[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
2979  jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2980  jvObj[jss::reserve_base] =
2981  lpAccepted->fees().accountReserve(0).jsonClipped();
2982  jvObj[jss::reserve_inc] =
2983  lpAccepted->fees().increment.jsonClipped();
2984 
2985  jvObj[jss::txn_count] = Json::UInt(alpAccepted->size());
2986 
2988  {
2989  jvObj[jss::validated_ledgers] =
2991  }
2992 
2993  auto it = mStreamMaps[sLedger].begin();
2994  while (it != mStreamMaps[sLedger].end())
2995  {
2996  InfoSub::pointer p = it->second.lock();
2997  if (p)
2998  {
2999  p->send(jvObj, true);
3000  ++it;
3001  }
3002  else
3003  it = mStreamMaps[sLedger].erase(it);
3004  }
3005  }
3006 
3007  if (!mStreamMaps[sBookChanges].empty())
3008  {
3009  Json::Value jvObj = ripple::RPC::computeBookChanges(lpAccepted);
3010 
3011  auto it = mStreamMaps[sBookChanges].begin();
3012  while (it != mStreamMaps[sBookChanges].end())
3013  {
3014  InfoSub::pointer p = it->second.lock();
3015  if (p)
3016  {
3017  p->send(jvObj, true);
3018  ++it;
3019  }
3020  else
3021  it = mStreamMaps[sBookChanges].erase(it);
3022  }
3023  }
3024 
3025  {
3026  static bool firstTime = true;
3027  if (firstTime)
3028  {
3029  // First validated ledger, start delayed SubAccountHistory
3030  firstTime = false;
3031  for (auto& outer : mSubAccountHistory)
3032  {
3033  for (auto& inner : outer.second)
3034  {
3035  auto& subInfo = inner.second;
3036  if (subInfo.index_->separationLedgerSeq_ == 0)
3037  {
3039  alpAccepted->getLedger(), subInfo);
3040  }
3041  }
3042  }
3043  }
3044  }
3045  }
3046 
3047  // Don't lock since pubAcceptedTransaction is locking.
3048  for (auto const& accTx : *alpAccepted)
3049  {
3050  JLOG(m_journal.trace()) << "pubAccepted: " << accTx->getJson();
3052  lpAccepted, *accTx, accTx == *(--alpAccepted->end()));
3053  }
3054 }
3055 
3056 void
3058 {
3059  if (app_.config().reporting())
3060  return;
3061  ServerFeeSummary f{
3062  app_.openLedger().current()->fees().base,
3064  app_.getFeeTrack()};
3065 
3066  // only schedule the job if something has changed
3067  if (f != mLastFeeSummary)
3068  {
3070  jtCLIENT_FEE_CHANGE, "reportFeeChange->pubServer", [this]() {
3071  pubServer();
3072  });
3073  }
3074 }
3075 
3076 void
3078 {
3081  "reportConsensusStateChange->pubConsensus",
3082  [this, phase]() { pubConsensus(phase); });
3083 }
3084 
3085 inline void
3087 {
3088  m_localTX->sweep(view);
3089 }
3090 inline std::size_t
3092 {
3093  return m_localTX->size();
3094 }
3095 
3096 // This routine should only be used to publish accepted or validated
3097 // transactions.
3100  std::shared_ptr<STTx const> const& transaction,
3101  TER result,
3102  bool validated,
3103  std::shared_ptr<ReadView const> const& ledger,
3105 {
3107  std::string sToken;
3108  std::string sHuman;
3109 
3110  transResultInfo(result, sToken, sHuman);
3111 
3112  jvObj[jss::type] = "transaction";
3113  // NOTE jvObj is not a finished object for either API version. After
3114  // it's populated, we need to finish it for a specific API version. This is
3115  // done in a loop, near the end of this function.
3116  jvObj[jss::transaction] =
3117  transaction->getJson(JsonOptions::disable_API_prior_V2, false);
3118 
3119  if (meta)
3120  {
3121  jvObj[jss::meta] = meta->get().getJson(JsonOptions::none);
3123  jvObj[jss::meta], *ledger, transaction, meta->get());
3124  }
3125 
3126  if (!ledger->open())
3127  jvObj[jss::ledger_hash] = to_string(ledger->info().hash);
3128 
3129  if (validated)
3130  {
3131  jvObj[jss::ledger_index] = ledger->info().seq;
3132  jvObj[jss::transaction][jss::date] =
3133  ledger->info().closeTime.time_since_epoch().count();
3134  jvObj[jss::validated] = true;
3135  jvObj[jss::close_time_iso] = to_string_iso(ledger->info().closeTime);
3136 
3137  // WRITEME: Put the account next seq here
3138  }
3139  else
3140  {
3141  jvObj[jss::validated] = false;
3142  jvObj[jss::ledger_current_index] = ledger->info().seq;
3143  }
3144 
3145  jvObj[jss::status] = validated ? "closed" : "proposed";
3146  jvObj[jss::engine_result] = sToken;
3147  jvObj[jss::engine_result_code] = result;
3148  jvObj[jss::engine_result_message] = sHuman;
3149 
3150  if (transaction->getTxnType() == ttOFFER_CREATE)
3151  {
3152  auto const account = transaction->getAccountID(sfAccount);
3153  auto const amount = transaction->getFieldAmount(sfTakerGets);
3154 
3155  // If the offer create is not self funded then add the owner balance
3156  if (account != amount.issue().account)
3157  {
3158  auto const ownerFunds = accountFunds(
3159  *ledger,
3160  account,
3161  amount,
3163  app_.journal("View"));
3164  jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3165  }
3166  }
3167 
3168  std::string const hash = to_string(transaction->getTransactionID());
3169  MultiApiJson multiObj{jvObj};
3170  visit<RPC::apiMinimumSupportedVersion, RPC::apiMaximumValidVersion>(
3171  multiObj, //
3172  [&](Json::Value& jvTx, unsigned int apiVersion) {
3174  jvTx[jss::transaction], transaction->getTxnType(), apiVersion);
3175 
3176  if (apiVersion > 1)
3177  {
3178  jvTx[jss::tx_json] = jvTx.removeMember(jss::transaction);
3179  jvTx[jss::hash] = hash;
3180  }
3181  else
3182  {
3183  jvTx[jss::transaction][jss::hash] = hash;
3184  }
3185  });
3186 
3187  return multiObj;
3188 }
3189 
3190 void
3192  std::shared_ptr<ReadView const> const& ledger,
3193  const AcceptedLedgerTx& transaction,
3194  bool last)
3195 {
3196  auto const& stTxn = transaction.getTxn();
3197 
3198  // Create two different Json objects, for different API versions
3199  auto const metaRef = std::ref(transaction.getMeta());
3200  auto const trResult = transaction.getResult();
3201  MultiApiJson jvObj = transJson(stTxn, trResult, true, ledger, metaRef);
3202 
3203  {
3205 
3206  auto it = mStreamMaps[sTransactions].begin();
3207  while (it != mStreamMaps[sTransactions].end())
3208  {
3209  InfoSub::pointer p = it->second.lock();
3210 
3211  if (p)
3212  {
3213  p->send(
3214  jvObj.select(apiVersionSelector(p->getApiVersion())), true);
3215  ++it;
3216  }
3217  else
3218  it = mStreamMaps[sTransactions].erase(it);
3219  }
3220 
3221  it = mStreamMaps[sRTTransactions].begin();
3222 
3223  while (it != mStreamMaps[sRTTransactions].end())
3224  {
3225  InfoSub::pointer p = it->second.lock();
3226 
3227  if (p)
3228  {
3229  p->send(
3230  jvObj.select(apiVersionSelector(p->getApiVersion())), true);
3231  ++it;
3232  }
3233  else
3234  it = mStreamMaps[sRTTransactions].erase(it);
3235  }
3236  }
3237 
3238  if (transaction.getResult() == tesSUCCESS)
3239  app_.getOrderBookDB().processTxn(ledger, transaction, jvObj);
3240 
3241  pubAccountTransaction(ledger, transaction, last);
3242 }
3243 
3244 void
3246  std::shared_ptr<ReadView const> const& ledger,
3247  AcceptedLedgerTx const& transaction,
3248  bool last)
3249 {
3251  int iProposed = 0;
3252  int iAccepted = 0;
3253 
3254  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3255  auto const currLedgerSeq = ledger->seq();
3256  {
3258 
3259  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3261  {
3262  for (auto const& affectedAccount : transaction.getAffected())
3263  {
3264  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3265  simiIt != mSubRTAccount.end())
3266  {
3267  auto it = simiIt->second.begin();
3268 
3269  while (it != simiIt->second.end())
3270  {
3271  InfoSub::pointer p = it->second.lock();
3272 
3273  if (p)
3274  {
3275  notify.insert(p);
3276  ++it;
3277  ++iProposed;
3278  }
3279  else
3280  it = simiIt->second.erase(it);
3281  }
3282  }
3283 
3284  if (auto simiIt = mSubAccount.find(affectedAccount);
3285  simiIt != mSubAccount.end())
3286  {
3287  auto it = simiIt->second.begin();
3288  while (it != simiIt->second.end())
3289  {
3290  InfoSub::pointer p = it->second.lock();
3291 
3292  if (p)
3293  {
3294  notify.insert(p);
3295  ++it;
3296  ++iAccepted;
3297  }
3298  else
3299  it = simiIt->second.erase(it);
3300  }
3301  }
3302 
3303  if (auto histoIt = mSubAccountHistory.find(affectedAccount);
3304  histoIt != mSubAccountHistory.end())
3305  {
3306  auto& subs = histoIt->second;
3307  auto it = subs.begin();
3308  while (it != subs.end())
3309  {
3310  SubAccountHistoryInfoWeak const& info = it->second;
3311  if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3312  {
3313  ++it;
3314  continue;
3315  }
3316 
3317  if (auto isSptr = info.sinkWptr_.lock(); isSptr)
3318  {
3319  accountHistoryNotify.emplace_back(
3320  SubAccountHistoryInfo{isSptr, info.index_});
3321  ++it;
3322  }
3323  else
3324  {
3325  it = subs.erase(it);
3326  }
3327  }
3328  if (subs.empty())
3329  mSubAccountHistory.erase(histoIt);
3330  }
3331  }
3332  }
3333  }
3334 
3335  JLOG(m_journal.trace())
3336  << "pubAccountTransaction: "
3337  << "proposed=" << iProposed << ", accepted=" << iAccepted;
3338 
3339  if (!notify.empty() || !accountHistoryNotify.empty())
3340  {
3341  auto const& stTxn = transaction.getTxn();
3342 
3343  // Create two different Json objects, for different API versions
3344  auto const metaRef = std::ref(transaction.getMeta());
3345  auto const trResult = transaction.getResult();
3346  MultiApiJson jvObj = transJson(stTxn, trResult, true, ledger, metaRef);
3347 
3348  for (InfoSub::ref isrListener : notify)
3349  {
3350  isrListener->send(
3351  jvObj.select(apiVersionSelector(isrListener->getApiVersion())),
3352  true);
3353  }
3354 
3355  if (last)
3356  jvObj.set(jss::account_history_boundary, true);
3357 
3358  assert(
3359  jvObj.isMember(jss::account_history_tx_stream) ==
3360  MultiApiJson::none);
3361  for (auto& info : accountHistoryNotify)
3362  {
3363  auto& index = info.index_;
3364  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3365  jvObj.set(jss::account_history_tx_first, true);
3366 
3367  jvObj.set(jss::account_history_tx_index, index->forwardTxIndex_++);
3368 
3369  info.sink_->send(
3370  jvObj.select(apiVersionSelector(info.sink_->getApiVersion())),
3371  true);
3372  }
3373  }
3374 }
3375 
3376 void
3378  std::shared_ptr<ReadView const> const& ledger,
3379  std::shared_ptr<STTx const> const& tx,
3380  TER result)
3381 {
3383  int iProposed = 0;
3384 
3385  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3386 
3387  {
3389 
3390  if (mSubRTAccount.empty())
3391  return;
3392 
3393  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3395  {
3396  for (auto const& affectedAccount : tx->getMentionedAccounts())
3397  {
3398  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3399  simiIt != mSubRTAccount.end())
3400  {
3401  auto it = simiIt->second.begin();
3402 
3403  while (it != simiIt->second.end())
3404  {
3405  InfoSub::pointer p = it->second.lock();
3406 
3407  if (p)
3408  {
3409  notify.insert(p);
3410  ++it;
3411  ++iProposed;
3412  }
3413  else
3414  it = simiIt->second.erase(it);
3415  }
3416  }
3417  }
3418  }
3419  }
3420 
3421  JLOG(m_journal.trace()) << "pubProposedAccountTransaction: " << iProposed;
3422 
3423  if (!notify.empty() || !accountHistoryNotify.empty())
3424  {
3425  // Create two different Json objects, for different API versions
3426  MultiApiJson jvObj = transJson(tx, result, false, ledger, std::nullopt);
3427 
3428  for (InfoSub::ref isrListener : notify)
3429  isrListener->send(
3430  jvObj.select(apiVersionSelector(isrListener->getApiVersion())),
3431  true);
3432 
3433  assert(
3434  jvObj.isMember(jss::account_history_tx_stream) ==
3435  MultiApiJson::none);
3436  for (auto& info : accountHistoryNotify)
3437  {
3438  auto& index = info.index_;
3439  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3440  jvObj.set(jss::account_history_tx_first, true);
3441  jvObj.set(jss::account_history_tx_index, index->forwardTxIndex_++);
3442  info.sink_->send(
3443  jvObj.select(apiVersionSelector(info.sink_->getApiVersion())),
3444  true);
3445  }
3446  }
3447 }
3448 
3449 //
3450 // Monitoring
3451 //
3452 
3453 void
3455  InfoSub::ref isrListener,
3456  hash_set<AccountID> const& vnaAccountIDs,
3457  bool rt)
3458 {
3459  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3460 
3461  for (auto const& naAccountID : vnaAccountIDs)
3462  {
3463  JLOG(m_journal.trace())
3464  << "subAccount: account: " << toBase58(naAccountID);
3465 
3466  isrListener->insertSubAccountInfo(naAccountID, rt);
3467  }
3468 
3470 
3471  for (auto const& naAccountID : vnaAccountIDs)
3472  {
3473  auto simIterator = subMap.find(naAccountID);
3474  if (simIterator == subMap.end())
3475  {
3476  // Not found, note that account has a new single listner.
3477  SubMapType usisElement;
3478  usisElement[isrListener->getSeq()] = isrListener;
3479  // VFALCO NOTE This is making a needless copy of naAccountID
3480  subMap.insert(simIterator, make_pair(naAccountID, usisElement));
3481  }
3482  else
3483  {
3484  // Found, note that the account has another listener.
3485  simIterator->second[isrListener->getSeq()] = isrListener;
3486  }
3487  }
3488 }
3489 
3490 void
3492  InfoSub::ref isrListener,
3493  hash_set<AccountID> const& vnaAccountIDs,
3494  bool rt)
3495 {
3496  for (auto const& naAccountID : vnaAccountIDs)
3497  {
3498  // Remove from the InfoSub
3499  isrListener->deleteSubAccountInfo(naAccountID, rt);
3500  }
3501 
3502  // Remove from the server
3503  unsubAccountInternal(isrListener->getSeq(), vnaAccountIDs, rt);
3504 }
3505 
3506 void
3508  std::uint64_t uSeq,
3509  hash_set<AccountID> const& vnaAccountIDs,
3510  bool rt)
3511 {
3513 
3514  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3515 
3516  for (auto const& naAccountID : vnaAccountIDs)
3517  {
3518  auto simIterator = subMap.find(naAccountID);
3519 
3520  if (simIterator != subMap.end())
3521  {
3522  // Found
3523  simIterator->second.erase(uSeq);
3524 
3525  if (simIterator->second.empty())
3526  {
3527  // Don't need hash entry.
3528  subMap.erase(simIterator);
3529  }
3530  }
3531  }
3532 }
3533 
3534 void
3536 {
3537  enum DatabaseType { Postgres, Sqlite, None };
3538  static const auto databaseType = [&]() -> DatabaseType {
3539 #ifdef RIPPLED_REPORTING
3540  if (app_.config().reporting())
3541  {
3542  // Use a dynamic_cast to return DatabaseType::None
3543  // on failure.
3544  if (dynamic_cast<PostgresDatabase*>(&app_.getRelationalDatabase()))
3545  {
3546  return DatabaseType::Postgres;
3547  }
3548  return DatabaseType::None;
3549  }
3550  else
3551  {
3552  // Use a dynamic_cast to return DatabaseType::None
3553  // on failure.
3554  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3555  {
3556  return DatabaseType::Sqlite;
3557  }
3558  return DatabaseType::None;
3559  }
3560 #else
3561  // Use a dynamic_cast to return DatabaseType::None
3562  // on failure.
3563  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3564  {
3565  return DatabaseType::Sqlite;
3566  }
3567  return DatabaseType::None;
3568 #endif
3569  }();
3570 
3571  if (databaseType == DatabaseType::None)
3572  {
3573  JLOG(m_journal.error())
3574  << "AccountHistory job for account "
3575  << toBase58(subInfo.index_->accountId_) << " no database";
3576  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3577  {
3578  sptr->send(rpcError(rpcINTERNAL), true);
3579  unsubAccountHistory(sptr, subInfo.index_->accountId_, false);
3580  }
3581  return;
3582  }
3583 
3586  "AccountHistoryTxStream",
3587  [this, dbType = databaseType, subInfo]() {
3588  auto const& accountId = subInfo.index_->accountId_;
3589  auto& lastLedgerSeq = subInfo.index_->historyLastLedgerSeq_;
3590  auto& txHistoryIndex = subInfo.index_->historyTxIndex_;
3591 
3592  JLOG(m_journal.trace())
3593  << "AccountHistory job for account " << toBase58(accountId)
3594  << " started. lastLedgerSeq=" << lastLedgerSeq;
3595 
3596  auto isFirstTx = [&](std::shared_ptr<Transaction> const& tx,
3597  std::shared_ptr<TxMeta> const& meta) -> bool {
3598  /*
3599  * genesis account: first tx is the one with seq 1
3600  * other account: first tx is the one created the account
3601  */
3602  if (accountId == genesisAccountId)
3603  {
3604  auto stx = tx->getSTransaction();
3605  if (stx->getAccountID(sfAccount) == accountId &&
3606  stx->getSeqProxy().value() == 1)
3607  return true;
3608  }
3609 
3610  for (auto& node : meta->getNodes())
3611  {
3612  if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3613  continue;
3614 
3615  if (node.isFieldPresent(sfNewFields))
3616  {
3617  if (auto inner = dynamic_cast<const STObject*>(
3618  node.peekAtPField(sfNewFields));
3619  inner)
3620  {
3621  if (inner->isFieldPresent(sfAccount) &&
3622  inner->getAccountID(sfAccount) == accountId)
3623  {
3624  return true;
3625  }
3626  }
3627  }
3628  }
3629 
3630  return false;
3631  };
3632 
3633  auto send = [&](Json::Value const& jvObj,
3634  bool unsubscribe) -> bool {
3635  if (auto sptr = subInfo.sinkWptr_.lock())
3636  {
3637  sptr->send(jvObj, true);
3638  if (unsubscribe)
3639  unsubAccountHistory(sptr, accountId, false);
3640  return true;
3641  }
3642 
3643  return false;
3644  };
3645 
3646  auto sendMultiApiJson = [&](MultiApiJson const& jvObj,
3647  bool unsubscribe) -> bool {
3648  if (auto sptr = subInfo.sinkWptr_.lock())
3649  {
3650  sptr->send(
3651  jvObj.select(apiVersionSelector(sptr->getApiVersion())),
3652  true);
3653 
3654  if (unsubscribe)
3655  unsubAccountHistory(sptr, accountId, false);
3656  return true;
3657  }
3658 
3659  return false;
3660  };
3661 
3662  auto getMoreTxns =
3663  [&](std::uint32_t minLedger,
3664  std::uint32_t maxLedger,
3669  switch (dbType)
3670  {
3671  case Postgres: {
3672  auto db = static_cast<PostgresDatabase*>(
3675  args.account = accountId;
3676  LedgerRange range{minLedger, maxLedger};
3677  args.ledger = range;
3678  args.marker = marker;
3679  auto [txResult, status] = db->getAccountTx(args);
3680  if (status != rpcSUCCESS)
3681  {
3682  JLOG(m_journal.debug())
3683  << "AccountHistory job for account "
3684  << toBase58(accountId)
3685  << " getAccountTx failed";
3686  return {};
3687  }
3688 
3689  if (auto txns =
3690  std::get_if<RelationalDatabase::AccountTxs>(
3691  &txResult.transactions);
3692  txns)
3693  {
3694  return std::make_pair(*txns, txResult.marker);
3695  }
3696  else
3697  {
3698  JLOG(m_journal.debug())
3699  << "AccountHistory job for account "
3700  << toBase58(accountId)
3701  << " getAccountTx wrong data";
3702  return {};
3703  }
3704  }
3705  case Sqlite: {
3706  auto db = static_cast<SQLiteDatabase*>(
3709  accountId, minLedger, maxLedger, marker, 0, true};
3710  return db->newestAccountTxPage(options);
3711  }
3712  default: {
3713  assert(false);
3714  return {};
3715  }
3716  }
3717  };
3718 
3719  /*
3720  * search backward until the genesis ledger or asked to stop
3721  */
3722  while (lastLedgerSeq >= 2 && !subInfo.index_->stopHistorical_)
3723  {
3724  int feeChargeCount = 0;
3725  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3726  {
3727  sptr->getConsumer().charge(Resource::feeMediumBurdenRPC);
3728  ++feeChargeCount;
3729  }
3730  else
3731  {
3732  JLOG(m_journal.trace())
3733  << "AccountHistory job for account "
3734  << toBase58(accountId) << " no InfoSub. Fee charged "
3735  << feeChargeCount << " times.";
3736  return;
3737  }
3738 
3739  // try to search in 1024 ledgers till reaching genesis ledgers
3740  auto startLedgerSeq =
3741  (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3742  JLOG(m_journal.trace())
3743  << "AccountHistory job for account " << toBase58(accountId)
3744  << ", working on ledger range [" << startLedgerSeq << ","
3745  << lastLedgerSeq << "]";
3746 
3747  auto haveRange = [&]() -> bool {
3748  std::uint32_t validatedMin = UINT_MAX;
3749  std::uint32_t validatedMax = 0;
3750  auto haveSomeValidatedLedgers =
3752  validatedMin, validatedMax);
3753 
3754  return haveSomeValidatedLedgers &&
3755  validatedMin <= startLedgerSeq &&
3756  lastLedgerSeq <= validatedMax;
3757  }();
3758 
3759  if (!haveRange)
3760  {
3761  JLOG(m_journal.debug())
3762  << "AccountHistory reschedule job for account "
3763  << toBase58(accountId) << ", incomplete ledger range ["
3764  << startLedgerSeq << "," << lastLedgerSeq << "]";
3765  setAccountHistoryJobTimer(subInfo);
3766  return;
3767  }
3768 
3770  while (!subInfo.index_->stopHistorical_)
3771  {
3772  auto dbResult =
3773  getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3774  if (!dbResult)
3775  {
3776  JLOG(m_journal.debug())
3777  << "AccountHistory job for account "
3778  << toBase58(accountId) << " getMoreTxns failed.";
3779  send(rpcError(rpcINTERNAL), true);
3780  return;
3781  }
3782 
3783  auto const& txns = dbResult->first;
3784  marker = dbResult->second;
3785  size_t num_txns = txns.size();
3786  for (size_t i = 0; i < num_txns; ++i)
3787  {
3788  auto const& [tx, meta] = txns[i];
3789 
3790  if (!tx || !meta)
3791  {
3792  JLOG(m_journal.debug())
3793  << "AccountHistory job for account "
3794  << toBase58(accountId) << " empty tx or meta.";
3795  send(rpcError(rpcINTERNAL), true);
3796  return;
3797  }
3798  auto curTxLedger =
3800  tx->getLedger());
3801  if (!curTxLedger)
3802  {
3803  JLOG(m_journal.debug())
3804  << "AccountHistory job for account "
3805  << toBase58(accountId) << " no ledger.";
3806  send(rpcError(rpcINTERNAL), true);
3807  return;
3808  }
3810  tx->getSTransaction();
3811  if (!stTxn)
3812  {
3813  JLOG(m_journal.debug())
3814  << "AccountHistory job for account "
3815  << toBase58(accountId)
3816  << " getSTransaction failed.";
3817  send(rpcError(rpcINTERNAL), true);
3818  return;
3819  }
3820 
3821  auto const mRef = std::ref(*meta);
3822  auto const trR = meta->getResultTER();
3823  MultiApiJson jvTx =
3824  transJson(stTxn, trR, true, curTxLedger, mRef);
3825 
3826  jvTx.set(
3827  jss::account_history_tx_index, txHistoryIndex--);
3828  if (i + 1 == num_txns ||
3829  txns[i + 1].first->getLedger() != tx->getLedger())
3830  jvTx.set(jss::account_history_boundary, true);
3831 
3832  if (isFirstTx(tx, meta))
3833  {
3834  jvTx.set(jss::account_history_tx_first, true);
3835  sendMultiApiJson(jvTx, false);
3836 
3837  JLOG(m_journal.trace())
3838  << "AccountHistory job for account "
3839  << toBase58(accountId)
3840  << " done, found last tx.";
3841  return;
3842  }
3843  else
3844  {
3845  sendMultiApiJson(jvTx, false);
3846  }
3847  }
3848 
3849  if (marker)
3850  {
3851  JLOG(m_journal.trace())
3852  << "AccountHistory job for account "
3853  << toBase58(accountId)
3854  << " paging, marker=" << marker->ledgerSeq << ":"
3855  << marker->txnSeq;
3856  }
3857  else
3858  {
3859  break;
3860  }
3861  }
3862 
3863  if (!subInfo.index_->stopHistorical_)
3864  {
3865  lastLedgerSeq = startLedgerSeq - 1;
3866  if (lastLedgerSeq <= 1)
3867  {
3868  JLOG(m_journal.trace())
3869  << "AccountHistory job for account "
3870  << toBase58(accountId)
3871  << " done, reached genesis ledger.";
3872  return;
3873  }
3874  }
3875  }
3876  });
3877 }
3878 
3879 void
3881  std::shared_ptr<ReadView const> const& ledger,
3882  SubAccountHistoryInfoWeak& subInfo)
3883 {
3884  subInfo.index_->separationLedgerSeq_ = ledger->seq();
3885  auto const& accountId = subInfo.index_->accountId_;
3886  auto const accountKeylet = keylet::account(accountId);
3887  if (!ledger->exists(accountKeylet))
3888  {
3889  JLOG(m_journal.debug())
3890  << "subAccountHistoryStart, no account " << toBase58(accountId)
3891  << ", no need to add AccountHistory job.";
3892  return;
3893  }
3894  if (accountId == genesisAccountId)
3895  {
3896  if (auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3897  {
3898  if (sleAcct->getFieldU32(sfSequence) == 1)
3899  {
3900  JLOG(m_journal.debug())
3901  << "subAccountHistoryStart, genesis account "
3902  << toBase58(accountId)
3903  << " does not have tx, no need to add AccountHistory job.";
3904  return;
3905  }
3906  }
3907  else
3908  {
3909  assert(false);
3910  return;
3911  }
3912  }
3913  subInfo.index_->historyLastLedgerSeq_ = ledger->seq();
3914  subInfo.index_->haveHistorical_ = true;
3915 
3916  JLOG(m_journal.debug())
3917  << "subAccountHistoryStart, add AccountHistory job: accountId="
3918  << toBase58(accountId) << ", currentLedgerSeq=" << ledger->seq();
3919 
3920  addAccountHistoryJob(subInfo);
3921 }
3922 
3925  InfoSub::ref isrListener,
3926  AccountID const& accountId)
3927 {
3928  if (!isrListener->insertSubAccountHistory(accountId))
3929  {
3930  JLOG(m_journal.debug())
3931  << "subAccountHistory, already subscribed to account "
3932  << toBase58(accountId);
3933  return rpcINVALID_PARAMS;
3934  }
3935 
3938  isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3939  auto simIterator = mSubAccountHistory.find(accountId);
3940  if (simIterator == mSubAccountHistory.end())
3941  {
3943  inner.emplace(isrListener->getSeq(), ahi);
3945  simIterator, std::make_pair(accountId, inner));
3946  }
3947  else
3948  {
3949  simIterator->second.emplace(isrListener->getSeq(), ahi);
3950  }
3951 
3952  auto const ledger = app_.getLedgerMaster().getValidatedLedger();
3953  if (ledger)
3954  {
3955  subAccountHistoryStart(ledger, ahi);
3956  }
3957  else
3958  {
3959  // The node does not have validated ledgers, so wait for
3960  // one before start streaming.
3961  // In this case, the subscription is also considered successful.
3962  JLOG(m_journal.debug())
3963  << "subAccountHistory, no validated ledger yet, delay start";
3964  }
3965 
3966  return rpcSUCCESS;
3967 }
3968 
3969 void
3971  InfoSub::ref isrListener,
3972  AccountID const& account,
3973  bool historyOnly)
3974 {
3975  if (!historyOnly)
3976  isrListener->deleteSubAccountHistory(account);
3977  unsubAccountHistoryInternal(isrListener->getSeq(), account, historyOnly);
3978 }
3979 
3980 void
3982  std::uint64_t seq,
3983  const AccountID& account,
3984  bool historyOnly)
3985 {
3987  auto simIterator = mSubAccountHistory.find(account);
3988  if (simIterator != mSubAccountHistory.end())
3989  {
3990  auto& subInfoMap = simIterator->second;
3991  auto subInfoIter = subInfoMap.find(seq);
3992  if (subInfoIter != subInfoMap.end())
3993  {
3994  subInfoIter->second.index_->stopHistorical_ = true;
3995  }
3996 
3997  if (!historyOnly)
3998  {
3999  simIterator->second.erase(seq);
4000  if (simIterator->second.empty())
4001  {
4002  mSubAccountHistory.erase(simIterator);
4003  }
4004  }
4005  JLOG(m_journal.debug())
4006  << "unsubAccountHistory, account " << toBase58(account)
4007  << ", historyOnly = " << (historyOnly ? "true" : "false");
4008  }
4009 }
4010 
4011 bool
4012 NetworkOPsImp::subBook(InfoSub::ref isrListener, Book const& book)
4013 {
4014  if (auto listeners = app_.getOrderBookDB().makeBookListeners(book))
4015  listeners->addSubscriber(isrListener);
4016  else
4017  assert(false);
4018  return true;
4019 }
4020 
4021 bool
4023 {
4024  if (auto listeners = app_.getOrderBookDB().getBookListeners(book))
4025  listeners->removeSubscriber(uSeq);
4026 
4027  return true;
4028 }
4029 
4033 {
4034  // This code-path is exclusively used when the server is in standalone
4035  // mode via `ledger_accept`
4036  assert(m_standalone);
4037 
4038  if (!m_standalone)
4039  Throw<std::runtime_error>(
4040  "Operation only possible in STANDALONE mode.");
4041 
4042  // FIXME Could we improve on this and remove the need for a specialized
4043  // API in Consensus?
4045  mConsensus.simulate(app_.timeKeeper().closeTime(), consensusDelay);
4046  return m_ledgerMaster.getCurrentLedger()->info().seq;
4047 }
4048 
4049 // <-- bool: true=added, false=already there
4050 bool
4052 {
4053  if (auto lpClosed = m_ledgerMaster.getValidatedLedger())
4054  {
4055  jvResult[jss::ledger_index] = lpClosed->info().seq;
4056  jvResult[jss::ledger_hash] = to_string(lpClosed->info().hash);
4057  jvResult[jss::ledger_time] = Json::Value::UInt(
4058  lpClosed->info().closeTime.time_since_epoch().count());
4059  if (!lpClosed->rules().enabled(featureXRPFees))
4060  jvResult[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
4061  jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
4062  jvResult[jss::reserve_base] =
4063  lpClosed->fees().accountReserve(0).jsonClipped();
4064  jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
4065  }
4066 
4068  {
4069  jvResult[jss::validated_ledgers] =
4071  }
4072 
4074  return mStreamMaps[sLedger]
4075  .emplace(isrListener->getSeq(), isrListener)
4076  .second;
4077 }
4078 
4079 // <-- bool: true=added, false=already there
4080 bool
4082 {
4084  return mStreamMaps[sBookChanges]
4085  .emplace(isrListener->getSeq(), isrListener)
4086  .second;
4087 }
4088 
4089 // <-- bool: true=erased, false=was not there
4090 bool
4092 {
4094  return mStreamMaps[sLedger].erase(uSeq);
4095 }
4096 
4097 // <-- bool: true=erased, false=was not there
4098 bool
4100 {
4102  return mStreamMaps[sBookChanges].erase(uSeq);
4103 }
4104 
4105 // <-- bool: true=added, false=already there
4106 bool
4108 {
4110  return mStreamMaps[sManifests]
4111  .emplace(isrListener->getSeq(), isrListener)
4112  .second;
4113 }
4114 
4115 // <-- bool: true=erased, false=was not there
4116 bool
4118 {
4120  return mStreamMaps[sManifests].erase(uSeq);
4121 }
4122 
4123 // <-- bool: true=added, false=already there
4124 bool
4126  InfoSub::ref isrListener,
4127  Json::Value& jvResult,
4128  bool admin)
4129 {
4130  uint256 uRandom;
4131 
4132  if (m_standalone)
4133  jvResult[jss::stand_alone] = m_standalone;
4134 
4135  // CHECKME: is it necessary to provide a random number here?
4136  beast::rngfill(uRandom.begin(), uRandom.size(), crypto_prng());
4137 
4138  auto const& feeTrack = app_.getFeeTrack();
4139  jvResult[jss::random] = to_string(uRandom);
4140  jvResult[jss::server_status] = strOperatingMode(admin);
4141  jvResult[jss::load_base] = feeTrack.getLoadBase();
4142  jvResult[jss::load_factor] = feeTrack.getLoadFactor();
4143  jvResult[jss::hostid] = getHostId(admin);
4144  jvResult[jss::pubkey_node] =
4146 
4148  return mStreamMaps[sServer]
4149  .emplace(isrListener->getSeq(), isrListener)
4150  .second;
4151 }
4152 
4153 // <-- bool: true=erased, false=was not there
4154 bool
4156 {
4158  return mStreamMaps[sServer].erase(uSeq);
4159 }
4160 
4161 // <-- bool: true=added, false=already there
4162 bool
4164 {
4166  return mStreamMaps[sTransactions]
4167  .emplace(isrListener->getSeq(), isrListener)
4168  .second;
4169 }
4170 
4171 // <-- bool: true=erased, false=was not there
4172 bool
4174 {
4176  return mStreamMaps[sTransactions].erase(uSeq);
4177 }
4178 
4179 // <-- bool: true=added, false=already there
4180 bool
4182 {
4185  .emplace(isrListener->getSeq(), isrListener)
4186  .second;
4187 }
4188 
4189 // <-- bool: true=erased, false=was not there
4190 bool
4192 {
4194  return mStreamMaps[sRTTransactions].erase(uSeq);
4195 }
4196 
4197 // <-- bool: true=added, false=already there
4198 bool
4200 {
4202  return mStreamMaps[sValidations]
4203  .emplace(isrListener->getSeq(), isrListener)
4204  .second;
4205 }
4206 
4207 void
4209 {
4210  accounting_.json(obj);
4211 }
4212 
4213 // <-- bool: true=erased, false=was not there
4214 bool
4216 {
4218  return mStreamMaps[sValidations].erase(uSeq);
4219 }
4220 
4221 // <-- bool: true=added, false=already there
4222 bool
4224 {
4226  return mStreamMaps[sPeerStatus]
4227  .emplace(isrListener->getSeq(), isrListener)
4228  .second;
4229 }
4230 
4231 // <-- bool: true=erased, false=was not there
4232 bool
4234 {
4236  return mStreamMaps[sPeerStatus].erase(uSeq);
4237 }
4238 
4239 // <-- bool: true=added, false=already there
4240 bool
4242 {
4245  .emplace(isrListener->getSeq(), isrListener)
4246  .second;
4247 }
4248 
4249 // <-- bool: true=erased, false=was not there
4250 bool
4252 {
4254  return mStreamMaps[sConsensusPhase].erase(uSeq);
4255 }
4256 
4259 {
4261 
4262  subRpcMapType::iterator it = mRpcSubMap.find(strUrl);
4263 
4264  if (it != mRpcSubMap.end())
4265  return it->second;
4266 
4267  return InfoSub::pointer();
4268 }
4269 
4272 {
4274 
4275  mRpcSubMap.emplace(strUrl, rspEntry);
4276 
4277  return rspEntry;
4278 }
4279 
4280 bool
4282 {
4284  auto pInfo = findRpcSub(strUrl);
4285 
4286  if (!pInfo)
4287  return false;
4288 
4289  // check to see if any of the stream maps still hold a weak reference to
4290  // this entry before removing
4291  for (SubMapType const& map : mStreamMaps)
4292  {
4293  if (map.find(pInfo->getSeq()) != map.end())
4294  return false;
4295  }
4296  mRpcSubMap.erase(strUrl);
4297  return true;
4298 }
4299 
4300 #ifndef USE_NEW_BOOK_PAGE
4301 
4302 // NIKB FIXME this should be looked at. There's no reason why this shouldn't
4303 // work, but it demonstrated poor performance.
4304 //
4305 void
4308  Book const& book,
4309  AccountID const& uTakerID,
4310  bool const bProof,
4311  unsigned int iLimit,
4312  Json::Value const& jvMarker,
4313  Json::Value& jvResult)
4314 { // CAUTION: This is the old get book page logic
4315  Json::Value& jvOffers =
4316  (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4317 
4319  const uint256 uBookBase = getBookBase(book);
4320  const uint256 uBookEnd = getQualityNext(uBookBase);
4321  uint256 uTipIndex = uBookBase;
4322 
4323  if (auto stream = m_journal.trace())
4324  {
4325  stream << "getBookPage:" << book;
4326  stream << "getBookPage: uBookBase=" << uBookBase;
4327  stream << "getBookPage: uBookEnd=" << uBookEnd;
4328  stream << "getBookPage: uTipIndex=" << uTipIndex;
4329  }
4330 
4331  ReadView const& view = *lpLedger;
4332 
4333  bool const bGlobalFreeze = isGlobalFrozen(view, book.out.account) ||
4334  isGlobalFrozen(view, book.in.account);
4335 
4336  bool bDone = false;
4337  bool bDirectAdvance = true;
4338 
4339  std::shared_ptr<SLE const> sleOfferDir;
4340  uint256 offerIndex;
4341  unsigned int uBookEntry;
4342  STAmount saDirRate;
4343 
4344  auto const rate = transferRate(view, book.out.account);
4345  auto viewJ = app_.journal("View");
4346 
4347  while (!bDone && iLimit-- > 0)
4348  {
4349  if (bDirectAdvance)
4350  {
4351  bDirectAdvance = false;
4352 
4353  JLOG(m_journal.trace()) << "getBookPage: bDirectAdvance";
4354 
4355  auto const ledgerIndex = view.succ(uTipIndex, uBookEnd);
4356  if (ledgerIndex)
4357  sleOfferDir = view.read(keylet::page(*ledgerIndex));
4358  else
4359  sleOfferDir.reset();
4360 
4361  if (!sleOfferDir)
4362  {
4363  JLOG(m_journal.trace()) << "getBookPage: bDone";
4364  bDone = true;
4365  }
4366  else
4367  {
4368  uTipIndex = sleOfferDir->key();
4369  saDirRate = amountFromQuality(getQuality(uTipIndex));
4370 
4371  cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4372 
4373  JLOG(m_journal.trace())
4374  << "getBookPage: uTipIndex=" << uTipIndex;
4375  JLOG(m_journal.trace())
4376  << "getBookPage: offerIndex=" << offerIndex;
4377  }
4378  }
4379 
4380  if (!bDone)
4381  {
4382  auto sleOffer = view.read(keylet::offer(offerIndex));
4383 
4384  if (sleOffer)
4385  {
4386  auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4387  auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4388  auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4389  STAmount saOwnerFunds;
4390  bool firstOwnerOffer(true);
4391 
4392  if (book.out.account == uOfferOwnerID)
4393  {
4394  // If an offer is selling issuer's own IOUs, it is fully
4395  // funded.
4396  saOwnerFunds = saTakerGets;
4397  }
4398  else if (bGlobalFreeze)
4399  {
4400  // If either asset is globally frozen, consider all offers
4401  // that aren't ours to be totally unfunded
4402  saOwnerFunds.clear(book.out);
4403  }
4404  else
4405  {
4406  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4407  if (umBalanceEntry != umBalance.end())
4408  {
4409  // Found in running balance table.
4410 
4411  saOwnerFunds = umBalanceEntry->second;
4412  firstOwnerOffer = false;
4413  }
4414  else
4415  {
4416  // Did not find balance in table.
4417 
4418  saOwnerFunds = accountHolds(
4419  view,
4420  uOfferOwnerID,
4421  book.out.currency,
4422  book.out.account,
4424  viewJ);
4425 
4426  if (saOwnerFunds < beast::zero)
4427  {
4428  // Treat negative funds as zero.
4429 
4430  saOwnerFunds.clear();
4431  }
4432  }
4433  }
4434 
4435  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4436 
4437  STAmount saTakerGetsFunded;
4438  STAmount saOwnerFundsLimit = saOwnerFunds;
4439  Rate offerRate = parityRate;
4440 
4441  if (rate != parityRate
4442  // Have a tranfer fee.
4443  && uTakerID != book.out.account
4444  // Not taking offers of own IOUs.
4445  && book.out.account != uOfferOwnerID)
4446  // Offer owner not issuing ownfunds
4447  {
4448  // Need to charge a transfer fee to offer owner.
4449  offerRate = rate;
4450  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4451  }
4452 
4453  if (saOwnerFundsLimit >= saTakerGets)
4454  {
4455  // Sufficient funds no shenanigans.
4456  saTakerGetsFunded = saTakerGets;
4457  }
4458  else
4459  {
4460  // Only provide, if not fully funded.
4461 
4462  saTakerGetsFunded = saOwnerFundsLimit;
4463 
4464  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4465  std::min(
4466  saTakerPays,
4467  multiply(
4468  saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4469  .setJson(jvOffer[jss::taker_pays_funded]);
4470  }
4471 
4472  STAmount saOwnerPays = (parityRate == offerRate)
4473  ? saTakerGetsFunded
4474  : std::min(
4475  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4476 
4477  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4478 
4479  // Include all offers funded and unfunded
4480  Json::Value& jvOf = jvOffers.append(jvOffer);
4481  jvOf[jss::quality] = saDirRate.getText();
4482 
4483  if (firstOwnerOffer)
4484  jvOf[jss::owner_funds] = saOwnerFunds.getText();
4485  }
4486  else
4487  {
4488  JLOG(m_journal.warn()) << "Missing offer";
4489  }
4490 
4491  if (!cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4492  {
4493  bDirectAdvance = true;
4494  }
4495  else
4496  {
4497  JLOG(m_journal.trace())
4498  << "getBookPage: offerIndex=" << offerIndex;
4499  }
4500  }
4501  }
4502 
4503  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4504  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4505 }
4506 
4507 #else
4508 
4509 // This is the new code that uses the book iterators
4510 // It has temporarily been disabled
4511 
4512 void
4515  Book const& book,
4516  AccountID const& uTakerID,
4517  bool const bProof,
4518  unsigned int iLimit,
4519  Json::Value const& jvMarker,
4520  Json::Value& jvResult)
4521 {
4522  auto& jvOffers = (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4523 
4525 
4526  MetaView lesActive(lpLedger, tapNONE, true);
4527  OrderBookIterator obIterator(lesActive, book);
4528 
4529  auto const rate = transferRate(lesActive, book.out.account);
4530 
4531  const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.out.account) ||
4532  lesActive.isGlobalFrozen(book.in.account);
4533 
4534  while (iLimit-- > 0 && obIterator.nextOffer())
4535  {
4536  SLE::pointer sleOffer = obIterator.getCurrentOffer();
4537  if (sleOffer)
4538  {
4539  auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4540  auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4541  auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4542  STAmount saDirRate = obIterator.getCurrentRate();
4543  STAmount saOwnerFunds;
4544 
4545  if (book.out.account == uOfferOwnerID)
4546  {
4547  // If offer is selling issuer's own IOUs, it is fully funded.
4548  saOwnerFunds = saTakerGets;
4549  }
4550  else if (bGlobalFreeze)
4551  {
4552  // If either asset is globally frozen, consider all offers
4553  // that aren't ours to be totally unfunded
4554  saOwnerFunds.clear(book.out);
4555  }
4556  else
4557  {
4558  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4559 
4560  if (umBalanceEntry != umBalance.end())
4561  {
4562  // Found in running balance table.
4563 
4564  saOwnerFunds = umBalanceEntry->second;
4565  }
4566  else
4567  {
4568  // Did not find balance in table.
4569 
4570  saOwnerFunds = lesActive.accountHolds(
4571  uOfferOwnerID,
4572  book.out.currency,
4573  book.out.account,
4575 
4576  if (saOwnerFunds.isNegative())
4577  {
4578  // Treat negative funds as zero.
4579 
4580  saOwnerFunds.zero();
4581  }
4582  }
4583  }
4584 
4585  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4586 
4587  STAmount saTakerGetsFunded;
4588  STAmount saOwnerFundsLimit = saOwnerFunds;
4589  Rate offerRate = parityRate;
4590 
4591  if (rate != parityRate
4592  // Have a tranfer fee.
4593  && uTakerID != book.out.account
4594  // Not taking offers of own IOUs.
4595  && book.out.account != uOfferOwnerID)
4596  // Offer owner not issuing ownfunds
4597  {
4598  // Need to charge a transfer fee to offer owner.
4599  offerRate = rate;
4600  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4601  }
4602 
4603  if (saOwnerFundsLimit >= saTakerGets)
4604  {
4605  // Sufficient funds no shenanigans.
4606  saTakerGetsFunded = saTakerGets;
4607  }
4608  else
4609  {
4610  // Only provide, if not fully funded.
4611  saTakerGetsFunded = saOwnerFundsLimit;
4612 
4613  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4614 
4615  // TOOD(tom): The result of this expression is not used - what's
4616  // going on here?
4617  std::min(
4618  saTakerPays,
4619  multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4620  .setJson(jvOffer[jss::taker_pays_funded]);
4621  }
4622 
4623  STAmount saOwnerPays = (parityRate == offerRate)
4624  ? saTakerGetsFunded
4625  : std::min(
4626  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4627 
4628  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4629 
4630  if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4631  {
4632  // Only provide funded offers and offers of the taker.
4633  Json::Value& jvOf = jvOffers.append(jvOffer);
4634  jvOf[jss::quality] = saDirRate.getText();
4635  }
4636  }
4637  }
4638 
4639  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4640  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4641 }
4642 
4643 #endif
4644 
4645 inline void
4647 {
4648  auto [counters, mode, start, initialSync] = accounting_.getCounterData();
4649  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4650  std::chrono::steady_clock::now() - start);
4651  counters[static_cast<std::size_t>(mode)].dur += current;
4652 
4655  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4656  .dur.count());
4658  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4659  .dur.count());
4661  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].dur.count());
4663  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4664  .dur.count());
4666  counters[static_cast<std::size_t>(OperatingMode::FULL)].dur.count());
4667 
4669  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4670  .transitions);
4672  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4673  .transitions);
4675  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].transitions);
4677  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4678  .transitions);
4680  counters[static_cast<std::size_t>(OperatingMode::FULL)].transitions);
4681 }
4682 
4683 void
4685 {
4686  auto now = std::chrono::steady_clock::now();
4687 
4688  std::lock_guard lock(mutex_);
4689  ++counters_[static_cast<std::size_t>(om)].transitions;
4690  if (om == OperatingMode::FULL &&
4691  counters_[static_cast<std::size_t>(om)].transitions == 1)
4692  {
4693  initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4694  now - processStart_)
4695  .count();
4696  }
4697  counters_[static_cast<std::size_t>(mode_)].dur +=
4698  std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4699 
4700  mode_ = om;
4701  start_ = now;
4702 }
4703 
4704 void
4706 {
4707  auto [counters, mode, start, initialSync] = getCounterData();
4708  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4709  std::chrono::steady_clock::now() - start);
4710  counters[static_cast<std::size_t>(mode)].dur += current;
4711 
4712  obj[jss::state_accounting] = Json::objectValue;
4713  for (std::size_t i = static_cast<std::size_t>(OperatingMode::DISCONNECTED);
4714  i <= static_cast<std::size_t>(OperatingMode::FULL);
4715  ++i)
4716  {
4717  obj[jss::state_accounting][states_[i]] = Json::objectValue;
4718  auto& state = obj[jss::state_accounting][states_[i]];
4719  state[jss::transitions] = std::to_string(counters[i].transitions);
4720  state[jss::duration_us] = std::to_string(counters[i].dur.count());
4721  }
4722  obj[jss::server_state_duration_us] = std::to_string(current.count());
4723  if (initialSync)
4724  obj[jss::initial_sync_duration_us] = std::to_string(initialSync);
4725 }
4726 
4727 //------------------------------------------------------------------------------
4728 
4731  Application& app,
4732  NetworkOPs::clock_type& clock,
4733  bool standalone,
4734  std::size_t minPeerCount,
4735  bool startvalid,
4736  JobQueue& job_queue,
4737  LedgerMaster& ledgerMaster,
4738  ValidatorKeys const& validatorKeys,
4739  boost::asio::io_service& io_svc,
4740  beast::Journal journal,
4741  beast::insight::Collector::ptr const& collector)
4742 {
4743  return std::make_unique<NetworkOPsImp>(
4744  app,
4745  clock,
4746  standalone,
4747  minPeerCount,
4748  startvalid,
4749  job_queue,
4750  ledgerMaster,
4751  validatorKeys,
4752  io_svc,
4753  journal,
4754  collector);
4755 }
4756 
4757 } // namespace ripple
ripple::SQLiteDatabase
Definition: SQLiteDatabase.h:27
ripple::NetworkOPsImp::forwardManifest
void forwardManifest(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2838
ripple::NetworkOPsImp::unsubValidations
bool unsubValidations(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4215
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:4199
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:4251
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:98
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:4208
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:1747
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::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:322
ripple::RCLConsensus::getJson
Json::Value getJson(bool full) const
Definition: RCLConsensus.cpp:911
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:4705
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:3245
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:643
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:4646
ripple::NetworkOPsImp::subPeerStatus
bool subPeerStatus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4223
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:92
ripple::NetworkOPsImp::StateAccounting::Counters::dur
std::chrono::microseconds dur
Definition: NetworkOPs.cpp:144
ripple::NetworkOPsImp::pubProposedAccountTransaction
void pubProposedAccountTransaction(std::shared_ptr< ReadView const > const &ledger, std::shared_ptr< STTx const > const &transaction, TER result)
Definition: NetworkOPs.cpp:3377
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:4281
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::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:2787
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:232
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:3981
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:3099
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:4730
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:110
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::NetworkOPsImp::forwardProposedAccountTransaction
void forwardProposedAccountTransaction(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2876
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::NetworkOPsImp::pubLedger
void pubLedger(std::shared_ptr< ReadView const > const &lpAccepted) override
Definition: NetworkOPs.cpp:2944
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:1754
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:4173
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:221
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:957
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:637
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:2858
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:161
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:4271
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
ripple::NetworkOPsImp::forwardValidation
void forwardValidation(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2818
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:3880
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:3057
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:3535
ripple::NetworkOPsImp::isBlocked
bool isBlocked() override
Definition: NetworkOPs.cpp:1593
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:143
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:319
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:3491
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:4191
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:243
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:4107
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::ValidatorList::localPublicKey
std::optional< PublicKey > localPublicKey() const
This function returns the local validator public key or a std::nullopt.
Definition: ValidatorList.cpp:1433
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:162
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:4081
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:1871
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:160
ripple::NetworkOPsImp::subTransactions
bool subTransactions(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4163
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:4091
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:254
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::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:3454
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:1707
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:1536
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:95
ripple::LedgerMaster::getFetchPackCacheSize
std::size_t getFetchPackCacheSize() const
Definition: LedgerMaster.cpp:2413
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:55
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:3077
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:231
ripple::NetworkOPsImp::unsubServer
bool unsubServer(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4155
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:4099
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:3091
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:2748
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:172
ripple::NetworkOPsImp::unsubBook
bool unsubBook(std::uint64_t uListener, Book const &) override
Definition: NetworkOPs.cpp:4022
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:4031
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:3191
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:4306
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:4051
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:3924
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:1717
ripple::NetworkOPsImp::unsubManifests
bool unsubManifests(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4117
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:3086
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:38
ripple::MultivarJson
Definition: MultivarJson.h:34
ripple::NetworkOPsImp::subRTTransactions
bool subRTTransactions(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4181
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:2754
ripple::Application::getValidationPublicKey
virtual std::optional< PublicKey const > getValidationPublicKey() const =0
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::Manifest::signingKey
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Definition: Manifest.h:92
ripple::NetworkOPsImp::subServer
bool subServer(InfoSub::ref ispListener, Json::Value &jvResult, bool admin) override
Definition: NetworkOPs.cpp:4125
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:130
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:4012
ripple::NetworkOPsImp::subConsensus
bool subConsensus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4241
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:1480
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:4684
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:3507
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:3970
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:238
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:118
ripple::Overlay::getPeerDisconnectCharges
virtual std::uint64_t getPeerDisconnectCharges() const =0
ripple::NetworkOPsImp::unsubPeerStatus
bool unsubPeerStatus(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4233
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:625
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:502
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:4258
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:2742
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)