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  // NOTE *seq is a number, but old API versions used string. We replace
2185  // number with a string using MultiApiJson near end of this function
2186  if (auto const seq = (*val)[~sfLedgerSequence])
2187  jvObj[jss::ledger_index] = *seq;
2188 
2189  if (val->isFieldPresent(sfAmendments))
2190  {
2191  jvObj[jss::amendments] = Json::Value(Json::arrayValue);
2192  for (auto const& amendment : val->getFieldV256(sfAmendments))
2193  jvObj[jss::amendments].append(to_string(amendment));
2194  }
2195 
2196  if (auto const closeTime = (*val)[~sfCloseTime])
2197  jvObj[jss::close_time] = *closeTime;
2198 
2199  if (auto const loadFee = (*val)[~sfLoadFee])
2200  jvObj[jss::load_fee] = *loadFee;
2201 
2202  if (auto const baseFee = val->at(~sfBaseFee))
2203  jvObj[jss::base_fee] = static_cast<double>(*baseFee);
2204 
2205  if (auto const reserveBase = val->at(~sfReserveBase))
2206  jvObj[jss::reserve_base] = *reserveBase;
2207 
2208  if (auto const reserveInc = val->at(~sfReserveIncrement))
2209  jvObj[jss::reserve_inc] = *reserveInc;
2210 
2211  // (The ~ operator converts the Proxy to a std::optional, which
2212  // simplifies later operations)
2213  if (auto const baseFeeXRP = ~val->at(~sfBaseFeeDrops);
2214  baseFeeXRP && baseFeeXRP->native())
2215  jvObj[jss::base_fee] = baseFeeXRP->xrp().jsonClipped();
2216 
2217  if (auto const reserveBaseXRP = ~val->at(~sfReserveBaseDrops);
2218  reserveBaseXRP && reserveBaseXRP->native())
2219  jvObj[jss::reserve_base] = reserveBaseXRP->xrp().jsonClipped();
2220 
2221  if (auto const reserveIncXRP = ~val->at(~sfReserveIncrementDrops);
2222  reserveIncXRP && reserveIncXRP->native())
2223  jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped();
2224 
2225  // NOTE Use MultiApiJson to publish two slightly different JSON objects
2226  // for consumers supporting different API versions
2227  MultiApiJson multiObj{jvObj};
2228  visit<RPC::apiMinimumSupportedVersion, RPC::apiMaximumValidVersion>(
2229  multiObj, //
2230  [](Json::Value& jvTx, unsigned int apiVersion) {
2231  // Type conversion for older API versions to string
2232  if (jvTx.isMember(jss::ledger_index) && apiVersion < 2)
2233  {
2234  jvTx[jss::ledger_index] =
2235  std::to_string(jvTx[jss::ledger_index].asUInt());
2236  }
2237  });
2238 
2239  for (auto i = mStreamMaps[sValidations].begin();
2240  i != mStreamMaps[sValidations].end();)
2241  {
2242  if (auto p = i->second.lock())
2243  {
2244  p->send(
2245  multiObj.select(apiVersionSelector(p->getApiVersion())),
2246  true);
2247  ++i;
2248  }
2249  else
2250  {
2251  i = mStreamMaps[sValidations].erase(i);
2252  }
2253  }
2254  }
2255 }
2256 
2257 void
2259 {
2261 
2262  if (!mStreamMaps[sPeerStatus].empty())
2263  {
2264  Json::Value jvObj(func());
2265 
2266  jvObj[jss::type] = "peerStatusChange";
2267 
2268  for (auto i = mStreamMaps[sPeerStatus].begin();
2269  i != mStreamMaps[sPeerStatus].end();)
2270  {
2271  InfoSub::pointer p = i->second.lock();
2272 
2273  if (p)
2274  {
2275  p->send(jvObj, true);
2276  ++i;
2277  }
2278  else
2279  {
2280  i = mStreamMaps[sPeerStatus].erase(i);
2281  }
2282  }
2283  }
2284 }
2285 
2286 void
2288 {
2289  using namespace std::chrono_literals;
2290  if (om == OperatingMode::CONNECTED)
2291  {
2294  }
2295  else if (om == OperatingMode::SYNCING)
2296  {
2297  if (app_.getLedgerMaster().getValidatedLedgerAge() >= 1min)
2299  }
2300 
2301  if ((om > OperatingMode::CONNECTED) && isBlocked())
2303 
2304  if (mMode == om)
2305  return;
2306 
2307  mMode = om;
2308 
2309  accounting_.mode(om);
2310 
2311  JLOG(m_journal.info()) << "STATE->" << strOperatingMode();
2312  pubServer();
2313 }
2314 
2315 bool
2317  std::shared_ptr<STValidation> const& val,
2318  std::string const& source)
2319 {
2320  JLOG(m_journal.trace())
2321  << "recvValidation " << val->getLedgerHash() << " from " << source;
2322 
2323  handleNewValidation(app_, val, source);
2324 
2325  pubValidation(val);
2326 
2327  // We will always relay trusted validations; if configured, we will
2328  // also relay all untrusted validations.
2329  return app_.config().RELAY_UNTRUSTED_VALIDATIONS == 1 || val->isTrusted();
2330 }
2331 
2334 {
2335  return mConsensus.getJson(true);
2336 }
2337 
2339 NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters)
2340 {
2342 
2343  // System-level warnings
2344  {
2345  Json::Value warnings{Json::arrayValue};
2346  if (isAmendmentBlocked())
2347  {
2348  Json::Value& w = warnings.append(Json::objectValue);
2349  w[jss::id] = warnRPC_AMENDMENT_BLOCKED;
2350  w[jss::message] =
2351  "This server is amendment blocked, and must be updated to be "
2352  "able to stay in sync with the network.";
2353  }
2354  if (isUNLBlocked())
2355  {
2356  Json::Value& w = warnings.append(Json::objectValue);
2357  w[jss::id] = warnRPC_EXPIRED_VALIDATOR_LIST;
2358  w[jss::message] =
2359  "This server has an expired validator list. validators.txt "
2360  "may be incorrectly configured or some [validator_list_sites] "
2361  "may be unreachable.";
2362  }
2363  if (admin && isAmendmentWarned())
2364  {
2365  Json::Value& w = warnings.append(Json::objectValue);
2366  w[jss::id] = warnRPC_UNSUPPORTED_MAJORITY;
2367  w[jss::message] =
2368  "One or more unsupported amendments have reached majority. "
2369  "Upgrade to the latest version before they are activated "
2370  "to avoid being amendment blocked.";
2371  if (auto const expected =
2373  {
2374  auto& d = w[jss::details] = Json::objectValue;
2375  d[jss::expected_date] = expected->time_since_epoch().count();
2376  d[jss::expected_date_UTC] = to_string(*expected);
2377  }
2378  }
2379 
2380  if (warnings.size())
2381  info[jss::warnings] = std::move(warnings);
2382  }
2383 
2384  // hostid: unique string describing the machine
2385  if (human)
2386  info[jss::hostid] = getHostId(admin);
2387 
2388  // domain: if configured with a domain, report it:
2389  if (!app_.config().SERVER_DOMAIN.empty())
2390  info[jss::server_domain] = app_.config().SERVER_DOMAIN;
2391 
2392  info[jss::build_version] = BuildInfo::getVersionString();
2393 
2394  info[jss::server_state] = strOperatingMode(admin);
2395 
2396  info[jss::time] = to_string(std::chrono::floor<std::chrono::microseconds>(
2398 
2399  if (needNetworkLedger_)
2400  info[jss::network_ledger] = "waiting";
2401 
2402  info[jss::validation_quorum] =
2403  static_cast<Json::UInt>(app_.validators().quorum());
2404 
2405  if (admin)
2406  {
2407  switch (app_.config().NODE_SIZE)
2408  {
2409  case 0:
2410  info[jss::node_size] = "tiny";
2411  break;
2412  case 1:
2413  info[jss::node_size] = "small";
2414  break;
2415  case 2:
2416  info[jss::node_size] = "medium";
2417  break;
2418  case 3:
2419  info[jss::node_size] = "large";
2420  break;
2421  case 4:
2422  info[jss::node_size] = "huge";
2423  break;
2424  }
2425 
2426  auto when = app_.validators().expires();
2427 
2428  if (!human)
2429  {
2430  if (when)
2431  info[jss::validator_list_expires] =
2432  safe_cast<Json::UInt>(when->time_since_epoch().count());
2433  else
2434  info[jss::validator_list_expires] = 0;
2435  }
2436  else
2437  {
2438  auto& x = (info[jss::validator_list] = Json::objectValue);
2439 
2440  x[jss::count] = static_cast<Json::UInt>(app_.validators().count());
2441 
2442  if (when)
2443  {
2444  if (*when == TimeKeeper::time_point::max())
2445  {
2446  x[jss::expiration] = "never";
2447  x[jss::status] = "active";
2448  }
2449  else
2450  {
2451  x[jss::expiration] = to_string(*when);
2452 
2453  if (*when > app_.timeKeeper().now())
2454  x[jss::status] = "active";
2455  else
2456  x[jss::status] = "expired";
2457  }
2458  }
2459  else
2460  {
2461  x[jss::status] = "unknown";
2462  x[jss::expiration] = "unknown";
2463  }
2464  }
2465  }
2466  info[jss::io_latency_ms] =
2467  static_cast<Json::UInt>(app_.getIOLatency().count());
2468 
2469  if (admin)
2470  {
2472  {
2473  info[jss::pubkey_validator] = toBase58(
2475  }
2476  else
2477  {
2478  info[jss::pubkey_validator] = "none";
2479  }
2480  }
2481 
2482  if (counters)
2483  {
2484  info[jss::counters] = app_.getPerfLog().countersJson();
2485 
2486  Json::Value nodestore(Json::objectValue);
2487  if (app_.getShardStore())
2488  app_.getShardStore()->getCountsJson(nodestore);
2489  else
2490  app_.getNodeStore().getCountsJson(nodestore);
2491  info[jss::counters][jss::nodestore] = nodestore;
2492  info[jss::current_activities] = app_.getPerfLog().currentJson();
2493  }
2494 
2495  info[jss::pubkey_node] =
2497 
2498  info[jss::complete_ledgers] = app_.getLedgerMaster().getCompleteLedgers();
2499 
2500  if (amendmentBlocked_)
2501  info[jss::amendment_blocked] = true;
2502 
2503  auto const fp = m_ledgerMaster.getFetchPackCacheSize();
2504 
2505  if (fp != 0)
2506  info[jss::fetch_pack] = Json::UInt(fp);
2507 
2508  if (!app_.config().reporting())
2509  info[jss::peers] = Json::UInt(app_.overlay().size());
2510 
2511  Json::Value lastClose = Json::objectValue;
2512  lastClose[jss::proposers] = Json::UInt(mConsensus.prevProposers());
2513 
2514  if (human)
2515  {
2516  lastClose[jss::converge_time_s] =
2518  }
2519  else
2520  {
2521  lastClose[jss::converge_time] =
2523  }
2524 
2525  info[jss::last_close] = lastClose;
2526 
2527  // info[jss::consensus] = mConsensus.getJson();
2528 
2529  if (admin)
2530  info[jss::load] = m_job_queue.getJson();
2531 
2532  if (!app_.config().reporting())
2533  {
2534  if (auto const netid = app_.overlay().networkID())
2535  info[jss::network_id] = static_cast<Json::UInt>(*netid);
2536 
2537  auto const escalationMetrics =
2539 
2540  auto const loadFactorServer = app_.getFeeTrack().getLoadFactor();
2541  auto const loadBaseServer = app_.getFeeTrack().getLoadBase();
2542  /* Scale the escalated fee level to unitless "load factor".
2543  In practice, this just strips the units, but it will continue
2544  to work correctly if either base value ever changes. */
2545  auto const loadFactorFeeEscalation =
2546  mulDiv(
2547  escalationMetrics.openLedgerFeeLevel,
2548  loadBaseServer,
2549  escalationMetrics.referenceFeeLevel)
2550  .value_or(ripple::muldiv_max);
2551 
2552  auto const loadFactor = std::max(
2553  safe_cast<std::uint64_t>(loadFactorServer),
2554  loadFactorFeeEscalation);
2555 
2556  if (!human)
2557  {
2558  info[jss::load_base] = loadBaseServer;
2559  info[jss::load_factor] = trunc32(loadFactor);
2560  info[jss::load_factor_server] = loadFactorServer;
2561 
2562  /* Json::Value doesn't support uint64, so clamp to max
2563  uint32 value. This is mostly theoretical, since there
2564  probably isn't enough extant XRP to drive the factor
2565  that high.
2566  */
2567  info[jss::load_factor_fee_escalation] =
2568  escalationMetrics.openLedgerFeeLevel.jsonClipped();
2569  info[jss::load_factor_fee_queue] =
2570  escalationMetrics.minProcessingFeeLevel.jsonClipped();
2571  info[jss::load_factor_fee_reference] =
2572  escalationMetrics.referenceFeeLevel.jsonClipped();
2573  }
2574  else
2575  {
2576  info[jss::load_factor] =
2577  static_cast<double>(loadFactor) / loadBaseServer;
2578 
2579  if (loadFactorServer != loadFactor)
2580  info[jss::load_factor_server] =
2581  static_cast<double>(loadFactorServer) / loadBaseServer;
2582 
2583  if (admin)
2584  {
2586  if (fee != loadBaseServer)
2587  info[jss::load_factor_local] =
2588  static_cast<double>(fee) / loadBaseServer;
2589  fee = app_.getFeeTrack().getRemoteFee();
2590  if (fee != loadBaseServer)
2591  info[jss::load_factor_net] =
2592  static_cast<double>(fee) / loadBaseServer;
2593  fee = app_.getFeeTrack().getClusterFee();
2594  if (fee != loadBaseServer)
2595  info[jss::load_factor_cluster] =
2596  static_cast<double>(fee) / loadBaseServer;
2597  }
2598  if (escalationMetrics.openLedgerFeeLevel !=
2599  escalationMetrics.referenceFeeLevel &&
2600  (admin || loadFactorFeeEscalation != loadFactor))
2601  info[jss::load_factor_fee_escalation] =
2602  escalationMetrics.openLedgerFeeLevel.decimalFromReference(
2603  escalationMetrics.referenceFeeLevel);
2604  if (escalationMetrics.minProcessingFeeLevel !=
2605  escalationMetrics.referenceFeeLevel)
2606  info[jss::load_factor_fee_queue] =
2607  escalationMetrics.minProcessingFeeLevel
2608  .decimalFromReference(
2609  escalationMetrics.referenceFeeLevel);
2610  }
2611  }
2612 
2613  bool valid = false;
2614  auto lpClosed = m_ledgerMaster.getValidatedLedger();
2615 
2616  if (lpClosed)
2617  valid = true;
2618  else if (!app_.config().reporting())
2619  lpClosed = m_ledgerMaster.getClosedLedger();
2620 
2621  if (lpClosed)
2622  {
2623  XRPAmount const baseFee = lpClosed->fees().base;
2625  l[jss::seq] = Json::UInt(lpClosed->info().seq);
2626  l[jss::hash] = to_string(lpClosed->info().hash);
2627 
2628  if (!human)
2629  {
2630  l[jss::base_fee] = baseFee.jsonClipped();
2631  l[jss::reserve_base] =
2632  lpClosed->fees().accountReserve(0).jsonClipped();
2633  l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
2634  l[jss::close_time] = Json::Value::UInt(
2635  lpClosed->info().closeTime.time_since_epoch().count());
2636  }
2637  else
2638  {
2639  l[jss::base_fee_xrp] = baseFee.decimalXRP();
2640  l[jss::reserve_base_xrp] =
2641  lpClosed->fees().accountReserve(0).decimalXRP();
2642  l[jss::reserve_inc_xrp] = lpClosed->fees().increment.decimalXRP();
2643 
2644  if (auto const closeOffset = app_.timeKeeper().closeOffset();
2645  std::abs(closeOffset.count()) >= 60)
2646  l[jss::close_time_offset] =
2647  static_cast<std::uint32_t>(closeOffset.count());
2648 
2649 #if RIPPLED_REPORTING
2650  std::int64_t const dbAge =
2652  l[jss::age] = Json::UInt(dbAge);
2653 #else
2654  constexpr std::chrono::seconds highAgeThreshold{1000000};
2656  {
2657  auto const age = m_ledgerMaster.getValidatedLedgerAge();
2658  l[jss::age] =
2659  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2660  }
2661  else
2662  {
2663  auto lCloseTime = lpClosed->info().closeTime;
2664  auto closeTime = app_.timeKeeper().closeTime();
2665  if (lCloseTime <= closeTime)
2666  {
2667  using namespace std::chrono_literals;
2668  auto age = closeTime - lCloseTime;
2669  l[jss::age] =
2670  Json::UInt(age < highAgeThreshold ? age.count() : 0);
2671  }
2672  }
2673 #endif
2674  }
2675 
2676  if (valid)
2677  info[jss::validated_ledger] = l;
2678  else
2679  info[jss::closed_ledger] = l;
2680 
2681  auto lpPublished = m_ledgerMaster.getPublishedLedger();
2682  if (!lpPublished)
2683  info[jss::published_ledger] = "none";
2684  else if (lpPublished->info().seq != lpClosed->info().seq)
2685  info[jss::published_ledger] = lpPublished->info().seq;
2686  }
2687 
2688  accounting_.json(info);
2689  info[jss::uptime] = UptimeClock::now().time_since_epoch().count();
2690  if (!app_.config().reporting())
2691  {
2692  info[jss::jq_trans_overflow] =
2694  info[jss::peer_disconnects] =
2696  info[jss::peer_disconnects_resources] =
2698  }
2699  else
2700  {
2701  info["reporting"] = app_.getReportingETL().getInfo();
2702  }
2703 
2704  // This array must be sorted in increasing order.
2705  static constexpr std::array<std::string_view, 7> protocols{
2706  "http", "https", "peer", "ws", "ws2", "wss", "wss2"};
2707  static_assert(std::is_sorted(std::begin(protocols), std::end(protocols)));
2708  {
2710  for (auto const& port : app_.getServerHandler().setup().ports)
2711  {
2712  // Don't publish admin ports for non-admin users
2713  if (!admin &&
2714  !(port.admin_nets_v4.empty() && port.admin_nets_v6.empty() &&
2715  port.admin_user.empty() && port.admin_password.empty()))
2716  continue;
2719  std::begin(port.protocol),
2720  std::end(port.protocol),
2721  std::begin(protocols),
2722  std::end(protocols),
2723  std::back_inserter(proto));
2724  if (!proto.empty())
2725  {
2726  auto& jv = ports.append(Json::Value(Json::objectValue));
2727  jv[jss::port] = std::to_string(port.port);
2728  jv[jss::protocol] = Json::Value{Json::arrayValue};
2729  for (auto const& p : proto)
2730  jv[jss::protocol].append(p);
2731  }
2732  }
2733 
2734  if (app_.config().exists("port_grpc"))
2735  {
2736  auto const& grpcSection = app_.config().section("port_grpc");
2737  auto const optPort = grpcSection.get("port");
2738  if (optPort && grpcSection.get("ip"))
2739  {
2740  auto& jv = ports.append(Json::Value(Json::objectValue));
2741  jv[jss::port] = *optPort;
2742  jv[jss::protocol] = Json::Value{Json::arrayValue};
2743  jv[jss::protocol].append("grpc");
2744  }
2745  }
2746  info[jss::ports] = std::move(ports);
2747  }
2748 
2749  return info;
2750 }
2751 
2752 void
2754 {
2756 }
2757 
2760 {
2761  return app_.getInboundLedgers().getInfo();
2762 }
2763 
2764 void
2766  std::shared_ptr<ReadView const> const& ledger,
2767  std::shared_ptr<STTx const> const& transaction,
2768  TER result)
2769 {
2770  MultiApiJson jvObj =
2771  transJson(transaction, result, false, ledger, std::nullopt);
2772 
2773  {
2775 
2776  auto it = mStreamMaps[sRTTransactions].begin();
2777  while (it != mStreamMaps[sRTTransactions].end())
2778  {
2779  InfoSub::pointer p = it->second.lock();
2780 
2781  if (p)
2782  {
2783  p->send(
2784  jvObj.select(apiVersionSelector(p->getApiVersion())), true);
2785  ++it;
2786  }
2787  else
2788  {
2789  it = mStreamMaps[sRTTransactions].erase(it);
2790  }
2791  }
2792  }
2793 
2794  pubProposedAccountTransaction(ledger, transaction, result);
2795 }
2796 
2797 void
2799 {
2800  // reporting does not forward validated transactions
2801  // validated transactions will be published to the proper streams when the
2802  // etl process writes a validated ledger
2803  if (jvObj[jss::validated].asBool())
2804  return;
2805  {
2807 
2808  auto it = mStreamMaps[sRTTransactions].begin();
2809  while (it != mStreamMaps[sRTTransactions].end())
2810  {
2811  InfoSub::pointer p = it->second.lock();
2812 
2813  if (p)
2814  {
2815  p->send(jvObj, true);
2816  ++it;
2817  }
2818  else
2819  {
2820  it = mStreamMaps[sRTTransactions].erase(it);
2821  }
2822  }
2823  }
2824 
2826 }
2827 
2828 void
2830 {
2832 
2833  for (auto i = mStreamMaps[sValidations].begin();
2834  i != mStreamMaps[sValidations].end();)
2835  {
2836  if (auto p = i->second.lock())
2837  {
2838  p->send(jvObj, true);
2839  ++i;
2840  }
2841  else
2842  {
2843  i = mStreamMaps[sValidations].erase(i);
2844  }
2845  }
2846 }
2847 
2848 void
2850 {
2852 
2853  for (auto i = mStreamMaps[sManifests].begin();
2854  i != mStreamMaps[sManifests].end();)
2855  {
2856  if (auto p = i->second.lock())
2857  {
2858  p->send(jvObj, true);
2859  ++i;
2860  }
2861  else
2862  {
2863  i = mStreamMaps[sManifests].erase(i);
2864  }
2865  }
2866 }
2867 
2868 static void
2870 {
2871  for (auto& jv : jvObj)
2872  {
2873  if (jv.isObject())
2874  {
2875  getAccounts(jv, accounts);
2876  }
2877  else if (jv.isString())
2878  {
2879  auto account = RPC::accountFromStringStrict(jv.asString());
2880  if (account)
2881  accounts.push_back(*account);
2882  }
2883  }
2884 }
2885 
2886 void
2888 {
2890  int iProposed = 0;
2891  // check if there are any subscribers before attempting to parse the JSON
2892  {
2894 
2895  if (mSubRTAccount.empty())
2896  return;
2897  }
2898 
2899  // parse the JSON outside of the lock
2900  std::vector<AccountID> accounts;
2901  if (jvObj.isMember(jss::transaction))
2902  {
2903  try
2904  {
2905  getAccounts(jvObj[jss::transaction], accounts);
2906  }
2907  catch (...)
2908  {
2909  JLOG(m_journal.debug())
2910  << __func__ << " : "
2911  << "error parsing json for accounts affected";
2912  return;
2913  }
2914  }
2915  {
2917 
2918  if (!mSubRTAccount.empty())
2919  {
2920  for (auto const& affectedAccount : accounts)
2921  {
2922  auto simiIt = mSubRTAccount.find(affectedAccount);
2923  if (simiIt != mSubRTAccount.end())
2924  {
2925  auto it = simiIt->second.begin();
2926 
2927  while (it != simiIt->second.end())
2928  {
2929  InfoSub::pointer p = it->second.lock();
2930 
2931  if (p)
2932  {
2933  notify.insert(p);
2934  ++it;
2935  ++iProposed;
2936  }
2937  else
2938  it = simiIt->second.erase(it);
2939  }
2940  }
2941  }
2942  }
2943  }
2944  JLOG(m_journal.trace()) << "forwardProposedAccountTransaction:"
2945  << " iProposed=" << iProposed;
2946 
2947  if (!notify.empty())
2948  {
2949  for (InfoSub::ref isrListener : notify)
2950  isrListener->send(jvObj, true);
2951  }
2952 }
2953 
2954 void
2956 {
2957  // Ledgers are published only when they acquire sufficient validations
2958  // Holes are filled across connection loss or other catastrophe
2959 
2960  std::shared_ptr<AcceptedLedger> alpAccepted =
2961  app_.getAcceptedLedgerCache().fetch(lpAccepted->info().hash);
2962  if (!alpAccepted)
2963  {
2964  alpAccepted = std::make_shared<AcceptedLedger>(lpAccepted, app_);
2965  app_.getAcceptedLedgerCache().canonicalize_replace_client(
2966  lpAccepted->info().hash, alpAccepted);
2967  }
2968 
2969  assert(alpAccepted->getLedger().get() == lpAccepted.get());
2970 
2971  {
2972  JLOG(m_journal.debug())
2973  << "Publishing ledger " << lpAccepted->info().seq << " "
2974  << lpAccepted->info().hash;
2975 
2977 
2978  if (!mStreamMaps[sLedger].empty())
2979  {
2981 
2982  jvObj[jss::type] = "ledgerClosed";
2983  jvObj[jss::ledger_index] = lpAccepted->info().seq;
2984  jvObj[jss::ledger_hash] = to_string(lpAccepted->info().hash);
2985  jvObj[jss::ledger_time] = Json::Value::UInt(
2986  lpAccepted->info().closeTime.time_since_epoch().count());
2987 
2988  if (!lpAccepted->rules().enabled(featureXRPFees))
2989  jvObj[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
2990  jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
2991  jvObj[jss::reserve_base] =
2992  lpAccepted->fees().accountReserve(0).jsonClipped();
2993  jvObj[jss::reserve_inc] =
2994  lpAccepted->fees().increment.jsonClipped();
2995 
2996  jvObj[jss::txn_count] = Json::UInt(alpAccepted->size());
2997 
2999  {
3000  jvObj[jss::validated_ledgers] =
3002  }
3003 
3004  auto it = mStreamMaps[sLedger].begin();
3005  while (it != mStreamMaps[sLedger].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[sLedger].erase(it);
3015  }
3016  }
3017 
3018  if (!mStreamMaps[sBookChanges].empty())
3019  {
3020  Json::Value jvObj = ripple::RPC::computeBookChanges(lpAccepted);
3021 
3022  auto it = mStreamMaps[sBookChanges].begin();
3023  while (it != mStreamMaps[sBookChanges].end())
3024  {
3025  InfoSub::pointer p = it->second.lock();
3026  if (p)
3027  {
3028  p->send(jvObj, true);
3029  ++it;
3030  }
3031  else
3032  it = mStreamMaps[sBookChanges].erase(it);
3033  }
3034  }
3035 
3036  {
3037  static bool firstTime = true;
3038  if (firstTime)
3039  {
3040  // First validated ledger, start delayed SubAccountHistory
3041  firstTime = false;
3042  for (auto& outer : mSubAccountHistory)
3043  {
3044  for (auto& inner : outer.second)
3045  {
3046  auto& subInfo = inner.second;
3047  if (subInfo.index_->separationLedgerSeq_ == 0)
3048  {
3050  alpAccepted->getLedger(), subInfo);
3051  }
3052  }
3053  }
3054  }
3055  }
3056  }
3057 
3058  // Don't lock since pubAcceptedTransaction is locking.
3059  for (auto const& accTx : *alpAccepted)
3060  {
3061  JLOG(m_journal.trace()) << "pubAccepted: " << accTx->getJson();
3063  lpAccepted, *accTx, accTx == *(--alpAccepted->end()));
3064  }
3065 }
3066 
3067 void
3069 {
3070  if (app_.config().reporting())
3071  return;
3072  ServerFeeSummary f{
3073  app_.openLedger().current()->fees().base,
3075  app_.getFeeTrack()};
3076 
3077  // only schedule the job if something has changed
3078  if (f != mLastFeeSummary)
3079  {
3081  jtCLIENT_FEE_CHANGE, "reportFeeChange->pubServer", [this]() {
3082  pubServer();
3083  });
3084  }
3085 }
3086 
3087 void
3089 {
3092  "reportConsensusStateChange->pubConsensus",
3093  [this, phase]() { pubConsensus(phase); });
3094 }
3095 
3096 inline void
3098 {
3099  m_localTX->sweep(view);
3100 }
3101 inline std::size_t
3103 {
3104  return m_localTX->size();
3105 }
3106 
3107 // This routine should only be used to publish accepted or validated
3108 // transactions.
3111  std::shared_ptr<STTx const> const& transaction,
3112  TER result,
3113  bool validated,
3114  std::shared_ptr<ReadView const> const& ledger,
3116 {
3118  std::string sToken;
3119  std::string sHuman;
3120 
3121  transResultInfo(result, sToken, sHuman);
3122 
3123  jvObj[jss::type] = "transaction";
3124  // NOTE jvObj is not a finished object for either API version. After
3125  // it's populated, we need to finish it for a specific API version. This is
3126  // done in a loop, near the end of this function.
3127  jvObj[jss::transaction] =
3128  transaction->getJson(JsonOptions::disable_API_prior_V2, false);
3129 
3130  if (meta)
3131  {
3132  jvObj[jss::meta] = meta->get().getJson(JsonOptions::none);
3134  jvObj[jss::meta], *ledger, transaction, meta->get());
3135  }
3136 
3137  if (!ledger->open())
3138  jvObj[jss::ledger_hash] = to_string(ledger->info().hash);
3139 
3140  if (validated)
3141  {
3142  jvObj[jss::ledger_index] = ledger->info().seq;
3143  jvObj[jss::transaction][jss::date] =
3144  ledger->info().closeTime.time_since_epoch().count();
3145  jvObj[jss::validated] = true;
3146  jvObj[jss::close_time_iso] = to_string_iso(ledger->info().closeTime);
3147 
3148  // WRITEME: Put the account next seq here
3149  }
3150  else
3151  {
3152  jvObj[jss::validated] = false;
3153  jvObj[jss::ledger_current_index] = ledger->info().seq;
3154  }
3155 
3156  jvObj[jss::status] = validated ? "closed" : "proposed";
3157  jvObj[jss::engine_result] = sToken;
3158  jvObj[jss::engine_result_code] = result;
3159  jvObj[jss::engine_result_message] = sHuman;
3160 
3161  if (transaction->getTxnType() == ttOFFER_CREATE)
3162  {
3163  auto const account = transaction->getAccountID(sfAccount);
3164  auto const amount = transaction->getFieldAmount(sfTakerGets);
3165 
3166  // If the offer create is not self funded then add the owner balance
3167  if (account != amount.issue().account)
3168  {
3169  auto const ownerFunds = accountFunds(
3170  *ledger,
3171  account,
3172  amount,
3174  app_.journal("View"));
3175  jvObj[jss::transaction][jss::owner_funds] = ownerFunds.getText();
3176  }
3177  }
3178 
3179  std::string const hash = to_string(transaction->getTransactionID());
3180  MultiApiJson multiObj{jvObj};
3181  visit<RPC::apiMinimumSupportedVersion, RPC::apiMaximumValidVersion>(
3182  multiObj, //
3183  [&](Json::Value& jvTx, unsigned int apiVersion) {
3185  jvTx[jss::transaction], transaction->getTxnType(), apiVersion);
3186 
3187  if (apiVersion > 1)
3188  {
3189  jvTx[jss::tx_json] = jvTx.removeMember(jss::transaction);
3190  jvTx[jss::hash] = hash;
3191  }
3192  else
3193  {
3194  jvTx[jss::transaction][jss::hash] = hash;
3195  }
3196  });
3197 
3198  return multiObj;
3199 }
3200 
3201 void
3203  std::shared_ptr<ReadView const> const& ledger,
3204  const AcceptedLedgerTx& transaction,
3205  bool last)
3206 {
3207  auto const& stTxn = transaction.getTxn();
3208 
3209  // Create two different Json objects, for different API versions
3210  auto const metaRef = std::ref(transaction.getMeta());
3211  auto const trResult = transaction.getResult();
3212  MultiApiJson jvObj = transJson(stTxn, trResult, true, ledger, metaRef);
3213 
3214  {
3216 
3217  auto it = mStreamMaps[sTransactions].begin();
3218  while (it != mStreamMaps[sTransactions].end())
3219  {
3220  InfoSub::pointer p = it->second.lock();
3221 
3222  if (p)
3223  {
3224  p->send(
3225  jvObj.select(apiVersionSelector(p->getApiVersion())), true);
3226  ++it;
3227  }
3228  else
3229  it = mStreamMaps[sTransactions].erase(it);
3230  }
3231 
3232  it = mStreamMaps[sRTTransactions].begin();
3233 
3234  while (it != mStreamMaps[sRTTransactions].end())
3235  {
3236  InfoSub::pointer p = it->second.lock();
3237 
3238  if (p)
3239  {
3240  p->send(
3241  jvObj.select(apiVersionSelector(p->getApiVersion())), true);
3242  ++it;
3243  }
3244  else
3245  it = mStreamMaps[sRTTransactions].erase(it);
3246  }
3247  }
3248 
3249  if (transaction.getResult() == tesSUCCESS)
3250  app_.getOrderBookDB().processTxn(ledger, transaction, jvObj);
3251 
3252  pubAccountTransaction(ledger, transaction, last);
3253 }
3254 
3255 void
3257  std::shared_ptr<ReadView const> const& ledger,
3258  AcceptedLedgerTx const& transaction,
3259  bool last)
3260 {
3262  int iProposed = 0;
3263  int iAccepted = 0;
3264 
3265  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3266  auto const currLedgerSeq = ledger->seq();
3267  {
3269 
3270  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3272  {
3273  for (auto const& affectedAccount : transaction.getAffected())
3274  {
3275  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3276  simiIt != mSubRTAccount.end())
3277  {
3278  auto it = simiIt->second.begin();
3279 
3280  while (it != simiIt->second.end())
3281  {
3282  InfoSub::pointer p = it->second.lock();
3283 
3284  if (p)
3285  {
3286  notify.insert(p);
3287  ++it;
3288  ++iProposed;
3289  }
3290  else
3291  it = simiIt->second.erase(it);
3292  }
3293  }
3294 
3295  if (auto simiIt = mSubAccount.find(affectedAccount);
3296  simiIt != mSubAccount.end())
3297  {
3298  auto it = simiIt->second.begin();
3299  while (it != simiIt->second.end())
3300  {
3301  InfoSub::pointer p = it->second.lock();
3302 
3303  if (p)
3304  {
3305  notify.insert(p);
3306  ++it;
3307  ++iAccepted;
3308  }
3309  else
3310  it = simiIt->second.erase(it);
3311  }
3312  }
3313 
3314  if (auto histoIt = mSubAccountHistory.find(affectedAccount);
3315  histoIt != mSubAccountHistory.end())
3316  {
3317  auto& subs = histoIt->second;
3318  auto it = subs.begin();
3319  while (it != subs.end())
3320  {
3321  SubAccountHistoryInfoWeak const& info = it->second;
3322  if (currLedgerSeq <= info.index_->separationLedgerSeq_)
3323  {
3324  ++it;
3325  continue;
3326  }
3327 
3328  if (auto isSptr = info.sinkWptr_.lock(); isSptr)
3329  {
3330  accountHistoryNotify.emplace_back(
3331  SubAccountHistoryInfo{isSptr, info.index_});
3332  ++it;
3333  }
3334  else
3335  {
3336  it = subs.erase(it);
3337  }
3338  }
3339  if (subs.empty())
3340  mSubAccountHistory.erase(histoIt);
3341  }
3342  }
3343  }
3344  }
3345 
3346  JLOG(m_journal.trace())
3347  << "pubAccountTransaction: "
3348  << "proposed=" << iProposed << ", accepted=" << iAccepted;
3349 
3350  if (!notify.empty() || !accountHistoryNotify.empty())
3351  {
3352  auto const& stTxn = transaction.getTxn();
3353 
3354  // Create two different Json objects, for different API versions
3355  auto const metaRef = std::ref(transaction.getMeta());
3356  auto const trResult = transaction.getResult();
3357  MultiApiJson jvObj = transJson(stTxn, trResult, true, ledger, metaRef);
3358 
3359  for (InfoSub::ref isrListener : notify)
3360  {
3361  isrListener->send(
3362  jvObj.select(apiVersionSelector(isrListener->getApiVersion())),
3363  true);
3364  }
3365 
3366  if (last)
3367  jvObj.set(jss::account_history_boundary, true);
3368 
3369  assert(
3370  jvObj.isMember(jss::account_history_tx_stream) ==
3371  MultiApiJson::none);
3372  for (auto& info : accountHistoryNotify)
3373  {
3374  auto& index = info.index_;
3375  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3376  jvObj.set(jss::account_history_tx_first, true);
3377 
3378  jvObj.set(jss::account_history_tx_index, index->forwardTxIndex_++);
3379 
3380  info.sink_->send(
3381  jvObj.select(apiVersionSelector(info.sink_->getApiVersion())),
3382  true);
3383  }
3384  }
3385 }
3386 
3387 void
3389  std::shared_ptr<ReadView const> const& ledger,
3390  std::shared_ptr<STTx const> const& tx,
3391  TER result)
3392 {
3394  int iProposed = 0;
3395 
3396  std::vector<SubAccountHistoryInfo> accountHistoryNotify;
3397 
3398  {
3400 
3401  if (mSubRTAccount.empty())
3402  return;
3403 
3404  if (!mSubAccount.empty() || !mSubRTAccount.empty() ||
3406  {
3407  for (auto const& affectedAccount : tx->getMentionedAccounts())
3408  {
3409  if (auto simiIt = mSubRTAccount.find(affectedAccount);
3410  simiIt != mSubRTAccount.end())
3411  {
3412  auto it = simiIt->second.begin();
3413 
3414  while (it != simiIt->second.end())
3415  {
3416  InfoSub::pointer p = it->second.lock();
3417 
3418  if (p)
3419  {
3420  notify.insert(p);
3421  ++it;
3422  ++iProposed;
3423  }
3424  else
3425  it = simiIt->second.erase(it);
3426  }
3427  }
3428  }
3429  }
3430  }
3431 
3432  JLOG(m_journal.trace()) << "pubProposedAccountTransaction: " << iProposed;
3433 
3434  if (!notify.empty() || !accountHistoryNotify.empty())
3435  {
3436  // Create two different Json objects, for different API versions
3437  MultiApiJson jvObj = transJson(tx, result, false, ledger, std::nullopt);
3438 
3439  for (InfoSub::ref isrListener : notify)
3440  isrListener->send(
3441  jvObj.select(apiVersionSelector(isrListener->getApiVersion())),
3442  true);
3443 
3444  assert(
3445  jvObj.isMember(jss::account_history_tx_stream) ==
3446  MultiApiJson::none);
3447  for (auto& info : accountHistoryNotify)
3448  {
3449  auto& index = info.index_;
3450  if (index->forwardTxIndex_ == 0 && !index->haveHistorical_)
3451  jvObj.set(jss::account_history_tx_first, true);
3452  jvObj.set(jss::account_history_tx_index, index->forwardTxIndex_++);
3453  info.sink_->send(
3454  jvObj.select(apiVersionSelector(info.sink_->getApiVersion())),
3455  true);
3456  }
3457  }
3458 }
3459 
3460 //
3461 // Monitoring
3462 //
3463 
3464 void
3466  InfoSub::ref isrListener,
3467  hash_set<AccountID> const& vnaAccountIDs,
3468  bool rt)
3469 {
3470  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3471 
3472  for (auto const& naAccountID : vnaAccountIDs)
3473  {
3474  JLOG(m_journal.trace())
3475  << "subAccount: account: " << toBase58(naAccountID);
3476 
3477  isrListener->insertSubAccountInfo(naAccountID, rt);
3478  }
3479 
3481 
3482  for (auto const& naAccountID : vnaAccountIDs)
3483  {
3484  auto simIterator = subMap.find(naAccountID);
3485  if (simIterator == subMap.end())
3486  {
3487  // Not found, note that account has a new single listner.
3488  SubMapType usisElement;
3489  usisElement[isrListener->getSeq()] = isrListener;
3490  // VFALCO NOTE This is making a needless copy of naAccountID
3491  subMap.insert(simIterator, make_pair(naAccountID, usisElement));
3492  }
3493  else
3494  {
3495  // Found, note that the account has another listener.
3496  simIterator->second[isrListener->getSeq()] = isrListener;
3497  }
3498  }
3499 }
3500 
3501 void
3503  InfoSub::ref isrListener,
3504  hash_set<AccountID> const& vnaAccountIDs,
3505  bool rt)
3506 {
3507  for (auto const& naAccountID : vnaAccountIDs)
3508  {
3509  // Remove from the InfoSub
3510  isrListener->deleteSubAccountInfo(naAccountID, rt);
3511  }
3512 
3513  // Remove from the server
3514  unsubAccountInternal(isrListener->getSeq(), vnaAccountIDs, rt);
3515 }
3516 
3517 void
3519  std::uint64_t uSeq,
3520  hash_set<AccountID> const& vnaAccountIDs,
3521  bool rt)
3522 {
3524 
3525  SubInfoMapType& subMap = rt ? mSubRTAccount : mSubAccount;
3526 
3527  for (auto const& naAccountID : vnaAccountIDs)
3528  {
3529  auto simIterator = subMap.find(naAccountID);
3530 
3531  if (simIterator != subMap.end())
3532  {
3533  // Found
3534  simIterator->second.erase(uSeq);
3535 
3536  if (simIterator->second.empty())
3537  {
3538  // Don't need hash entry.
3539  subMap.erase(simIterator);
3540  }
3541  }
3542  }
3543 }
3544 
3545 void
3547 {
3548  enum DatabaseType { Postgres, Sqlite, None };
3549  static const auto databaseType = [&]() -> DatabaseType {
3550 #ifdef RIPPLED_REPORTING
3551  if (app_.config().reporting())
3552  {
3553  // Use a dynamic_cast to return DatabaseType::None
3554  // on failure.
3555  if (dynamic_cast<PostgresDatabase*>(&app_.getRelationalDatabase()))
3556  {
3557  return DatabaseType::Postgres;
3558  }
3559  return DatabaseType::None;
3560  }
3561  else
3562  {
3563  // Use a dynamic_cast to return DatabaseType::None
3564  // on failure.
3565  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3566  {
3567  return DatabaseType::Sqlite;
3568  }
3569  return DatabaseType::None;
3570  }
3571 #else
3572  // Use a dynamic_cast to return DatabaseType::None
3573  // on failure.
3574  if (dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase()))
3575  {
3576  return DatabaseType::Sqlite;
3577  }
3578  return DatabaseType::None;
3579 #endif
3580  }();
3581 
3582  if (databaseType == DatabaseType::None)
3583  {
3584  JLOG(m_journal.error())
3585  << "AccountHistory job for account "
3586  << toBase58(subInfo.index_->accountId_) << " no database";
3587  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3588  {
3589  sptr->send(rpcError(rpcINTERNAL), true);
3590  unsubAccountHistory(sptr, subInfo.index_->accountId_, false);
3591  }
3592  return;
3593  }
3594 
3597  "AccountHistoryTxStream",
3598  [this, dbType = databaseType, subInfo]() {
3599  auto const& accountId = subInfo.index_->accountId_;
3600  auto& lastLedgerSeq = subInfo.index_->historyLastLedgerSeq_;
3601  auto& txHistoryIndex = subInfo.index_->historyTxIndex_;
3602 
3603  JLOG(m_journal.trace())
3604  << "AccountHistory job for account " << toBase58(accountId)
3605  << " started. lastLedgerSeq=" << lastLedgerSeq;
3606 
3607  auto isFirstTx = [&](std::shared_ptr<Transaction> const& tx,
3608  std::shared_ptr<TxMeta> const& meta) -> bool {
3609  /*
3610  * genesis account: first tx is the one with seq 1
3611  * other account: first tx is the one created the account
3612  */
3613  if (accountId == genesisAccountId)
3614  {
3615  auto stx = tx->getSTransaction();
3616  if (stx->getAccountID(sfAccount) == accountId &&
3617  stx->getSeqProxy().value() == 1)
3618  return true;
3619  }
3620 
3621  for (auto& node : meta->getNodes())
3622  {
3623  if (node.getFieldU16(sfLedgerEntryType) != ltACCOUNT_ROOT)
3624  continue;
3625 
3626  if (node.isFieldPresent(sfNewFields))
3627  {
3628  if (auto inner = dynamic_cast<const STObject*>(
3629  node.peekAtPField(sfNewFields));
3630  inner)
3631  {
3632  if (inner->isFieldPresent(sfAccount) &&
3633  inner->getAccountID(sfAccount) == accountId)
3634  {
3635  return true;
3636  }
3637  }
3638  }
3639  }
3640 
3641  return false;
3642  };
3643 
3644  auto send = [&](Json::Value const& jvObj,
3645  bool unsubscribe) -> bool {
3646  if (auto sptr = subInfo.sinkWptr_.lock())
3647  {
3648  sptr->send(jvObj, true);
3649  if (unsubscribe)
3650  unsubAccountHistory(sptr, accountId, false);
3651  return true;
3652  }
3653 
3654  return false;
3655  };
3656 
3657  auto sendMultiApiJson = [&](MultiApiJson const& jvObj,
3658  bool unsubscribe) -> bool {
3659  if (auto sptr = subInfo.sinkWptr_.lock())
3660  {
3661  sptr->send(
3662  jvObj.select(apiVersionSelector(sptr->getApiVersion())),
3663  true);
3664 
3665  if (unsubscribe)
3666  unsubAccountHistory(sptr, accountId, false);
3667  return true;
3668  }
3669 
3670  return false;
3671  };
3672 
3673  auto getMoreTxns =
3674  [&](std::uint32_t minLedger,
3675  std::uint32_t maxLedger,
3680  switch (dbType)
3681  {
3682  case Postgres: {
3683  auto db = static_cast<PostgresDatabase*>(
3686  args.account = accountId;
3687  LedgerRange range{minLedger, maxLedger};
3688  args.ledger = range;
3689  args.marker = marker;
3690  auto [txResult, status] = db->getAccountTx(args);
3691  if (status != rpcSUCCESS)
3692  {
3693  JLOG(m_journal.debug())
3694  << "AccountHistory job for account "
3695  << toBase58(accountId)
3696  << " getAccountTx failed";
3697  return {};
3698  }
3699 
3700  if (auto txns =
3701  std::get_if<RelationalDatabase::AccountTxs>(
3702  &txResult.transactions);
3703  txns)
3704  {
3705  return std::make_pair(*txns, txResult.marker);
3706  }
3707  else
3708  {
3709  JLOG(m_journal.debug())
3710  << "AccountHistory job for account "
3711  << toBase58(accountId)
3712  << " getAccountTx wrong data";
3713  return {};
3714  }
3715  }
3716  case Sqlite: {
3717  auto db = static_cast<SQLiteDatabase*>(
3720  accountId, minLedger, maxLedger, marker, 0, true};
3721  return db->newestAccountTxPage(options);
3722  }
3723  default: {
3724  assert(false);
3725  return {};
3726  }
3727  }
3728  };
3729 
3730  /*
3731  * search backward until the genesis ledger or asked to stop
3732  */
3733  while (lastLedgerSeq >= 2 && !subInfo.index_->stopHistorical_)
3734  {
3735  int feeChargeCount = 0;
3736  if (auto sptr = subInfo.sinkWptr_.lock(); sptr)
3737  {
3738  sptr->getConsumer().charge(Resource::feeMediumBurdenRPC);
3739  ++feeChargeCount;
3740  }
3741  else
3742  {
3743  JLOG(m_journal.trace())
3744  << "AccountHistory job for account "
3745  << toBase58(accountId) << " no InfoSub. Fee charged "
3746  << feeChargeCount << " times.";
3747  return;
3748  }
3749 
3750  // try to search in 1024 ledgers till reaching genesis ledgers
3751  auto startLedgerSeq =
3752  (lastLedgerSeq > 1024 + 2 ? lastLedgerSeq - 1024 : 2);
3753  JLOG(m_journal.trace())
3754  << "AccountHistory job for account " << toBase58(accountId)
3755  << ", working on ledger range [" << startLedgerSeq << ","
3756  << lastLedgerSeq << "]";
3757 
3758  auto haveRange = [&]() -> bool {
3759  std::uint32_t validatedMin = UINT_MAX;
3760  std::uint32_t validatedMax = 0;
3761  auto haveSomeValidatedLedgers =
3763  validatedMin, validatedMax);
3764 
3765  return haveSomeValidatedLedgers &&
3766  validatedMin <= startLedgerSeq &&
3767  lastLedgerSeq <= validatedMax;
3768  }();
3769 
3770  if (!haveRange)
3771  {
3772  JLOG(m_journal.debug())
3773  << "AccountHistory reschedule job for account "
3774  << toBase58(accountId) << ", incomplete ledger range ["
3775  << startLedgerSeq << "," << lastLedgerSeq << "]";
3776  setAccountHistoryJobTimer(subInfo);
3777  return;
3778  }
3779 
3781  while (!subInfo.index_->stopHistorical_)
3782  {
3783  auto dbResult =
3784  getMoreTxns(startLedgerSeq, lastLedgerSeq, marker);
3785  if (!dbResult)
3786  {
3787  JLOG(m_journal.debug())
3788  << "AccountHistory job for account "
3789  << toBase58(accountId) << " getMoreTxns failed.";
3790  send(rpcError(rpcINTERNAL), true);
3791  return;
3792  }
3793 
3794  auto const& txns = dbResult->first;
3795  marker = dbResult->second;
3796  size_t num_txns = txns.size();
3797  for (size_t i = 0; i < num_txns; ++i)
3798  {
3799  auto const& [tx, meta] = txns[i];
3800 
3801  if (!tx || !meta)
3802  {
3803  JLOG(m_journal.debug())
3804  << "AccountHistory job for account "
3805  << toBase58(accountId) << " empty tx or meta.";
3806  send(rpcError(rpcINTERNAL), true);
3807  return;
3808  }
3809  auto curTxLedger =
3811  tx->getLedger());
3812  if (!curTxLedger)
3813  {
3814  JLOG(m_journal.debug())
3815  << "AccountHistory job for account "
3816  << toBase58(accountId) << " no ledger.";
3817  send(rpcError(rpcINTERNAL), true);
3818  return;
3819  }
3821  tx->getSTransaction();
3822  if (!stTxn)
3823  {
3824  JLOG(m_journal.debug())
3825  << "AccountHistory job for account "
3826  << toBase58(accountId)
3827  << " getSTransaction failed.";
3828  send(rpcError(rpcINTERNAL), true);
3829  return;
3830  }
3831 
3832  auto const mRef = std::ref(*meta);
3833  auto const trR = meta->getResultTER();
3834  MultiApiJson jvTx =
3835  transJson(stTxn, trR, true, curTxLedger, mRef);
3836 
3837  jvTx.set(
3838  jss::account_history_tx_index, txHistoryIndex--);
3839  if (i + 1 == num_txns ||
3840  txns[i + 1].first->getLedger() != tx->getLedger())
3841  jvTx.set(jss::account_history_boundary, true);
3842 
3843  if (isFirstTx(tx, meta))
3844  {
3845  jvTx.set(jss::account_history_tx_first, true);
3846  sendMultiApiJson(jvTx, false);
3847 
3848  JLOG(m_journal.trace())
3849  << "AccountHistory job for account "
3850  << toBase58(accountId)
3851  << " done, found last tx.";
3852  return;
3853  }
3854  else
3855  {
3856  sendMultiApiJson(jvTx, false);
3857  }
3858  }
3859 
3860  if (marker)
3861  {
3862  JLOG(m_journal.trace())
3863  << "AccountHistory job for account "
3864  << toBase58(accountId)
3865  << " paging, marker=" << marker->ledgerSeq << ":"
3866  << marker->txnSeq;
3867  }
3868  else
3869  {
3870  break;
3871  }
3872  }
3873 
3874  if (!subInfo.index_->stopHistorical_)
3875  {
3876  lastLedgerSeq = startLedgerSeq - 1;
3877  if (lastLedgerSeq <= 1)
3878  {
3879  JLOG(m_journal.trace())
3880  << "AccountHistory job for account "
3881  << toBase58(accountId)
3882  << " done, reached genesis ledger.";
3883  return;
3884  }
3885  }
3886  }
3887  });
3888 }
3889 
3890 void
3892  std::shared_ptr<ReadView const> const& ledger,
3893  SubAccountHistoryInfoWeak& subInfo)
3894 {
3895  subInfo.index_->separationLedgerSeq_ = ledger->seq();
3896  auto const& accountId = subInfo.index_->accountId_;
3897  auto const accountKeylet = keylet::account(accountId);
3898  if (!ledger->exists(accountKeylet))
3899  {
3900  JLOG(m_journal.debug())
3901  << "subAccountHistoryStart, no account " << toBase58(accountId)
3902  << ", no need to add AccountHistory job.";
3903  return;
3904  }
3905  if (accountId == genesisAccountId)
3906  {
3907  if (auto const sleAcct = ledger->read(accountKeylet); sleAcct)
3908  {
3909  if (sleAcct->getFieldU32(sfSequence) == 1)
3910  {
3911  JLOG(m_journal.debug())
3912  << "subAccountHistoryStart, genesis account "
3913  << toBase58(accountId)
3914  << " does not have tx, no need to add AccountHistory job.";
3915  return;
3916  }
3917  }
3918  else
3919  {
3920  assert(false);
3921  return;
3922  }
3923  }
3924  subInfo.index_->historyLastLedgerSeq_ = ledger->seq();
3925  subInfo.index_->haveHistorical_ = true;
3926 
3927  JLOG(m_journal.debug())
3928  << "subAccountHistoryStart, add AccountHistory job: accountId="
3929  << toBase58(accountId) << ", currentLedgerSeq=" << ledger->seq();
3930 
3931  addAccountHistoryJob(subInfo);
3932 }
3933 
3936  InfoSub::ref isrListener,
3937  AccountID const& accountId)
3938 {
3939  if (!isrListener->insertSubAccountHistory(accountId))
3940  {
3941  JLOG(m_journal.debug())
3942  << "subAccountHistory, already subscribed to account "
3943  << toBase58(accountId);
3944  return rpcINVALID_PARAMS;
3945  }
3946 
3949  isrListener, std::make_shared<SubAccountHistoryIndex>(accountId)};
3950  auto simIterator = mSubAccountHistory.find(accountId);
3951  if (simIterator == mSubAccountHistory.end())
3952  {
3954  inner.emplace(isrListener->getSeq(), ahi);
3956  simIterator, std::make_pair(accountId, inner));
3957  }
3958  else
3959  {
3960  simIterator->second.emplace(isrListener->getSeq(), ahi);
3961  }
3962 
3963  auto const ledger = app_.getLedgerMaster().getValidatedLedger();
3964  if (ledger)
3965  {
3966  subAccountHistoryStart(ledger, ahi);
3967  }
3968  else
3969  {
3970  // The node does not have validated ledgers, so wait for
3971  // one before start streaming.
3972  // In this case, the subscription is also considered successful.
3973  JLOG(m_journal.debug())
3974  << "subAccountHistory, no validated ledger yet, delay start";
3975  }
3976 
3977  return rpcSUCCESS;
3978 }
3979 
3980 void
3982  InfoSub::ref isrListener,
3983  AccountID const& account,
3984  bool historyOnly)
3985 {
3986  if (!historyOnly)
3987  isrListener->deleteSubAccountHistory(account);
3988  unsubAccountHistoryInternal(isrListener->getSeq(), account, historyOnly);
3989 }
3990 
3991 void
3993  std::uint64_t seq,
3994  const AccountID& account,
3995  bool historyOnly)
3996 {
3998  auto simIterator = mSubAccountHistory.find(account);
3999  if (simIterator != mSubAccountHistory.end())
4000  {
4001  auto& subInfoMap = simIterator->second;
4002  auto subInfoIter = subInfoMap.find(seq);
4003  if (subInfoIter != subInfoMap.end())
4004  {
4005  subInfoIter->second.index_->stopHistorical_ = true;
4006  }
4007 
4008  if (!historyOnly)
4009  {
4010  simIterator->second.erase(seq);
4011  if (simIterator->second.empty())
4012  {
4013  mSubAccountHistory.erase(simIterator);
4014  }
4015  }
4016  JLOG(m_journal.debug())
4017  << "unsubAccountHistory, account " << toBase58(account)
4018  << ", historyOnly = " << (historyOnly ? "true" : "false");
4019  }
4020 }
4021 
4022 bool
4023 NetworkOPsImp::subBook(InfoSub::ref isrListener, Book const& book)
4024 {
4025  if (auto listeners = app_.getOrderBookDB().makeBookListeners(book))
4026  listeners->addSubscriber(isrListener);
4027  else
4028  assert(false);
4029  return true;
4030 }
4031 
4032 bool
4034 {
4035  if (auto listeners = app_.getOrderBookDB().getBookListeners(book))
4036  listeners->removeSubscriber(uSeq);
4037 
4038  return true;
4039 }
4040 
4044 {
4045  // This code-path is exclusively used when the server is in standalone
4046  // mode via `ledger_accept`
4047  assert(m_standalone);
4048 
4049  if (!m_standalone)
4050  Throw<std::runtime_error>(
4051  "Operation only possible in STANDALONE mode.");
4052 
4053  // FIXME Could we improve on this and remove the need for a specialized
4054  // API in Consensus?
4056  mConsensus.simulate(app_.timeKeeper().closeTime(), consensusDelay);
4057  return m_ledgerMaster.getCurrentLedger()->info().seq;
4058 }
4059 
4060 // <-- bool: true=added, false=already there
4061 bool
4063 {
4064  if (auto lpClosed = m_ledgerMaster.getValidatedLedger())
4065  {
4066  jvResult[jss::ledger_index] = lpClosed->info().seq;
4067  jvResult[jss::ledger_hash] = to_string(lpClosed->info().hash);
4068  jvResult[jss::ledger_time] = Json::Value::UInt(
4069  lpClosed->info().closeTime.time_since_epoch().count());
4070  if (!lpClosed->rules().enabled(featureXRPFees))
4071  jvResult[jss::fee_ref] = Config::FEE_UNITS_DEPRECATED;
4072  jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
4073  jvResult[jss::reserve_base] =
4074  lpClosed->fees().accountReserve(0).jsonClipped();
4075  jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
4076  }
4077 
4079  {
4080  jvResult[jss::validated_ledgers] =
4082  }
4083 
4085  return mStreamMaps[sLedger]
4086  .emplace(isrListener->getSeq(), isrListener)
4087  .second;
4088 }
4089 
4090 // <-- bool: true=added, false=already there
4091 bool
4093 {
4095  return mStreamMaps[sBookChanges]
4096  .emplace(isrListener->getSeq(), isrListener)
4097  .second;
4098 }
4099 
4100 // <-- bool: true=erased, false=was not there
4101 bool
4103 {
4105  return mStreamMaps[sLedger].erase(uSeq);
4106 }
4107 
4108 // <-- bool: true=erased, false=was not there
4109 bool
4111 {
4113  return mStreamMaps[sBookChanges].erase(uSeq);
4114 }
4115 
4116 // <-- bool: true=added, false=already there
4117 bool
4119 {
4121  return mStreamMaps[sManifests]
4122  .emplace(isrListener->getSeq(), isrListener)
4123  .second;
4124 }
4125 
4126 // <-- bool: true=erased, false=was not there
4127 bool
4129 {
4131  return mStreamMaps[sManifests].erase(uSeq);
4132 }
4133 
4134 // <-- bool: true=added, false=already there
4135 bool
4137  InfoSub::ref isrListener,
4138  Json::Value& jvResult,
4139  bool admin)
4140 {
4141  uint256 uRandom;
4142 
4143  if (m_standalone)
4144  jvResult[jss::stand_alone] = m_standalone;
4145 
4146  // CHECKME: is it necessary to provide a random number here?
4147  beast::rngfill(uRandom.begin(), uRandom.size(), crypto_prng());
4148 
4149  auto const& feeTrack = app_.getFeeTrack();
4150  jvResult[jss::random] = to_string(uRandom);
4151  jvResult[jss::server_status] = strOperatingMode(admin);
4152  jvResult[jss::load_base] = feeTrack.getLoadBase();
4153  jvResult[jss::load_factor] = feeTrack.getLoadFactor();
4154  jvResult[jss::hostid] = getHostId(admin);
4155  jvResult[jss::pubkey_node] =
4157 
4159  return mStreamMaps[sServer]
4160  .emplace(isrListener->getSeq(), isrListener)
4161  .second;
4162 }
4163 
4164 // <-- bool: true=erased, false=was not there
4165 bool
4167 {
4169  return mStreamMaps[sServer].erase(uSeq);
4170 }
4171 
4172 // <-- bool: true=added, false=already there
4173 bool
4175 {
4177  return mStreamMaps[sTransactions]
4178  .emplace(isrListener->getSeq(), isrListener)
4179  .second;
4180 }
4181 
4182 // <-- bool: true=erased, false=was not there
4183 bool
4185 {
4187  return mStreamMaps[sTransactions].erase(uSeq);
4188 }
4189 
4190 // <-- bool: true=added, false=already there
4191 bool
4193 {
4196  .emplace(isrListener->getSeq(), isrListener)
4197  .second;
4198 }
4199 
4200 // <-- bool: true=erased, false=was not there
4201 bool
4203 {
4205  return mStreamMaps[sRTTransactions].erase(uSeq);
4206 }
4207 
4208 // <-- bool: true=added, false=already there
4209 bool
4211 {
4213  return mStreamMaps[sValidations]
4214  .emplace(isrListener->getSeq(), isrListener)
4215  .second;
4216 }
4217 
4218 void
4220 {
4221  accounting_.json(obj);
4222 }
4223 
4224 // <-- bool: true=erased, false=was not there
4225 bool
4227 {
4229  return mStreamMaps[sValidations].erase(uSeq);
4230 }
4231 
4232 // <-- bool: true=added, false=already there
4233 bool
4235 {
4237  return mStreamMaps[sPeerStatus]
4238  .emplace(isrListener->getSeq(), isrListener)
4239  .second;
4240 }
4241 
4242 // <-- bool: true=erased, false=was not there
4243 bool
4245 {
4247  return mStreamMaps[sPeerStatus].erase(uSeq);
4248 }
4249 
4250 // <-- bool: true=added, false=already there
4251 bool
4253 {
4256  .emplace(isrListener->getSeq(), isrListener)
4257  .second;
4258 }
4259 
4260 // <-- bool: true=erased, false=was not there
4261 bool
4263 {
4265  return mStreamMaps[sConsensusPhase].erase(uSeq);
4266 }
4267 
4270 {
4272 
4273  subRpcMapType::iterator it = mRpcSubMap.find(strUrl);
4274 
4275  if (it != mRpcSubMap.end())
4276  return it->second;
4277 
4278  return InfoSub::pointer();
4279 }
4280 
4283 {
4285 
4286  mRpcSubMap.emplace(strUrl, rspEntry);
4287 
4288  return rspEntry;
4289 }
4290 
4291 bool
4293 {
4295  auto pInfo = findRpcSub(strUrl);
4296 
4297  if (!pInfo)
4298  return false;
4299 
4300  // check to see if any of the stream maps still hold a weak reference to
4301  // this entry before removing
4302  for (SubMapType const& map : mStreamMaps)
4303  {
4304  if (map.find(pInfo->getSeq()) != map.end())
4305  return false;
4306  }
4307  mRpcSubMap.erase(strUrl);
4308  return true;
4309 }
4310 
4311 #ifndef USE_NEW_BOOK_PAGE
4312 
4313 // NIKB FIXME this should be looked at. There's no reason why this shouldn't
4314 // work, but it demonstrated poor performance.
4315 //
4316 void
4319  Book const& book,
4320  AccountID const& uTakerID,
4321  bool const bProof,
4322  unsigned int iLimit,
4323  Json::Value const& jvMarker,
4324  Json::Value& jvResult)
4325 { // CAUTION: This is the old get book page logic
4326  Json::Value& jvOffers =
4327  (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4328 
4330  const uint256 uBookBase = getBookBase(book);
4331  const uint256 uBookEnd = getQualityNext(uBookBase);
4332  uint256 uTipIndex = uBookBase;
4333 
4334  if (auto stream = m_journal.trace())
4335  {
4336  stream << "getBookPage:" << book;
4337  stream << "getBookPage: uBookBase=" << uBookBase;
4338  stream << "getBookPage: uBookEnd=" << uBookEnd;
4339  stream << "getBookPage: uTipIndex=" << uTipIndex;
4340  }
4341 
4342  ReadView const& view = *lpLedger;
4343 
4344  bool const bGlobalFreeze = isGlobalFrozen(view, book.out.account) ||
4345  isGlobalFrozen(view, book.in.account);
4346 
4347  bool bDone = false;
4348  bool bDirectAdvance = true;
4349 
4350  std::shared_ptr<SLE const> sleOfferDir;
4351  uint256 offerIndex;
4352  unsigned int uBookEntry;
4353  STAmount saDirRate;
4354 
4355  auto const rate = transferRate(view, book.out.account);
4356  auto viewJ = app_.journal("View");
4357 
4358  while (!bDone && iLimit-- > 0)
4359  {
4360  if (bDirectAdvance)
4361  {
4362  bDirectAdvance = false;
4363 
4364  JLOG(m_journal.trace()) << "getBookPage: bDirectAdvance";
4365 
4366  auto const ledgerIndex = view.succ(uTipIndex, uBookEnd);
4367  if (ledgerIndex)
4368  sleOfferDir = view.read(keylet::page(*ledgerIndex));
4369  else
4370  sleOfferDir.reset();
4371 
4372  if (!sleOfferDir)
4373  {
4374  JLOG(m_journal.trace()) << "getBookPage: bDone";
4375  bDone = true;
4376  }
4377  else
4378  {
4379  uTipIndex = sleOfferDir->key();
4380  saDirRate = amountFromQuality(getQuality(uTipIndex));
4381 
4382  cdirFirst(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex);
4383 
4384  JLOG(m_journal.trace())
4385  << "getBookPage: uTipIndex=" << uTipIndex;
4386  JLOG(m_journal.trace())
4387  << "getBookPage: offerIndex=" << offerIndex;
4388  }
4389  }
4390 
4391  if (!bDone)
4392  {
4393  auto sleOffer = view.read(keylet::offer(offerIndex));
4394 
4395  if (sleOffer)
4396  {
4397  auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4398  auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4399  auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4400  STAmount saOwnerFunds;
4401  bool firstOwnerOffer(true);
4402 
4403  if (book.out.account == uOfferOwnerID)
4404  {
4405  // If an offer is selling issuer's own IOUs, it is fully
4406  // funded.
4407  saOwnerFunds = saTakerGets;
4408  }
4409  else if (bGlobalFreeze)
4410  {
4411  // If either asset is globally frozen, consider all offers
4412  // that aren't ours to be totally unfunded
4413  saOwnerFunds.clear(book.out);
4414  }
4415  else
4416  {
4417  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4418  if (umBalanceEntry != umBalance.end())
4419  {
4420  // Found in running balance table.
4421 
4422  saOwnerFunds = umBalanceEntry->second;
4423  firstOwnerOffer = false;
4424  }
4425  else
4426  {
4427  // Did not find balance in table.
4428 
4429  saOwnerFunds = accountHolds(
4430  view,
4431  uOfferOwnerID,
4432  book.out.currency,
4433  book.out.account,
4435  viewJ);
4436 
4437  if (saOwnerFunds < beast::zero)
4438  {
4439  // Treat negative funds as zero.
4440 
4441  saOwnerFunds.clear();
4442  }
4443  }
4444  }
4445 
4446  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4447 
4448  STAmount saTakerGetsFunded;
4449  STAmount saOwnerFundsLimit = saOwnerFunds;
4450  Rate offerRate = parityRate;
4451 
4452  if (rate != parityRate
4453  // Have a tranfer fee.
4454  && uTakerID != book.out.account
4455  // Not taking offers of own IOUs.
4456  && book.out.account != uOfferOwnerID)
4457  // Offer owner not issuing ownfunds
4458  {
4459  // Need to charge a transfer fee to offer owner.
4460  offerRate = rate;
4461  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4462  }
4463 
4464  if (saOwnerFundsLimit >= saTakerGets)
4465  {
4466  // Sufficient funds no shenanigans.
4467  saTakerGetsFunded = saTakerGets;
4468  }
4469  else
4470  {
4471  // Only provide, if not fully funded.
4472 
4473  saTakerGetsFunded = saOwnerFundsLimit;
4474 
4475  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4476  std::min(
4477  saTakerPays,
4478  multiply(
4479  saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4480  .setJson(jvOffer[jss::taker_pays_funded]);
4481  }
4482 
4483  STAmount saOwnerPays = (parityRate == offerRate)
4484  ? saTakerGetsFunded
4485  : std::min(
4486  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4487 
4488  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4489 
4490  // Include all offers funded and unfunded
4491  Json::Value& jvOf = jvOffers.append(jvOffer);
4492  jvOf[jss::quality] = saDirRate.getText();
4493 
4494  if (firstOwnerOffer)
4495  jvOf[jss::owner_funds] = saOwnerFunds.getText();
4496  }
4497  else
4498  {
4499  JLOG(m_journal.warn()) << "Missing offer";
4500  }
4501 
4502  if (!cdirNext(view, uTipIndex, sleOfferDir, uBookEntry, offerIndex))
4503  {
4504  bDirectAdvance = true;
4505  }
4506  else
4507  {
4508  JLOG(m_journal.trace())
4509  << "getBookPage: offerIndex=" << offerIndex;
4510  }
4511  }
4512  }
4513 
4514  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4515  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4516 }
4517 
4518 #else
4519 
4520 // This is the new code that uses the book iterators
4521 // It has temporarily been disabled
4522 
4523 void
4526  Book const& book,
4527  AccountID const& uTakerID,
4528  bool const bProof,
4529  unsigned int iLimit,
4530  Json::Value const& jvMarker,
4531  Json::Value& jvResult)
4532 {
4533  auto& jvOffers = (jvResult[jss::offers] = Json::Value(Json::arrayValue));
4534 
4536 
4537  MetaView lesActive(lpLedger, tapNONE, true);
4538  OrderBookIterator obIterator(lesActive, book);
4539 
4540  auto const rate = transferRate(lesActive, book.out.account);
4541 
4542  const bool bGlobalFreeze = lesActive.isGlobalFrozen(book.out.account) ||
4543  lesActive.isGlobalFrozen(book.in.account);
4544 
4545  while (iLimit-- > 0 && obIterator.nextOffer())
4546  {
4547  SLE::pointer sleOffer = obIterator.getCurrentOffer();
4548  if (sleOffer)
4549  {
4550  auto const uOfferOwnerID = sleOffer->getAccountID(sfAccount);
4551  auto const& saTakerGets = sleOffer->getFieldAmount(sfTakerGets);
4552  auto const& saTakerPays = sleOffer->getFieldAmount(sfTakerPays);
4553  STAmount saDirRate = obIterator.getCurrentRate();
4554  STAmount saOwnerFunds;
4555 
4556  if (book.out.account == uOfferOwnerID)
4557  {
4558  // If offer is selling issuer's own IOUs, it is fully funded.
4559  saOwnerFunds = saTakerGets;
4560  }
4561  else if (bGlobalFreeze)
4562  {
4563  // If either asset is globally frozen, consider all offers
4564  // that aren't ours to be totally unfunded
4565  saOwnerFunds.clear(book.out);
4566  }
4567  else
4568  {
4569  auto umBalanceEntry = umBalance.find(uOfferOwnerID);
4570 
4571  if (umBalanceEntry != umBalance.end())
4572  {
4573  // Found in running balance table.
4574 
4575  saOwnerFunds = umBalanceEntry->second;
4576  }
4577  else
4578  {
4579  // Did not find balance in table.
4580 
4581  saOwnerFunds = lesActive.accountHolds(
4582  uOfferOwnerID,
4583  book.out.currency,
4584  book.out.account,
4586 
4587  if (saOwnerFunds.isNegative())
4588  {
4589  // Treat negative funds as zero.
4590 
4591  saOwnerFunds.zero();
4592  }
4593  }
4594  }
4595 
4596  Json::Value jvOffer = sleOffer->getJson(JsonOptions::none);
4597 
4598  STAmount saTakerGetsFunded;
4599  STAmount saOwnerFundsLimit = saOwnerFunds;
4600  Rate offerRate = parityRate;
4601 
4602  if (rate != parityRate
4603  // Have a tranfer fee.
4604  && uTakerID != book.out.account
4605  // Not taking offers of own IOUs.
4606  && book.out.account != uOfferOwnerID)
4607  // Offer owner not issuing ownfunds
4608  {
4609  // Need to charge a transfer fee to offer owner.
4610  offerRate = rate;
4611  saOwnerFundsLimit = divide(saOwnerFunds, offerRate);
4612  }
4613 
4614  if (saOwnerFundsLimit >= saTakerGets)
4615  {
4616  // Sufficient funds no shenanigans.
4617  saTakerGetsFunded = saTakerGets;
4618  }
4619  else
4620  {
4621  // Only provide, if not fully funded.
4622  saTakerGetsFunded = saOwnerFundsLimit;
4623 
4624  saTakerGetsFunded.setJson(jvOffer[jss::taker_gets_funded]);
4625 
4626  // TOOD(tom): The result of this expression is not used - what's
4627  // going on here?
4628  std::min(
4629  saTakerPays,
4630  multiply(saTakerGetsFunded, saDirRate, saTakerPays.issue()))
4631  .setJson(jvOffer[jss::taker_pays_funded]);
4632  }
4633 
4634  STAmount saOwnerPays = (parityRate == offerRate)
4635  ? saTakerGetsFunded
4636  : std::min(
4637  saOwnerFunds, multiply(saTakerGetsFunded, offerRate));
4638 
4639  umBalance[uOfferOwnerID] = saOwnerFunds - saOwnerPays;
4640 
4641  if (!saOwnerFunds.isZero() || uOfferOwnerID == uTakerID)
4642  {
4643  // Only provide funded offers and offers of the taker.
4644  Json::Value& jvOf = jvOffers.append(jvOffer);
4645  jvOf[jss::quality] = saDirRate.getText();
4646  }
4647  }
4648  }
4649 
4650  // jvResult[jss::marker] = Json::Value(Json::arrayValue);
4651  // jvResult[jss::nodes] = Json::Value(Json::arrayValue);
4652 }
4653 
4654 #endif
4655 
4656 inline void
4658 {
4659  auto [counters, mode, start, initialSync] = accounting_.getCounterData();
4660  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4661  std::chrono::steady_clock::now() - start);
4662  counters[static_cast<std::size_t>(mode)].dur += current;
4663 
4666  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4667  .dur.count());
4669  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4670  .dur.count());
4672  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].dur.count());
4674  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4675  .dur.count());
4677  counters[static_cast<std::size_t>(OperatingMode::FULL)].dur.count());
4678 
4680  counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
4681  .transitions);
4683  counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
4684  .transitions);
4686  counters[static_cast<std::size_t>(OperatingMode::SYNCING)].transitions);
4688  counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
4689  .transitions);
4691  counters[static_cast<std::size_t>(OperatingMode::FULL)].transitions);
4692 }
4693 
4694 void
4696 {
4697  auto now = std::chrono::steady_clock::now();
4698 
4699  std::lock_guard lock(mutex_);
4700  ++counters_[static_cast<std::size_t>(om)].transitions;
4701  if (om == OperatingMode::FULL &&
4702  counters_[static_cast<std::size_t>(om)].transitions == 1)
4703  {
4704  initialSyncUs_ = std::chrono::duration_cast<std::chrono::microseconds>(
4705  now - processStart_)
4706  .count();
4707  }
4708  counters_[static_cast<std::size_t>(mode_)].dur +=
4709  std::chrono::duration_cast<std::chrono::microseconds>(now - start_);
4710 
4711  mode_ = om;
4712  start_ = now;
4713 }
4714 
4715 void
4717 {
4718  auto [counters, mode, start, initialSync] = getCounterData();
4719  auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
4720  std::chrono::steady_clock::now() - start);
4721  counters[static_cast<std::size_t>(mode)].dur += current;
4722 
4723  obj[jss::state_accounting] = Json::objectValue;
4724  for (std::size_t i = static_cast<std::size_t>(OperatingMode::DISCONNECTED);
4725  i <= static_cast<std::size_t>(OperatingMode::FULL);
4726  ++i)
4727  {
4728  obj[jss::state_accounting][states_[i]] = Json::objectValue;
4729  auto& state = obj[jss::state_accounting][states_[i]];
4730  state[jss::transitions] = std::to_string(counters[i].transitions);
4731  state[jss::duration_us] = std::to_string(counters[i].dur.count());
4732  }
4733  obj[jss::server_state_duration_us] = std::to_string(current.count());
4734  if (initialSync)
4735  obj[jss::initial_sync_duration_us] = std::to_string(initialSync);
4736 }
4737 
4738 //------------------------------------------------------------------------------
4739 
4742  Application& app,
4743  NetworkOPs::clock_type& clock,
4744  bool standalone,
4745  std::size_t minPeerCount,
4746  bool startvalid,
4747  JobQueue& job_queue,
4748  LedgerMaster& ledgerMaster,
4749  ValidatorKeys const& validatorKeys,
4750  boost::asio::io_service& io_svc,
4751  beast::Journal journal,
4752  beast::insight::Collector::ptr const& collector)
4753 {
4754  return std::make_unique<NetworkOPsImp>(
4755  app,
4756  clock,
4757  standalone,
4758  minPeerCount,
4759  startvalid,
4760  job_queue,
4761  ledgerMaster,
4762  validatorKeys,
4763  io_svc,
4764  journal,
4765  collector);
4766 }
4767 
4768 } // namespace ripple
ripple::SQLiteDatabase
Definition: SQLiteDatabase.h:27
ripple::NetworkOPsImp::forwardManifest
void forwardManifest(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2849
ripple::NetworkOPsImp::unsubValidations
bool unsubValidations(std::uint64_t uListener) override
Definition: NetworkOPs.cpp:4226
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:4210
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:4262
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:4219
ripple::RPC::SubmitSync
SubmitSync
Possible values for defining synchronous behavior of the transaction submission API.
Definition: SubmitSync.h:36
ripple::LoadManager
Manages load sources.
Definition: LoadManager.h:45
ripple::sfReserveBase
const SF_UINT32 sfReserveBase
ripple::Application::cluster
virtual Cluster & cluster()=0
ripple::MultivarJson::isMember
Json::Value const &select(auto &&selector) const requires std IsMemberResult isMember(const char *key) const
Definition: MultivarJson.h:69
ripple::NetworkOPsImp::m_journal
beast::Journal m_journal
Definition: NetworkOPs.cpp:704
ripple::LedgerMaster::getPublishedLedger
std::shared_ptr< ReadView const > getPublishedLedger()
Definition: LedgerMaster.cpp: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.
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:4716
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:3256
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:4657
ripple::NetworkOPsImp::subPeerStatus
bool subPeerStatus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4234
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:2287
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:3388
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:4292
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:2316
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:2798
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:3992
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:3110
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:4741
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:2887
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::NetworkOPsImp::pubLedger
void pubLedger(std::shared_ptr< ReadView const > const &lpAccepted) override
Definition: NetworkOPs.cpp:2955
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:4184
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:2869
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:4282
ripple::rpcSUCCESS
@ rpcSUCCESS
Definition: ErrorCodes.h:44
ripple::NetworkOPsImp::forwardValidation
void forwardValidation(Json::Value const &jvObj) override
Definition: NetworkOPs.cpp:2829
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:3891
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:3068
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:3546
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:3502
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:4202
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:4118
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:4092
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:106
ripple::warnRPC_UNSUPPORTED_MAJORITY
@ warnRPC_UNSUPPORTED_MAJORITY
Definition: ErrorCodes.h:156
ripple::NetworkOPsImp::subTransactions
bool subTransactions(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4174
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:4102
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:3465
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:357
ripple::NetworkOPsImp::sConsensusPhase
@ sConsensusPhase
Definition: NetworkOPs.cpp:745
ripple::NetworkOPsImp::mMutex
std::mutex mMutex
Definition: NetworkOPs.cpp:764
ripple::sfBaseFee
const SF_UINT64 sfBaseFee
ripple::NetworkOPsImp::Stats::tracking_transitions
beast::insight::Gauge tracking_transitions
Definition: NetworkOPs.cpp:818
ripple::LedgerMaster::haveValidated
bool haveValidated()
Whether we have ever fully validated a ledger.
Definition: LedgerMaster.h:288
ripple::LedgerMaster::getValidatedLedgerAge
std::chrono::seconds getValidatedLedgerAge()
Definition: LedgerMaster.cpp:274
ripple::generateSeed
Seed generateSeed(std::string const &passPhrase)
Generate a seed deterministically.
Definition: Seed.cpp:69
ripple::LedgerMaster::getClosedLedger
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:98
ripple::NetworkOPsImp::Stats::connected_transitions
beast::insight::Gauge connected_transitions
Definition: NetworkOPs.cpp:816
ripple::NetworkOPsImp::clusterTimer_
boost::asio::steady_timer clusterTimer_
Definition: NetworkOPs.cpp:719
ripple::STObject
Definition: STObject.h:53
ripple::perf::PerfLog::countersJson
virtual Json::Value countersJson() const =0
Render performance counters in Json.
ripple::NetworkOPsImp::mTransactions
std::vector< TransactionStatus > mTransactions
Definition: NetworkOPs.cpp:766
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:54
ripple::NetworkOPsImp::reportConsensusStateChange
void reportConsensusStateChange(ConsensusPhase phase)
Definition: NetworkOPs.cpp:3088
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:4166
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:4110
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:3102
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:2759
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:4033
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:4042
ripple::NetworkOPsImp::sTransactions
@ sTransactions
Definition: NetworkOPs.cpp:741
ripple::NetworkOPsImp::mSubAccount
SubInfoMapType mSubAccount
Definition: NetworkOPs.cpp:730
ripple::Config::SERVER_DOMAIN
std::string SERVER_DOMAIN
Definition: Config.h:290
ripple::NetworkOPsImp::pubValidatedTransaction
void pubValidatedTransaction(std::shared_ptr< ReadView const > const &ledger, AcceptedLedgerTx const &transaction, bool last)
Definition: NetworkOPs.cpp:3202
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:4317
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:2258
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:4062
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:3935
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:4128
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:3097
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:34
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:4192
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:2765
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:2339
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:4136
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:4023
ripple::NetworkOPsImp::subConsensus
bool subConsensus(InfoSub::ref ispListener) override
Definition: NetworkOPs.cpp:4252
ripple::NetworkOPsImp::getConsensusInfo
Json::Value getConsensusInfo() override
Definition: NetworkOPs.cpp:2333
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:4695
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:3518
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:3981
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:4244
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:4269
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:2753
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)