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