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