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