20 #include <ripple/app/ledger/AccountStateSF.h>
21 #include <ripple/app/ledger/InboundLedger.h>
22 #include <ripple/app/ledger/InboundLedgers.h>
23 #include <ripple/app/ledger/LedgerMaster.h>
24 #include <ripple/app/ledger/TransactionStateSF.h>
25 #include <ripple/app/main/Application.h>
26 #include <ripple/app/misc/NetworkOPs.h>
27 #include <ripple/basics/Log.h>
28 #include <ripple/core/JobQueue.h>
29 #include <ripple/nodestore/DatabaseShard.h>
30 #include <ripple/overlay/Overlay.h>
31 #include <ripple/protocol/HashPrefix.h>
32 #include <ripple/protocol/jss.h>
33 #include <ripple/resource/Fees.h>
34 #include <ripple/shamap/SHAMapNodeID.h>
40 using namespace std::chrono_literals;
84 , mHaveTransactions(false)
89 , mReceiveDispatched(false)
113 <<
"Acquiring shard with no shard store available";
127 else if (shardStore &&
mSeq >= shardStore->earliestLedgerSeq())
129 if (
auto l = shardStore->fetchLedger(
mHash,
mSeq))
147 <<
" local store. " <<
mHash;
164 return app_.overlay().findPeerByShortID(id) != nullptr;
173 JLOG(
m_journal.
debug()) <<
"Deferring InboundLedger timer due to load";
180 ptr->invokeOnTimer();
190 if ((seq != 0) && (
mSeq == 0))
224 if (entry.second->type() == protocol::liAS_NODE)
230 <<
"Acquire " <<
mHash <<
" abort "
255 for (
auto const& n : mn)
310 auto makeLedger = [&,
this](
Blob const& data) {
312 mLedger = std::make_shared<Ledger>(
323 <<
" cannot be a ledger";
334 makeLedger(nodeObject->getData());
339 auto& dstDB{
mLedger->stateMap().family().db()};
342 Blob blob{nodeObject->getData()};
361 mLedger->stateMap().family().db().store(
374 if (
mLedger->info().txHash.isZero())
383 if (
mLedger->txMap().fetchRoot(
397 if (
mLedger->info().accountHash.isZero())
400 <<
"We are acquiring a ledger with a zero account hash";
406 if (
mLedger->stateMap().fetchRoot(
407 SHAMapHash{mLedger->info().accountHash}, &filter))
463 <<
"No progress(" << pc <<
") for ledger " <<
mHash;
483 [
this](
auto peer) {
return peer->hasLedger(
mHash,
mSeq); });
530 if (self->mComplete && !self->mFailed)
532 self->app_.getLedgerMaster().checkAccept(self->getLedger());
533 self->app_.getLedgerMaster().tryAdvance();
536 self->app_.getInboundLedgers().logFailure(
537 self->mHash, self->mSeq);
551 <<
"Trigger on ledger: " <<
mHash << (
mComplete ?
" completed" :
"")
559 stream <<
"Trigger acquiring ledger " <<
mHash <<
" from " << peer;
561 stream <<
"Trigger acquiring ledger " <<
mHash;
582 protocol::TMGetLedger tmGL;
588 tmGL.set_querytype(protocol::qtINDIRECT);
597 protocol::TMGetObjectByHash tmBH;
598 bool typeSet =
false;
599 tmBH.set_query(
true);
601 for (
auto const& p : need)
607 tmBH.set_type(p.first);
611 if (p.first == tmBH.type())
613 protocol::TMIndexedObject* io = tmBH.add_objects();
614 io->set_hash(p.second.begin(), p.second.size());
616 io->set_ledgerseq(
mSeq);
621 std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS);
635 <<
"getNeededHashes says acquire is complete";
648 tmGL.set_itype(protocol::liBASE);
650 tmGL.set_ledgerseq(
mSeq);
652 << (peer ?
"selected peer" :
"all peers");
658 tmGL.set_ledgerseq(
mLedger->info().seq);
663 tmGL.set_querydepth(0);
665 else if (peer && peer->isHighLatency())
668 tmGL.set_querydepth(2);
671 tmGL.set_querydepth(1);
679 if (!
mLedger->stateMap().isValid())
683 else if (
mLedger->stateMap().getHash().isZero())
686 tmGL.set_itype(protocol::liAS_NODE);
689 << (peer ?
"selected peer" :
"all peers");
709 if (!
mLedger->stateMap().isValid())
725 tmGL.set_itype(protocol::liAS_NODE);
726 for (
auto const&
id : nodes)
728 *(tmGL.add_nodeids()) =
id.first.getRawString();
732 <<
"Sending AS node request (" << nodes.size()
734 << (peer ?
"selected peer" :
"all peers");
751 if (!
mLedger->txMap().isValid())
755 else if (
mLedger->txMap().getHash().isZero())
758 tmGL.set_itype(protocol::liTX_NODE);
761 << (peer ?
"selected peer" :
"all peers");
775 if (!
mLedger->txMap().isValid())
791 tmGL.set_itype(protocol::liTX_NODE);
792 for (
auto const& n : nodes)
794 *(tmGL.add_nodeids()) = n.first.getRawString();
797 <<
"Sending TX node request (" << nodes.size()
798 <<
") to " << (peer ?
"selected peer" :
"all peers");
813 <<
"Done:" << (
mComplete ?
" complete" :
"")
828 nodes.begin(), nodes.end(), [
this](
auto const& item) {
829 return mRecentNodes.count(item.second) == 0;
835 if (dup == nodes.begin())
849 nodes.erase(dup, nodes.end());
855 if (nodes.size() > limit)
858 for (
auto const& n : nodes)
877 mLedger = std::make_shared<Ledger>(
883 <<
"Acquire hash mismatch: " <<
mLedger->info().hash
896 s.
addRaw(data.data(), data.size());
899 if (
mLedger->info().txHash.isZero())
902 if (
mLedger->info().accountHash.isZero())
905 mLedger->txMap().setSynching();
906 mLedger->stateMap().setSynching();
923 if (packet.type() == protocol::liTX_NODE)
937 auto [map, rootHash, filter] = [&]()
939 if (packet.type() == protocol::liTX_NODE)
943 std::make_unique<TransactionStateSF>(
948 std::make_unique<AccountStateSF>(
954 for (
auto const& node : packet.nodes())
964 if (nodeID->isRoot())
965 san += map.addRootNode(
966 rootHash,
makeSlice(node.nodedata()), filter.get());
968 san += map.addKnownNode(
969 *nodeID,
makeSlice(node.nodedata()), filter.get());
985 if (!map.isSynching())
987 if (packet.type() == protocol::liTX_NODE)
1020 san +=
mLedger->stateMap().addRootNode(
1045 san +=
mLedger->txMap().addRootNode(
1080 protocol::TMGetObjectByHash::otTRANSACTION_NODE, h));
1120 protocol::TMLedgerData& packet)
1124 if (packet.type() == protocol::liBASE)
1126 if (packet.nodes_size() < 1)
1149 if (!
mHaveState && (packet.nodes().size() > 1) &&
1164 <<
"Included AS/TX root invalid: " << ex.
what();
1176 if ((packet.type() == protocol::liTX_NODE) ||
1177 (packet.type() == protocol::liAS_NODE))
1179 if (packet.nodes().size() == 0)
1187 for (
auto const& node : packet.nodes())
1189 if (!node.has_nodeid() || !node.has_nodedata())
1200 if (packet.type() == protocol::liTX_NODE)
1226 int chosenPeerCount = -1;
1247 for (
auto& entry : data)
1249 if (
auto peer = entry.first.lock())
1252 if (count > chosenPeerCount)
1254 chosenPeerCount = count;
1255 chosenPeer = std::move(peer);
1275 ret[jss::complete] =
true;
1278 ret[jss::failed] =
true;
1281 ret[jss::peers] =
static_cast<int>(
mPeers.size());
1300 ret[jss::needed_state_hashes] = hv;
1310 ret[jss::needed_transaction_hashes] = hv;
std::set< uint256 > mRecentNodes
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
virtual Family & getNodeFamily()=0
std::vector< neededHash_t > getNeededHashes()
@ ledgerMaster
ledger master data for signing
Json::Value getJson(int)
Return a Json::objectValue.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Persistency layer for NodeObject.
SHAMapHash getHash() const
bool mProgress
Whether forward progress has been made.
Stream trace() const
Severity stream access functions.
std::optional< SHAMapNodeID > deserializeSHAMapNodeID(void const *data, std::size_t size)
Return an object representing a serialized SHAMap Node ID.
An immutable linear range of bytes.
@ arrayValue
array value (ordered list)
constexpr auto ledgerAcquireTimeout
void update(std::uint32_t seq)
InboundLedger(Application &app, uint256 const &hash, std::uint32_t seq, Reason reason, clock_type &)
std::set< Peer::id_t > mPeers
The identifiers of the peers we are tracking.
static std::vector< uint256 > neededHashes(uint256 const &root, SHAMap &map, int max, SHAMapSyncFilter *filter)
void filterNodes(std::vector< std::pair< SHAMapNodeID, uint256 >> &nodes, TriggerReason reason)
int processData(std::shared_ptr< Peer > peer, protocol::TMLedgerData &data)
Process one TMLedgerData Returns the number of useful nodes.
virtual NodeStore::DatabaseShard * getShardStore()=0
void queueJob() override
Queue a job to call invokeOnTimer().
std::vector< uint256 > neededStateHashes(int max, SHAMapSyncFilter *filter) const
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
std::string to_string(ListDisposition disposition)
Identifies a node inside a SHAMap.
void addPeers(std::size_t limit, std::function< bool(std::shared_ptr< Peer > const &)> score)
Add at most limit peers to this set from the overlay.
const uint256 mHash
The hash of the object (in practice, always a ledger) we are trying to fetch.
LedgerInfo deserializeHeader(Slice data)
Deserialize a ledger header from a byte array.
virtual NodeStore::Database & db()=0
virtual InboundLedgers & getInboundLedgers()=0
constexpr static std::size_t size()
void sendRequest(const protocol::TMGetLedger &message, std::shared_ptr< Peer > const &peer)
Send a GetLedger message to one or all peers.
LedgerInfo deserializePrefixedHeader(Slice data)
Deserialize a ledger header (prefixed with 4 bytes) from a byte array.
std::vector< uint256 > neededTxHashes(int max, SHAMapSyncFilter *filter) const
NetClock::time_point closeTime
bool takeHeader(std::string const &data)
Take ledger header data Call with a lock.
int getJobCountTotal(JobType t) const
Jobs waiting plus running at this priority.
bool gotData(std::weak_ptr< Peer >, std::shared_ptr< protocol::TMLedgerData > const &)
Stash a TMLedgerData received from a peer for later processing Returns 'true' if we need to dispatch.
Value & append(const Value &value)
Append value to array at the end.
std::shared_ptr< Ledger > mLedger
T shared_from_this(T... args)
std::size_t getPeerCount() const
@ objectValue
object value (collection of name/value pairs).
void addPeers()
Add more peers to the set, if possible.
virtual LedgerMaster & getLedgerMaster()=0
virtual void gotStaleData(std::shared_ptr< protocol::TMLedgerData > packet)=0
boost::optional< Blob > getFetchPack(uint256 const &hash) override
Retrieves partial ledger data of the coresponding hash from peers.
virtual Config & config()=0
virtual void onLedgerFetched()=0
Called when a complete ledger is obtained.
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
std::string getRawString() const
int addRaw(Blob const &vector)
virtual JobQueue & getJobQueue()=0
void tryDB(NodeStore::Database &srcDB)
bool takeTxRootNode(Slice const &data, SHAMapAddNode &)
Process AS root node received from a peer Call with a lock.
std::weak_ptr< PeerSet > pmDowncast() override
Return a weak pointer to this.
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, std::uint32_t ledgerSeq=0, FetchType fetchType=FetchType::synchronous)
Fetch a node object.
std::vector< std::pair< SHAMapNodeID, uint256 > > getMissingNodes(int maxNodes, SHAMapSyncFilter *filter)
Check for nodes in the SHAMap not available.
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
virtual Family * getShardFamily()=0
bool takeAsRootNode(Slice const &data, SHAMapAddNode &)
Process AS root node received from a peer Call with a lock.
NetClock::duration closeTimeResolution
Supports data retrieval by managing a set of peers.
virtual void setStored(std::shared_ptr< Ledger const > const &ledger)=0
Notifies the database that the given ledger has been fully acquired and stored.
virtual Overlay & overlay()=0
virtual std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id) const =0
Returns the peer with the matching short id, or null.
void trigger(std::shared_ptr< Peer > const &, TriggerReason)
Request more nodes, perhaps from a specific peer.
int add32(std::uint32_t i)
Information about the notional ledger backing the view.
bool storeLedger(std::shared_ptr< Ledger const > ledger)
void receiveNode(protocol::TMLedgerData &packet, SHAMapAddNode &)
Process node data received from a peer Call with a lock.
void runData()
Process pending TMLedgerData Query the 'best' peer.
std::vector< PeerDataPairType > mReceivedData
@ ledgerBecomeAggressiveThreshold
T stable_partition(T... args)
void onTimer(bool progress, ScopedLockType &peerSetLock) override
Called with a lock by the PeerSet when the timer expires.
std::mutex mReceivedDataLock
@ ledgerTimeoutRetriesMax
void setTimer()
Schedule a call to queueJob() after mTimerInterval.
void init(ScopedLockType &collectionLock)
std::recursive_mutex mLock
NetClock::time_point parentCloseTime