Compare commits

...

2 Commits

Author SHA1 Message Date
Bronek Kozicki
1526b434ad Version 3.0.0-rc1 2025-11-03 11:36:50 +00:00
Vlad
0f1b607bb4 refactor: Improve txset handling (#5951) 2025-11-03 11:36:41 +00:00
3 changed files with 88 additions and 52 deletions

View File

@@ -36,7 +36,7 @@ namespace BuildInfo {
// and follow the format described at http://semver.org/
//------------------------------------------------------------------------------
// clang-format off
char const* const versionString = "3.0.0-b1"
char const* const versionString = "3.0.0-rc1"
// clang-format on
#if defined(DEBUG) || defined(SANITIZER)

View File

@@ -1225,7 +1225,16 @@ OverlayImpl::relay(
{
auto& txn = tx->get();
SerialIter sit(makeSlice(txn.rawtransaction()));
relay = !isPseudoTx(STTx{sit});
try
{
relay = !isPseudoTx(STTx{sit});
}
catch (std::exception const&)
{
// Could not construct STTx, not relaying
JLOG(journal_.debug()) << "Could not construct STTx: " << hash;
return;
}
}
Overlay::PeerSequence peers = {};

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <xrpld/shamap/SHAMap.h>
#include <xrpld/shamap/SHAMapLeafNode.h>
#include <xrpld/shamap/SHAMapSyncFilter.h>
#include <xrpl/basics/random.h>
@@ -591,16 +592,16 @@ SHAMap::addKnownNode(
}
auto const generation = f_.getFullBelowCache()->getGeneration();
SHAMapNodeID iNodeID;
auto iNode = root_.get();
SHAMapNodeID currNodeID;
auto currNode = root_.get();
while (iNode->isInner() &&
!static_cast<SHAMapInnerNode*>(iNode)->isFullBelow(generation) &&
(iNodeID.getDepth() < node.getDepth()))
while (currNode->isInner() &&
!static_cast<SHAMapInnerNode*>(currNode)->isFullBelow(generation) &&
(currNodeID.getDepth() < node.getDepth()))
{
int branch = selectBranch(iNodeID, node.getNodeID());
int const branch = selectBranch(currNodeID, node.getNodeID());
XRPL_ASSERT(branch >= 0, "ripple::SHAMap::addKnownNode : valid branch");
auto inner = static_cast<SHAMapInnerNode*>(iNode);
auto inner = static_cast<SHAMapInnerNode*>(currNode);
if (inner->isEmptyBranch(branch))
{
JLOG(journal_.warn()) << "Add known node for empty branch" << node;
@@ -614,58 +615,84 @@ SHAMap::addKnownNode(
}
auto prevNode = inner;
std::tie(iNode, iNodeID) = descend(inner, iNodeID, branch, filter);
std::tie(currNode, currNodeID) =
descend(inner, currNodeID, branch, filter);
if (iNode == nullptr)
if (currNode != nullptr)
continue;
auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
if (!newNode || childHash != newNode->getHash())
{
auto newNode = SHAMapTreeNode::makeFromWire(rawNode);
JLOG(journal_.warn()) << "Corrupt node received";
return SHAMapAddNode::invalid();
}
if (!newNode || childHash != newNode->getHash())
// In rare cases, a node can still be corrupt even after hash
// validation. For leaf nodes, we perform an additional check to
// ensure the node's position in the tree is consistent with its
// content to prevent inconsistencies that could
// propagate further down the line.
if (newNode->isLeaf())
{
auto const& actualKey =
static_cast<SHAMapLeafNode const*>(newNode.get())
->peekItem()
->key();
// Validate that this leaf belongs at the target position
auto const expectedNodeID =
SHAMapNodeID::createID(node.getDepth(), actualKey);
if (expectedNodeID.getNodeID() != node.getNodeID())
{
JLOG(journal_.warn()) << "Corrupt node received";
JLOG(journal_.debug())
<< "Leaf node position mismatch: "
<< "expected=" << expectedNodeID.getNodeID()
<< ", actual=" << node.getNodeID();
return SHAMapAddNode::invalid();
}
}
// Inner nodes must be at a level strictly less than 64
// but leaf nodes (while notionally at level 64) can be
// at any depth up to and including 64:
if ((iNodeID.getDepth() > leafDepth) ||
(newNode->isInner() && iNodeID.getDepth() == leafDepth))
{
// Map is provably invalid
state_ = SHAMapState::Invalid;
return SHAMapAddNode::useful();
}
if (iNodeID != node)
{
// Either this node is broken or we didn't request it (yet)
JLOG(journal_.warn()) << "unable to hook node " << node;
JLOG(journal_.info()) << " stuck at " << iNodeID;
JLOG(journal_.info()) << "got depth=" << node.getDepth()
<< ", walked to= " << iNodeID.getDepth();
return SHAMapAddNode::useful();
}
if (backed_)
canonicalize(childHash, newNode);
newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
if (filter)
{
Serializer s;
newNode->serializeWithPrefix(s);
filter->gotNode(
false,
childHash,
ledgerSeq_,
std::move(s.modData()),
newNode->getType());
}
// Inner nodes must be at a level strictly less than 64
// but leaf nodes (while notionally at level 64) can be
// at any depth up to and including 64:
if ((currNodeID.getDepth() > leafDepth) ||
(newNode->isInner() && currNodeID.getDepth() == leafDepth))
{
// Map is provably invalid
state_ = SHAMapState::Invalid;
return SHAMapAddNode::useful();
}
if (currNodeID != node)
{
// Either this node is broken or we didn't request it (yet)
JLOG(journal_.warn()) << "unable to hook node " << node;
JLOG(journal_.info()) << " stuck at " << currNodeID;
JLOG(journal_.info()) << "got depth=" << node.getDepth()
<< ", walked to= " << currNodeID.getDepth();
return SHAMapAddNode::useful();
}
if (backed_)
canonicalize(childHash, newNode);
newNode = prevNode->canonicalizeChild(branch, std::move(newNode));
if (filter)
{
Serializer s;
newNode->serializeWithPrefix(s);
filter->gotNode(
false,
childHash,
ledgerSeq_,
std::move(s.modData()),
newNode->getType());
}
return SHAMapAddNode::useful();
}
JLOG(journal_.trace()) << "got node, already had it (late)";