1#include <xrpld/app/ledger/LedgerMaster.h>
2#include <xrpld/app/ledger/LedgerReplayer.h>
3#include <xrpld/app/ledger/detail/LedgerReplayMsgHandler.h>
4#include <xrpld/app/main/Application.h>
6#include <xrpl/basics/safe_cast.h>
7#include <xrpl/protocol/LedgerHeader.h>
13 : app_(app), replayer_(replayer), journal_(app.getJournal(
"LedgerReplayMsgHandler"))
17protocol::TMProofPathResponse
21 protocol::TMProofPathRequest& packet = *msg;
22 protocol::TMProofPathResponse reply;
24 if (!packet.has_key() || !packet.has_ledgerhash() || !packet.has_type() ||
26 !protocol::TMLedgerMapType_IsValid(packet.type()))
29 reply.set_error(protocol::TMReplyError::reBAD_REQUEST);
32 reply.set_key(packet.key());
33 reply.set_ledgerhash(packet.ledgerhash());
34 reply.set_type(packet.type());
36 uint256 const key(packet.key());
37 uint256 const ledgerHash(packet.ledgerhash());
41 JLOG(
journal_.
debug()) <<
"getProofPath: Don't have ledger " << ledgerHash;
42 reply.set_error(protocol::TMReplyError::reNO_LEDGER);
47 switch (packet.type())
49 case protocol::lmACCOUNT_STATE:
50 return ledger->stateMap().getProofPath(key);
51 case protocol::lmTRANSACTION:
52 return ledger->txMap().getProofPath(key);
62 JLOG(
journal_.
debug()) <<
"getProofPath: Don't have the node " << key <<
" of ledger "
64 reply.set_error(protocol::TMReplyError::reNO_NODE);
70 addRaw(ledger->header(), nData);
73 for (
auto const& b : *path)
74 reply.add_path(b.data(), b.size());
76 JLOG(
journal_.
debug()) <<
"getProofPath for the node " << key <<
" of ledger " << ledgerHash
77 <<
" path length " << path->
size();
85 protocol::TMProofPathResponse
const& reply = *msg;
86 if (reply.has_error() || !reply.has_key() || !reply.has_ledgerhash() || !reply.has_type() ||
87 !reply.has_ledgerheader() || reply.path_size() == 0)
93 if (reply.type() != protocol::lmACCOUNT_STATE)
95 JLOG(
journal_.
debug()) <<
"Bad message: we only support the state ShaMap for now";
100 auto info =
deserializeHeader({reply.ledgerheader().data(), reply.ledgerheader().size()});
101 uint256 const replyHash(reply.ledgerhash());
107 info.hash = replyHash;
109 uint256 const key(reply.key());
112 JLOG(
journal_.
debug()) <<
"Bad message: we only support the short skip list for now. "
120 path.
reserve(reply.path_size());
121 for (
int i = 0; i < reply.path_size(); ++i)
123 path.
emplace_back(reply.path(i).begin(), reply.path(i).end());
128 JLOG(
journal_.
debug()) <<
"Bad message: Proof path verify failed";
134 if (!node || !node->isLeaf())
140 if (
auto item = safe_downcast<SHAMapLeafNode*>(node.get())->peekItem())
146 JLOG(
journal_.
debug()) <<
"Bad message: Cannot get ShaMapItem";
150protocol::TMReplayDeltaResponse
154 protocol::TMReplayDeltaRequest
const& packet = *msg;
155 protocol::TMReplayDeltaResponse reply;
157 if (!packet.has_ledgerhash() || packet.ledgerhash().size() !=
uint256::size())
160 reply.set_error(protocol::TMReplyError::reBAD_REQUEST);
163 reply.set_ledgerhash(packet.ledgerhash());
165 uint256 const ledgerHash{packet.ledgerhash()};
167 if (!ledger || !ledger->isImmutable())
169 JLOG(
journal_.
debug()) <<
"getReplayDelta: Don't have ledger " << ledgerHash;
170 reply.set_error(protocol::TMReplyError::reNO_LEDGER);
176 addRaw(ledger->header(), nData);
179 auto const& txMap = ledger->txMap();
180 txMap.visitLeaves([&](boost::intrusive_ptr<SHAMapItem const>
const&
txNode) {
184 JLOG(
journal_.
debug()) <<
"getReplayDelta for ledger " << ledgerHash <<
" txMap hash "
185 << txMap.getHash().as_uint256();
193 protocol::TMReplayDeltaResponse
const& reply = *msg;
194 if (reply.has_error() || !reply.has_ledgerheader())
200 auto info =
deserializeHeader({reply.ledgerheader().data(), reply.ledgerheader().size()});
201 uint256 const replyHash(reply.ledgerhash());
207 info.hash = replyHash;
209 auto numTxns = reply.transaction_size();
214 for (
int i = 0; i < numTxns; ++i)
221 reply.transaction(i).data(), reply.transaction(i).size());
233 auto tid = tx->getTransactionID();
235 orderedTxns.
emplace(meta[sfTransactionIndex], std::move(tx));
253 JLOG(
journal_.
debug()) <<
"Bad message: Transactions verify failed";
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
bool processProofPathResponse(std::shared_ptr< protocol::TMProofPathResponse > const &msg)
Process TMProofPathResponse.
protocol::TMProofPathResponse processProofPathRequest(std::shared_ptr< protocol::TMProofPathRequest > const &msg)
Process TMProofPathRequest and return TMProofPathResponse.
LedgerReplayMsgHandler(Application &app, LedgerReplayer &replayer)
LedgerReplayer & replayer_
bool processReplayDeltaResponse(std::shared_ptr< protocol::TMReplayDeltaResponse > const &msg)
Process TMReplayDeltaResponse.
protocol::TMReplayDeltaResponse processReplayDeltaRequest(std::shared_ptr< protocol::TMReplayDeltaRequest > const &msg)
Process TMReplayDeltaRequest and return TMReplayDeltaResponse.
Manages the lifetime of ledger replay tasks.
void gotReplayDelta(LedgerHeader const &info, std::map< std::uint32_t, std::shared_ptr< STTx const > > &&txns)
Process a ledger delta (extracted from a TMReplayDeltaResponse message)
void gotSkipList(LedgerHeader const &info, boost::intrusive_ptr< SHAMapItem const > const &data)
Process a skip list (extracted from a TMProofPathResponse message)
uint256 const & as_uint256() const
static intr_ptr::SharedPtr< SHAMapTreeNode > makeFromWire(Slice rawNode)
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
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
virtual LedgerMaster & getLedgerMaster()=0
virtual Family & getNodeFamily()=0
static constexpr std::size_t size()
T emplace_back(T... args)
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.
boost::intrusive_ptr< SHAMapItem > make_shamapitem(uint256 const &tag, Slice data)
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.
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
@ txNode
transaction plus metadata
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)