1#include <xrpld/app/ledger/detail/LedgerReplayMsgHandler.h>
3#include <xrpld/app/ledger/LedgerMaster.h>
4#include <xrpld/app/ledger/LedgerReplayer.h>
5#include <xrpld/app/main/Application.h>
7#include <xrpl/basics/Blob.h>
8#include <xrpl/basics/Log.h>
9#include <xrpl/basics/Slice.h>
10#include <xrpl/basics/base_uint.h>
11#include <xrpl/basics/safe_cast.h>
12#include <xrpl/protocol/Indexes.h>
13#include <xrpl/protocol/LedgerHeader.h>
14#include <xrpl/protocol/SField.h>
15#include <xrpl/protocol/STObject.h>
16#include <xrpl/protocol/STTx.h>
17#include <xrpl/protocol/Serializer.h>
18#include <xrpl/shamap/SHAMapItem.h>
19#include <xrpl/shamap/SHAMapMissingNode.h>
20#include <xrpl/shamap/SHAMapTreeNode.h>
22#include <boost/smart_ptr/intrusive_ptr.hpp>
40protocol::TMProofPathResponse
44 protocol::TMProofPathRequest& packet = *msg;
45 protocol::TMProofPathResponse reply;
47 if (!packet.has_key() || !packet.has_ledgerhash() || !packet.has_type() ||
49 !protocol::TMLedgerMapType_IsValid(packet.type()))
51 JLOG(
journal_.debug()) <<
"getProofPath: Invalid request";
52 reply.set_error(protocol::TMReplyError::reBAD_REQUEST);
55 reply.set_key(packet.key());
56 reply.set_ledgerhash(packet.ledgerhash());
57 reply.set_type(packet.type());
61 auto ledger =
app_.getLedgerMaster().getLedgerByHash(ledgerHash);
64 JLOG(
journal_.debug()) <<
"getProofPath: Don't have ledger " << ledgerHash;
65 reply.set_error(protocol::TMReplyError::reNO_LEDGER);
70 switch (packet.type())
72 case protocol::lmACCOUNT_STATE:
73 return ledger->stateMap().getProofPath(key);
74 case protocol::lmTRANSACTION:
75 return ledger->txMap().getProofPath(key);
85 JLOG(
journal_.debug()) <<
"getProofPath: Don't have the node " << key <<
" of ledger "
87 reply.set_error(protocol::TMReplyError::reNO_NODE);
93 addRaw(ledger->header(), nData);
96 for (
auto const& b : *
path)
97 reply.add_path(b.data(), b.size());
99 JLOG(
journal_.debug()) <<
"getProofPath for the node " << key <<
" of ledger " << ledgerHash
100 <<
" path length " <<
path->size();
108 protocol::TMProofPathResponse
const& reply = *msg;
109 if (reply.has_error())
111 JLOG(
journal_.debug()) <<
"ProofPathResponse: peer reported error";
114 if (!reply.has_key() || !reply.has_ledgerhash() || !reply.has_type() ||
115 !reply.has_ledgerheader() || reply.path_size() == 0 ||
118 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed (missing or wrong-size fields)";
122 if (reply.type() != protocol::lmACCOUNT_STATE)
124 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed (unsupported map type)";
136 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed header (" << e.
what() <<
")";
142 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed (hash mismatch)";
145 info.
hash = replyHash;
150 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed (unexpected key " << key <<
")";
156 path.reserve(reply.path_size());
157 for (
int i = 0; i < reply.path_size(); ++i)
159 path.emplace_back(reply.path(i).begin(), reply.path(i).end());
164 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed (proof path verify failed)";
176 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed SHAMap node (" << e.
what() <<
")";
179 if (!node || !node->isLeaf())
181 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed (not a leaf node)";
191 JLOG(
journal_.debug()) <<
"ProofPathResponse: malformed (no SHAMapItem)";
195protocol::TMReplayDeltaResponse
199 protocol::TMReplayDeltaRequest
const& packet = *msg;
200 protocol::TMReplayDeltaResponse reply;
202 if (!packet.has_ledgerhash() || packet.ledgerhash().size() !=
uint256::size())
204 JLOG(
journal_.debug()) <<
"getReplayDelta: Invalid request";
205 reply.set_error(protocol::TMReplyError::reBAD_REQUEST);
208 reply.set_ledgerhash(packet.ledgerhash());
211 auto ledger =
app_.getLedgerMaster().getLedgerByHash(ledgerHash);
212 if (!ledger || !ledger->isImmutable())
214 JLOG(
journal_.debug()) <<
"getReplayDelta: Don't have ledger " << ledgerHash;
215 reply.set_error(protocol::TMReplyError::reNO_LEDGER);
221 addRaw(ledger->header(), nData);
224 auto const& txMap = ledger->txMap();
225 txMap.visitLeaves([&](boost::intrusive_ptr<SHAMapItem const>
const& txNode) {
226 reply.add_transaction(txNode->data(), txNode->size());
229 JLOG(
journal_.debug()) <<
"getReplayDelta for ledger " << ledgerHash <<
" txMap hash "
230 << txMap.getHash().asUInt256();
238 protocol::TMReplayDeltaResponse
const& reply = *msg;
239 if (reply.has_error())
241 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: peer reported error";
244 if (!reply.has_ledgerheader() || !reply.has_ledgerhash() ||
247 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: malformed (missing or wrong-size fields)";
258 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: malformed header (" << e.
what() <<
")";
264 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: malformed (hash mismatch)";
267 info.
hash = replyHash;
269 auto numTxns = reply.transaction_size();
274 for (
int i = 0; i < numTxns; ++i)
281 reply.transaction(i).data(), reply.transaction(i).size());
290 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: malformed (tx deserialize)";
293 auto tid = tx->getTransactionID();
295 orderedTxns.
emplace(meta[sfTransactionIndex], std::move(tx));
300 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: malformed (tx map add)";
307 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: malformed transactions (" << e.
what()
314 JLOG(
journal_.debug()) <<
"ReplayDeltaResponse: malformed (transactions verify failed)";
318 replayer_.gotReplayDelta(info, std::move(orderedTxns));
static BaseUInt fromRaw(Container const &c)
static constexpr std::size_t size()
protocol::TMProofPathResponse processProofPathRequest(std::shared_ptr< protocol::TMProofPathRequest > const &msg)
Process TMProofPathRequest and return TMProofPathResponse.
LedgerReplayMsgHandler(Application &app, LedgerReplayer &replayer)
ReplayMsgStatus processReplayDeltaResponse(std::shared_ptr< protocol::TMReplayDeltaResponse > const &msg)
Process TMReplayDeltaResponse.
ReplayMsgStatus processProofPathResponse(std::shared_ptr< protocol::TMProofPathResponse > const &msg)
Process TMProofPathResponse.
LedgerReplayer & replayer_
protocol::TMReplayDeltaResponse processReplayDeltaRequest(std::shared_ptr< protocol::TMReplayDeltaRequest > const &msg)
Process TMReplayDeltaRequest and return TMReplayDeltaResponse.
Manages the lifetime of ledger replay tasks.
uint256 const & asUInt256() const
static SHAMapTreeNodePtr makeFromWire(Slice rawNode)
static bool verifyProofPath(uint256 const &rootHash, uint256 const &key, std::vector< Blob > const &path)
Verify the proof path.
bool addGiveItem(SHAMapNodeType type, boost::intrusive_ptr< SHAMapItem const > item)
SHAMapHash getHash() const
Slice getSlice(std::size_t bytes)
void const * getDataPtr() const
Slice slice() const noexcept
T * get() const
Get the raw pointer.
Keylet const & skip() noexcept
The index of the "short" skip list.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
intr_ptr::SharedPtr< SHAMapTreeNode > SHAMapTreeNodePtr
Dest safeDowncast(Src *s) noexcept
LedgerHeader deserializeHeader(Slice data, bool hasHash=false)
Deserialize a ledger header from a byte array.
uint256 calculateLedgerHash(LedgerHeader const &info)
Calculate the hash of a ledger header.
Slice makeSlice(std::array< T, N > const &a)
boost::intrusive_ptr< SHAMapItem > makeShamapitem(uint256 const &tag, Slice data)
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
ReplayMsgStatus
Outcome of processing an incoming ledger-replay response.
@ Malformed
Protocol-level violation; no honest peer would produce this.
@ BadData
Peer reported has_error() (legitimate "cannot fulfill" signal).