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