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)
111 <<
"Acquiring shard with no shard store available";
123 else if (shardStore &&
mSeq >= shardStore->earliestLedgerSeq())
125 if (
auto l = shardStore->fetchLedger(
mHash,
mSeq))
143 <<
" local store. " <<
mHash;
160 return app_.overlay().findPeerByShortID(id) != nullptr;
169 JLOG(
m_journal.
debug()) <<
"Deferring InboundLedger timer due to load";
176 ptr->invokeOnTimer();
186 if ((seq != 0) && (
mSeq == 0))
220 if (entry.second->type() == protocol::liAS_NODE)
226 <<
"Acquire " <<
mHash <<
" abort "
239 if (
mLedger->info().txHash.isNonZero())
241 if (
mLedger->txMap().getHash().isZero())
244 ret =
mLedger->txMap().getNeededHashes(max, filter);
255 if (
mLedger->info().accountHash.isNonZero())
257 if (
mLedger->stateMap().getHash().isZero())
260 ret =
mLedger->stateMap().getNeededHashes(max, filter);
300 auto makeLedger = [&,
this](
Blob const& data) {
302 mLedger = std::make_shared<Ledger>(
310 <<
" cannot be a ledger";
332 makeLedger(node->getData());
345 if (
mLedger->info().txHash.isZero())
354 if (
mLedger->txMap().fetchRoot(
368 if (
mLedger->info().accountHash.isZero())
371 <<
"We are acquiring a ledger with a zero account hash";
377 if (
mLedger->stateMap().fetchRoot(
378 SHAMapHash{mLedger->info().accountHash}, &filter))
434 <<
"No progress(" << pc <<
") for ledger " <<
mHash;
454 [
this](
auto peer) {
return peer->hasLedger(
mHash,
mSeq); });
501 if (self->mComplete && !self->mFailed)
503 self->app_.getLedgerMaster().checkAccept(self->getLedger());
504 self->app_.getLedgerMaster().tryAdvance();
507 self->app_.getInboundLedgers().logFailure(
508 self->mHash, self->mSeq);
522 <<
"Trigger on ledger: " <<
mHash << (
mComplete ?
" completed" :
"")
530 stream <<
"Trigger acquiring ledger " <<
mHash <<
" from " << peer;
532 stream <<
"Trigger acquiring ledger " <<
mHash;
551 protocol::TMGetLedger tmGL;
557 tmGL.set_querytype(protocol::qtINDIRECT);
566 protocol::TMGetObjectByHash tmBH;
567 bool typeSet =
false;
568 tmBH.set_query(
true);
570 for (
auto const& p : need)
576 tmBH.set_type(p.first);
580 if (p.first == tmBH.type())
582 protocol::TMIndexedObject* io = tmBH.add_objects();
583 io->set_hash(p.second.begin(), p.second.size());
585 io->set_ledgerseq(
mSeq);
590 std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS);
604 <<
"getNeededHashes says acquire is complete";
617 tmGL.set_itype(protocol::liBASE);
619 tmGL.set_ledgerseq(
mSeq);
621 << (peer ?
"selected peer" :
"all peers");
627 tmGL.set_ledgerseq(
mLedger->info().seq);
632 tmGL.set_querydepth(0);
634 else if (peer && peer->isHighLatency())
637 tmGL.set_querydepth(2);
640 tmGL.set_querydepth(1);
648 if (!
mLedger->stateMap().isValid())
652 else if (
mLedger->stateMap().getHash().isZero())
655 tmGL.set_itype(protocol::liAS_NODE);
658 << (peer ?
"selected peer" :
"all peers");
678 if (!
mLedger->stateMap().isValid())
694 tmGL.set_itype(protocol::liAS_NODE);
695 for (
auto const&
id : nodes)
697 *(tmGL.add_nodeids()) =
id.first.getRawString();
701 <<
"Sending AS node request (" << nodes.size()
703 << (peer ?
"selected peer" :
"all peers");
720 if (!
mLedger->txMap().isValid())
724 else if (
mLedger->txMap().getHash().isZero())
727 tmGL.set_itype(protocol::liTX_NODE);
730 << (peer ?
"selected peer" :
"all peers");
744 if (!
mLedger->txMap().isValid())
760 tmGL.set_itype(protocol::liTX_NODE);
761 for (
auto const& n : nodes)
763 *(tmGL.add_nodeids()) = n.first.getRawString();
766 <<
"Sending TX node request (" << nodes.size()
767 <<
") to " << (peer ?
"selected peer" :
"all peers");
782 <<
"Done:" << (
mComplete ?
" complete" :
"")
797 nodes.begin(), nodes.end(), [
this](
auto const& item) {
798 return mRecentNodes.count(item.second) == 0;
804 if (dup == nodes.begin())
818 nodes.erase(dup, nodes.end());
824 if (nodes.size() > limit)
827 for (
auto const& n : nodes)
845 mLedger = std::make_shared<Ledger>(
851 <<
"Acquire hash mismatch: " <<
mLedger->info().hash
864 s.
addRaw(data.data(), data.size());
867 if (
mLedger->info().txHash.isZero())
870 if (
mLedger->info().accountHash.isZero())
873 mLedger->txMap().setSynching();
874 mLedger->stateMap().setSynching();
901 auto nodeIDit = nodeIDs.
cbegin();
902 auto nodeDatait = data.begin();
906 while (nodeIDit != nodeIDs.
cend())
908 if (nodeIDit->isRoot())
910 san +=
mLedger->txMap().addRootNode(
920 san +=
mLedger->txMap().addKnownNode(
921 *nodeIDit,
makeSlice(*nodeDatait), &filter);
930 if (!
mLedger->txMap().isSynching())
954 <<
"got ASdata (" << nodeIDs.
size() <<
") acquiring ledger " <<
mHash;
955 if (nodeIDs.
size() == 1)
975 auto nodeIDit = nodeIDs.
cbegin();
976 auto nodeDatait = data.begin();
980 while (nodeIDit != nodeIDs.
cend())
982 if (nodeIDit->isRoot())
984 san +=
mLedger->stateMap().addRootNode(
997 san +=
mLedger->stateMap().addKnownNode(
998 *nodeIDit,
makeSlice(*nodeDatait), &filter);
1010 if (!
mLedger->stateMap().isSynching())
1044 san +=
mLedger->stateMap().addRootNode(
1069 san +=
mLedger->txMap().addRootNode(
1104 protocol::TMGetObjectByHash::otTRANSACTION_NODE, h));
1144 protocol::TMLedgerData& packet)
1148 if (packet.type() == protocol::liBASE)
1150 if (packet.nodes_size() < 1)
1171 if (!
mHaveState && (packet.nodes().size() > 1) &&
1190 if ((packet.type() == protocol::liTX_NODE) ||
1191 (packet.type() == protocol::liAS_NODE))
1193 if (packet.nodes().size() == 0)
1201 nodeIDs.
reserve(packet.nodes().size());
1203 nodeData.
reserve(packet.nodes().size());
1205 for (
int i = 0; i < packet.nodes().size(); ++i)
1207 const protocol::TMLedgerNode& node = packet.nodes(i);
1209 if (!node.has_nodeid() || !node.has_nodedata())
1217 SHAMapNodeID(node.nodeid().data(), node.nodeid().size()));
1219 Blob(node.nodedata().begin(), node.nodedata().end()));
1224 if (packet.type() == protocol::liTX_NODE)
1252 int chosenPeerCount = -1;
1273 for (
auto& entry : data)
1275 if (
auto peer = entry.first.lock())
1278 if (count > chosenPeerCount)
1280 chosenPeerCount = count;
1281 chosenPeer = std::move(peer);
1301 ret[jss::complete] =
true;
1304 ret[jss::failed] =
true;
1307 ret[jss::peers] =
static_cast<int>(
mPeers.size());
1326 ret[jss::needed_state_hashes] = hv;
1336 ret[jss::needed_transaction_hashes] = hv;
std::set< uint256 > mRecentNodes
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
std::vector< neededHash_t > getNeededHashes()
@ ledgerMaster
ledger master data for signing
std::vector< unsigned char > Blob
Storage for linear binary data.
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)
bool mProgress
Whether forward progress has been made.
Stream trace() const
Severity stream access functions.
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.
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)
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.
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq)=0
Store the object.
bool takeTxNode(const std::vector< SHAMapNodeID > &IDs, const std::vector< Blob > &data, SHAMapAddNode &)
Process TX data received from a peer Call with a lock.
Value & append(const Value &value)
Append value to array at the end.
std::shared_ptr< Ledger > mLedger
virtual Family * shardFamily()=0
T shared_from_this(T... args)
virtual Family & family()=0
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 std::shared_ptr< NodeObject > fetch(uint256 const &hash, std::uint32_t seq)=0
Fetch an object.
virtual Config & config()=0
virtual void onLedgerFetched()=0
Called when a complete ledger is obtained.
std::string getRawString() const
int addRaw(Blob const &vector)
virtual JobQueue & getJobQueue()=0
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.
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
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
bool takeAsNode(const std::vector< SHAMapNodeID > &IDs, const std::vector< Blob > &data, SHAMapAddNode &)
Process AS data received from a peer Call with a lock.
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 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.
virtual std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id)=0
Returns the peer with the matching short id, or null.
void init(ScopedLockType &collectionLock)
std::recursive_mutex mLock
NetClock::time_point parentCloseTime