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