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