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