mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 06:25:51 +00:00
Complete SHAMap V2 cutover
This commit is contained in:
committed by
Miguel Portilla
parent
63a5522406
commit
d88b63d4c8
@@ -981,11 +981,13 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
|||||||
auto buildLCL = std::make_shared<Ledger>(
|
auto buildLCL = std::make_shared<Ledger>(
|
||||||
*mPreviousLedger,
|
*mPreviousLedger,
|
||||||
app_.timeKeeper().closeTime());
|
app_.timeKeeper().closeTime());
|
||||||
auto constexpr v2_ledger_seq_switch = 40'000'000;
|
auto const v2_enabled = buildLCL->rules().enabled(featureSHAMapV2,
|
||||||
if (buildLCL->info().seq > v2_ledger_seq_switch &&
|
app_.config().features);
|
||||||
!buildLCL->stateMap().is_v2())
|
auto v2_transition = false;
|
||||||
|
if (v2_enabled && !buildLCL->stateMap().is_v2())
|
||||||
{
|
{
|
||||||
buildLCL->make_v2();
|
buildLCL->make_v2();
|
||||||
|
v2_transition = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up to write SHAMap changes to our database,
|
// Set up to write SHAMap changes to our database,
|
||||||
@@ -1022,15 +1024,10 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
|||||||
|
|
||||||
buildLCL->updateSkipList ();
|
buildLCL->updateSkipList ();
|
||||||
|
|
||||||
// unshare in case a nodestore load changed the
|
|
||||||
// version back, otherwise the map is inconsistent
|
|
||||||
if (buildLCL->info().seq > v2_ledger_seq_switch &&
|
|
||||||
!buildLCL->stateMap().is_v2())
|
|
||||||
{
|
{
|
||||||
buildLCL->unshare();
|
// Write the final version of all modified SHAMap
|
||||||
}
|
// nodes to the node store to preserve the new LCL
|
||||||
|
|
||||||
{
|
|
||||||
int asf = buildLCL->stateMap().flushDirty (
|
int asf = buildLCL->stateMap().flushDirty (
|
||||||
hotACCOUNT_NODE, buildLCL->info().seq);
|
hotACCOUNT_NODE, buildLCL->info().seq);
|
||||||
int tmf = buildLCL->txMap().flushDirty (
|
int tmf = buildLCL->txMap().flushDirty (
|
||||||
@@ -1039,6 +1036,7 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
|
|||||||
asf << " accounts and " <<
|
asf << " accounts and " <<
|
||||||
tmf << " transaction nodes";
|
tmf << " transaction nodes";
|
||||||
}
|
}
|
||||||
|
buildLCL->unshare();
|
||||||
|
|
||||||
// Accept ledger
|
// Accept ledger
|
||||||
buildLCL->setAccepted(closeTime, mCloseResolution,
|
buildLCL->setAccepted(closeTime, mCloseResolution,
|
||||||
|
|||||||
@@ -1006,7 +1006,7 @@ bool ApplicationImp::setup()
|
|||||||
enabledAmendments.append (detail::preEnabledAmendments ());
|
enabledAmendments.append (detail::preEnabledAmendments ());
|
||||||
|
|
||||||
m_amendmentTable = make_AmendmentTable (
|
m_amendmentTable = make_AmendmentTable (
|
||||||
weeks(2),
|
weeks{2},
|
||||||
MAJORITY_FRACTION,
|
MAJORITY_FRACTION,
|
||||||
supportedAmendments,
|
supportedAmendments,
|
||||||
enabledAmendments,
|
enabledAmendments,
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ extern uint256 const featureFeeEscalation;
|
|||||||
extern uint256 const featureFlowV2;
|
extern uint256 const featureFlowV2;
|
||||||
extern uint256 const featureOwnerPaysFee;
|
extern uint256 const featureOwnerPaysFee;
|
||||||
extern uint256 const featureCompareFlowV1V2;
|
extern uint256 const featureCompareFlowV1V2;
|
||||||
|
extern uint256 const featureSHAMapV2;
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|
||||||
|
|||||||
@@ -53,5 +53,6 @@ uint256 const featureFeeEscalation = feature("FeeEscalation");
|
|||||||
uint256 const featureFlowV2 = feature("FlowV2");
|
uint256 const featureFlowV2 = feature("FlowV2");
|
||||||
uint256 const featureOwnerPaysFee = feature("OwnerPaysFee");
|
uint256 const featureOwnerPaysFee = feature("OwnerPaysFee");
|
||||||
uint256 const featureCompareFlowV1V2 = feature("CompareFlowV1V2");
|
uint256 const featureCompareFlowV1V2 = feature("CompareFlowV1V2");
|
||||||
|
uint256 const featureSHAMapV2 = feature("SHAMapV2");
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ private:
|
|||||||
std::shared_ptr<SHAMapItem const> const& otherMapItem,
|
std::shared_ptr<SHAMapItem const> const& otherMapItem,
|
||||||
bool isFirstMap, Delta & differences, int & maxCount) const;
|
bool isFirstMap, Delta & differences, int & maxCount) const;
|
||||||
int walkSubTree (bool doWrite, NodeObjectType t, std::uint32_t seq);
|
int walkSubTree (bool doWrite, NodeObjectType t, std::uint32_t seq);
|
||||||
|
bool isInconsistentNode(std::shared_ptr<SHAMapAbstractNode> const& node) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ public:
|
|||||||
void shareChild (int m, std::shared_ptr<SHAMapAbstractNode> const& child);
|
void shareChild (int m, std::shared_ptr<SHAMapAbstractNode> const& child);
|
||||||
SHAMapAbstractNode* getChildPointer (int branch);
|
SHAMapAbstractNode* getChildPointer (int branch);
|
||||||
std::shared_ptr<SHAMapAbstractNode> getChild (int branch);
|
std::shared_ptr<SHAMapAbstractNode> getChild (int branch);
|
||||||
std::shared_ptr<SHAMapAbstractNode>
|
virtual std::shared_ptr<SHAMapAbstractNode>
|
||||||
canonicalizeChild (int branch, std::shared_ptr<SHAMapAbstractNode> node);
|
canonicalizeChild (int branch, std::shared_ptr<SHAMapAbstractNode> node);
|
||||||
|
|
||||||
// sync functions
|
// sync functions
|
||||||
@@ -212,6 +212,8 @@ public:
|
|||||||
uint256 const& key() const override;
|
uint256 const& key() const override;
|
||||||
void setChildren(std::shared_ptr<SHAMapTreeNode> const& child1,
|
void setChildren(std::shared_ptr<SHAMapTreeNode> const& child1,
|
||||||
std::shared_ptr<SHAMapTreeNode> const& child2);
|
std::shared_ptr<SHAMapTreeNode> const& child2);
|
||||||
|
std::shared_ptr<SHAMapAbstractNode>
|
||||||
|
canonicalizeChild (int branch, std::shared_ptr<SHAMapAbstractNode> node) override;
|
||||||
void invariants(bool is_v2, bool is_root = false) const override;
|
void invariants(bool is_v2, bool is_root = false) const override;
|
||||||
|
|
||||||
friend std::shared_ptr<SHAMapAbstractNode>
|
friend std::shared_ptr<SHAMapAbstractNode>
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const
|
|||||||
if (inNode->isInner())
|
if (inNode->isInner())
|
||||||
{
|
{
|
||||||
auto n = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(inNode);
|
auto n = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(inNode);
|
||||||
assert(n);
|
if (n == nullptr)
|
||||||
|
return nullptr;
|
||||||
nodeID = SHAMapNodeID{n->depth(), n->common()};
|
nodeID = SHAMapNodeID{n->depth(), n->common()};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -255,6 +256,11 @@ SHAMap::fetchNodeFromDB (SHAMapHash const& hash) const
|
|||||||
{
|
{
|
||||||
auto root = std::dynamic_pointer_cast<SHAMapInnerNode>(root_);
|
auto root = std::dynamic_pointer_cast<SHAMapInnerNode>(root_);
|
||||||
assert(root);
|
assert(root);
|
||||||
|
if (!root->isEmpty())
|
||||||
|
{
|
||||||
|
std::cerr << "isv2 = " << isv2 << '\n';
|
||||||
|
std::cerr << "is_v2() = " << is_v2() << '\n';
|
||||||
|
}
|
||||||
assert(root->isEmpty());
|
assert(root->isEmpty());
|
||||||
if (isv2)
|
if (isv2)
|
||||||
{
|
{
|
||||||
@@ -405,7 +411,7 @@ SHAMapAbstractNode* SHAMap::descend (SHAMapInnerNode* parent, int branch) const
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
std::shared_ptr<SHAMapAbstractNode> node = fetchNodeNT (parent->getChildHash (branch));
|
std::shared_ptr<SHAMapAbstractNode> node = fetchNodeNT (parent->getChildHash (branch));
|
||||||
if (!node)
|
if (!node || isInconsistentNode(node))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
node = parent->canonicalizeChild (branch, std::move(node));
|
node = parent->canonicalizeChild (branch, std::move(node));
|
||||||
@@ -420,7 +426,7 @@ SHAMap::descend (std::shared_ptr<SHAMapInnerNode> const& parent, int branch) con
|
|||||||
return node;
|
return node;
|
||||||
|
|
||||||
node = fetchNode (parent->getChildHash (branch));
|
node = fetchNode (parent->getChildHash (branch));
|
||||||
if (!node)
|
if (!node || isInconsistentNode(node))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
node = parent->canonicalizeChild (branch, std::move(node));
|
node = parent->canonicalizeChild (branch, std::move(node));
|
||||||
@@ -452,6 +458,8 @@ SHAMap::descend (SHAMapInnerNode * parent, SHAMapNodeID const& parentID,
|
|||||||
if (!child)
|
if (!child)
|
||||||
{
|
{
|
||||||
std::shared_ptr<SHAMapAbstractNode> childNode = fetchNodeNT (childHash, filter);
|
std::shared_ptr<SHAMapAbstractNode> childNode = fetchNodeNT (childHash, filter);
|
||||||
|
if (isInconsistentNode(childNode))
|
||||||
|
childNode = nullptr;
|
||||||
|
|
||||||
if (childNode)
|
if (childNode)
|
||||||
{
|
{
|
||||||
@@ -518,6 +526,8 @@ SHAMap::descendAsync (SHAMapInnerNode* parent, int branch,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isInconsistentNode(ptr))
|
||||||
|
ptr = nullptr;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
ptr = parent->canonicalizeChild (branch, std::move(ptr));
|
ptr = parent->canonicalizeChild (branch, std::move(ptr));
|
||||||
|
|
||||||
@@ -561,7 +571,8 @@ SHAMap::firstBelow(std::shared_ptr<SHAMapAbstractNode> node,
|
|||||||
{
|
{
|
||||||
if (is_v2())
|
if (is_v2())
|
||||||
{
|
{
|
||||||
auto inner2 = std::static_pointer_cast<SHAMapInnerNodeV2>(inner);
|
auto inner2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(inner);
|
||||||
|
assert(inner2 != nullptr);
|
||||||
stack.push({inner2, {inner2->depth(), inner2->common()}});
|
stack.push({inner2, {inner2->depth(), inner2->common()}});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1373,7 +1384,20 @@ SHAMap::invariants() const
|
|||||||
auto node = root_.get();
|
auto node = root_.get();
|
||||||
assert(node != nullptr);
|
assert(node != nullptr);
|
||||||
assert(!node->isLeaf());
|
assert(!node->isLeaf());
|
||||||
|
SharedPtrNodeStack stack;
|
||||||
|
for (auto leaf = peekFirstItem(stack); leaf != nullptr;
|
||||||
|
leaf = peekNextItem(leaf->peekItem()->key(), stack))
|
||||||
|
;
|
||||||
node->invariants(is_v2(), true);
|
node->invariants(is_v2(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SHAMap::isInconsistentNode(std::shared_ptr<SHAMapAbstractNode> const& node) const
|
||||||
|
{
|
||||||
|
if (std::dynamic_pointer_cast<SHAMapTreeNode>(node) != nullptr)
|
||||||
|
return false;
|
||||||
|
bool is_node_v2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) != nullptr;
|
||||||
|
return is_v2() != is_node_v2;
|
||||||
|
}
|
||||||
|
|
||||||
} // ripple
|
} // ripple
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ SHAMap::getMissingNodes(std::size_t max, SHAMapSyncFilter* filter)
|
|||||||
auto const& nodeHash = parent->getChildHash (branch);
|
auto const& nodeHash = parent->getChildHash (branch);
|
||||||
|
|
||||||
auto nodePtr = fetchNodeNT(nodeHash, filter);
|
auto nodePtr = fetchNodeNT(nodeHash, filter);
|
||||||
if (nodePtr)
|
if (nodePtr && !isInconsistentNode(nodePtr))
|
||||||
{
|
{
|
||||||
++hits;
|
++hits;
|
||||||
if (backed_)
|
if (backed_)
|
||||||
@@ -523,15 +523,18 @@ SHAMap::addKnownNode (const SHAMapNodeID& node, Blob const& rawNode,
|
|||||||
return SHAMapAddNode::useful ();
|
return SHAMapAddNode::useful ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
if (newNode && isInconsistentNode(newNode))
|
||||||
if (newNode && newNode->isInner())
|
|
||||||
{
|
{
|
||||||
bool isv2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(newNode) != nullptr;
|
return SHAMapAddNode::invalid();
|
||||||
assert(isv2 == is_v2());
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (backed_)
|
if (backed_)
|
||||||
|
{
|
||||||
|
auto temp = newNode;
|
||||||
canonicalize (childHash, newNode);
|
canonicalize (childHash, newNode);
|
||||||
|
if (isInconsistentNode(newNode))
|
||||||
|
newNode = temp;
|
||||||
|
}
|
||||||
newNode = prevNode->canonicalizeChild (branch, std::move(newNode));
|
newNode = prevNode->canonicalizeChild (branch, std::move(newNode));
|
||||||
|
|
||||||
if (filter)
|
if (filter)
|
||||||
|
|||||||
@@ -710,6 +710,33 @@ SHAMapInnerNode::canonicalizeChild(int branch, std::shared_ptr<SHAMapAbstractNod
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Hook this node up
|
// Hook this node up
|
||||||
|
// node must not be a v2 inner node
|
||||||
|
assert(std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) == nullptr);
|
||||||
|
mChildren[branch] = node;
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SHAMapAbstractNode>
|
||||||
|
SHAMapInnerNodeV2::canonicalizeChild(int branch, std::shared_ptr<SHAMapAbstractNode> node)
|
||||||
|
{
|
||||||
|
assert (branch >= 0 && branch < 16);
|
||||||
|
assert (isInner());
|
||||||
|
assert (node);
|
||||||
|
assert (node->getNodeHash() == mHashes[branch]);
|
||||||
|
|
||||||
|
std::unique_lock <std::mutex> lock (childLock);
|
||||||
|
if (mChildren[branch])
|
||||||
|
{
|
||||||
|
// There is already a node hooked up, return it
|
||||||
|
node = mChildren[branch];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Hook this node up
|
||||||
|
// node must not be a v1 inner node
|
||||||
|
assert(std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) != nullptr ||
|
||||||
|
std::dynamic_pointer_cast<SHAMapTreeNode>(node) != nullptr);
|
||||||
mChildren[branch] = node;
|
mChildren[branch] = node;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
|
|||||||
Reference in New Issue
Block a user