Remove SHAMap V2

This commit is contained in:
Howard Hinnant
2019-08-26 16:06:39 -04:00
committed by Manoj doshi
parent 33ab0cd7bd
commit 7228b2e068
23 changed files with 113 additions and 1162 deletions

View File

@@ -895,7 +895,6 @@ else ()
src/test/ledger/Invariants_test.cpp
src/test/ledger/PaymentSandbox_test.cpp
src/test/ledger/PendingSaves_test.cpp
src/test/ledger/SHAMapV2_test.cpp
src/test/ledger/SkipList_test.cpp
src/test/ledger/View_test.cpp
#[===============================[

View File

@@ -293,7 +293,7 @@ RCLConsensus::Adaptor::onClose(
auto initialLedger = app_.openLedger().current();
auto initialSet = std::make_shared<SHAMap>(
SHAMapType::TRANSACTION, app_.family(), SHAMap::version{1});
SHAMapType::TRANSACTION, app_.family());
initialSet->setUnbacked();
// Build SHAMap containing all transactions in our open ledger

View File

@@ -184,9 +184,9 @@ Ledger::Ledger (
Family& family)
: mImmutable (false)
, txMap_ (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
family, SHAMap::version{1}))
family))
, stateMap_ (std::make_shared <SHAMap> (SHAMapType::STATE,
family, SHAMap::version{1}))
family))
, rules_{config.features}
{
info_.seq = 1;
@@ -224,11 +224,9 @@ Ledger::Ledger (
beast::Journal j)
: mImmutable (true)
, txMap_ (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
info.txHash, family,
SHAMap::version{getSHAMapV2(info) ? 2 : 1}))
info.txHash, family))
, stateMap_ (std::make_shared <SHAMap> (SHAMapType::STATE,
info.accountHash, family,
SHAMap::version{getSHAMapV2(info) ? 2 : 1}))
info.accountHash, family))
, rules_ (config.features)
, info_ (info)
{
@@ -268,8 +266,7 @@ Ledger::Ledger (Ledger const& prevLedger,
: mImmutable (false)
, txMap_ (std::make_shared <SHAMap> (
SHAMapType::TRANSACTION,
prevLedger.stateMap_->family(),
prevLedger.stateMap_->get_version()))
prevLedger.stateMap_->family()))
, stateMap_ (prevLedger.stateMap_->snapShot (true))
, fees_(prevLedger.fees_)
, rules_(prevLedger.rules_)
@@ -285,11 +282,6 @@ Ledger::Ledger (Ledger const& prevLedger,
prevLedger.info_.closeTimeResolution,
getCloseAgree(prevLedger.info()), info_.seq);
if (stateMap_->is_v2())
{
info_.closeFlags |= sLCF_SHAMapV2;
}
if (prevLedger.info_.closeTime == NetClock::time_point{})
{
info_.closeTime = roundCloseTime(closeTime, info_.closeTimeResolution);
@@ -307,11 +299,9 @@ Ledger::Ledger (
Family& family)
: mImmutable (true)
, txMap_ (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
info.txHash, family,
SHAMap::version{getSHAMapV2(info) ? 2 : 1}))
info.txHash, family))
, stateMap_ (std::make_shared <SHAMap> (SHAMapType::STATE,
info.accountHash, family,
SHAMap::version{getSHAMapV2(info) ? 2 : 1}))
info.accountHash, family))
, rules_{config.features}
, info_ (info)
{
@@ -323,9 +313,9 @@ Ledger::Ledger (std::uint32_t ledgerSeq,
Family& family)
: mImmutable (false)
, txMap_ (std::make_shared <SHAMap> (
SHAMapType::TRANSACTION, family, SHAMap::version{1}))
SHAMapType::TRANSACTION, family))
, stateMap_ (std::make_shared <SHAMap> (
SHAMapType::STATE, family, SHAMap::version{1}))
SHAMapType::STATE, family))
, rules_{config.features}
{
info_.seq = ledgerSeq;
@@ -1045,19 +1035,6 @@ bool pendSaveValidated (
return saveValidatedLedger(app, ledger, isCurrent);
}
void
Ledger::make_v2()
{
assert (! mImmutable);
stateMap_ = stateMap_->make_v2();
txMap_ = txMap_->make_v2();
info_.validated = false;
info_.accountHash = stateMap_->getHash ().as_uint256();
info_.txHash = txMap_->getHash ().as_uint256();
info_.hash = calculateLedgerHash (info_);
info_.closeFlags |= sLCF_SHAMapV2;
}
void
Ledger::unshare() const
{

View File

@@ -314,7 +314,6 @@ public:
bool assertSane (beast::Journal ledgerJ) const;
void make_v2();
void invariants() const;
void unshare() const;
private:

View File

@@ -47,9 +47,6 @@ buildLedgerImpl(
{
auto built = std::make_shared<Ledger>(*parent, closeTime);
if (built->rules().enabled(featureSHAMapV2) && !built->stateMap().is_v2())
built->make_v2();
// Set up to write SHAMap changes to our database,
// perform updates, extract changes

View File

@@ -80,7 +80,7 @@ public:
{
m_zeroSet.mSet = std::make_shared<SHAMap> (
SHAMapType::TRANSACTION, uint256(),
app_.family(), SHAMap::version{1});
app_.family());
m_zeroSet.mSet->setUnbacked();
}

View File

@@ -47,7 +47,7 @@ TransactionAcquire::TransactionAcquire (Application& app, uint256 const& hash, c
, j_(app.journal("TransactionAcquire"))
{
mMap = std::make_shared<SHAMap> (SHAMapType::TRANSACTION, hash,
app_.family(), SHAMap::version{1});
app_.family());
mMap->setUnbacked ();
}

View File

@@ -421,21 +421,12 @@ public:
static
std::uint32_t const sLCF_NoConsensusTime = 0x01;
static
std::uint32_t const sLCF_SHAMapV2 = 0x02;
inline
bool getCloseAgree (LedgerInfo const& info)
{
return (info.closeFlags & sLCF_NoConsensusTime) == 0;
}
inline
bool getSHAMapV2 (LedgerInfo const& info)
{
return (info.closeFlags & sLCF_SHAMapV2) != 0;
}
void addRaw (LedgerInfo const&, Serializer&);
} // ripple

View File

@@ -204,91 +204,6 @@ nodeobject_decompress (void const* in,
write(os, is(512), 512);
break;
}
case 5: // compressed v2 inner node
{
auto const hs =
field<std::uint16_t>::size; // Mask size
if (in_size < hs + 65)
Throw<std::runtime_error> (
"nodeobject codec v2: short inner node size: "
+ std::string("size = ") + std::to_string(in_size)
+ " hs = " + std::to_string(hs));
istream is(p, in_size);
std::uint16_t mask;
read<std::uint16_t>(is, mask); // Mask
in_size -= hs;
std::uint8_t depth;
read<std::uint8_t>(is, depth);
in_size -= 1;
result.second = 525 + 1 + (depth+1)/2;
void* const out = bf(result.second);
result.first = out;
ostream os(out, result.second);
write<std::uint32_t>(os, 0);
write<std::uint32_t>(os, 0);
write<std::uint8_t> (os, hotUNKNOWN);
write<std::uint32_t>(os,
static_cast<std::uint32_t>(HashPrefix::innerNodeV2));
if (mask == 0)
Throw<std::runtime_error> (
"nodeobject codec v2: empty inner node");
std::uint16_t bit = 0x8000;
for (int i = 16; i--; bit >>= 1)
{
if (mask & bit)
{
if (in_size < 32)
Throw<std::runtime_error> (
"nodeobject codec v2: short inner node subsize: "
+ std::string("in_size = ") + std::to_string(in_size)
+ " i = " + std::to_string(i));
std::memcpy(os.data(32), is(32), 32);
in_size -= 32;
}
else
{
std::memset(os.data(32), 0, 32);
}
}
write<std::uint8_t>(os, depth);
if (in_size < (depth+1)/2)
Throw<std::runtime_error> (
"nodeobject codec v2: short inner node: "
+ std::string("size = ") + std::to_string(in_size)
+ " depth = " + std::to_string(depth));
std::memcpy(os.data((depth+1)/2), is((depth+1)/2), (depth+1)/2);
in_size -= (depth+1)/2;
if (in_size > 0)
Throw<std::runtime_error> (
"nodeobject codec v2: long inner node, in_size = "
+ std::to_string(in_size));
break;
}
case 6: // full v2 inner node
{
istream is(p, in_size);
std::uint8_t depth;
read<std::uint8_t>(is, depth);
in_size -= 1;
result.second = 525 + 1 + (depth+1)/2;
if (in_size != 16 * 32 + (depth+1)/2) // hashes and common
Throw<std::runtime_error> (
"nodeobject codec v2: short full inner node: "
+ std::string("size = ") + std::to_string(in_size)
+ " depth = " + std::to_string(depth));
void* const out = bf(result.second);
result.first = out;
ostream os(out, result.second);
write<std::uint32_t>(os, 0);
write<std::uint32_t>(os, 0);
write<std::uint8_t> (os, hotUNKNOWN);
write<std::uint32_t>(os,
static_cast<std::uint32_t>(HashPrefix::innerNodeV2));
write(os, is(512), 512);
write<std::uint8_t>(os, depth);
write(os, is((depth+1)/2), (depth+1)/2);
break;
}
default:
Throw<std::runtime_error> (
"nodeobject codec: bad type=" +
@@ -379,87 +294,6 @@ nodeobject_compress (void const* in,
}
}
// Check for inner node v2
if (526 <= in_size && in_size <= 556)
{
istream is(in, in_size);
std::uint32_t index;
std::uint32_t unused;
std::uint8_t kind;
std::uint32_t prefix;
read<std::uint32_t>(is, index);
read<std::uint32_t>(is, unused);
read<std::uint8_t> (is, kind);
read<std::uint32_t>(is, prefix);
if (prefix == HashPrefix::innerNodeV2)
{
std::size_t n = 0;
std::uint16_t mask = 0;
std::array<
std::uint8_t, 512> vh;
for (unsigned bit = 0x8000;
bit; bit >>= 1)
{
void const* const h = is(32);
if (std::memcmp(
h, zero32(), 32) == 0)
continue;
std::memcpy(
vh.data() + 32 * n, h, 32);
mask |= bit;
++n;
}
std::uint8_t depth;
read<std::uint8_t>(is, depth);
std::array<std::uint8_t, 32> common{};
for (unsigned d = 0; d < (depth+1)/2; ++d)
read<std::uint8_t>(is, common[d]);
std::pair<void const*,
std::size_t> result;
if (n < 16)
{
// 5 = v2 inner node compressed
auto const type = 5U;
auto const vs = size_varint(type);
result.second =
vs +
field<std::uint16_t>::size + // mask
n * 32 + // hashes
1 + // depth
(depth+1)/2; // common prefix
std::uint8_t* out = reinterpret_cast<
std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);
write<varint>(os, type);
write<std::uint16_t>(os, mask);
write<std::uint8_t>(os, depth);
write(os, vh.data(), n * 32);
for (unsigned d = 0; d < (depth+1)/2; ++d)
write<std::uint8_t>(os, common[d]);
return result;
}
// 6 = full v2 inner node
auto const type = 6U;
auto const vs = size_varint(type);
result.second =
vs +
n * 32 + // hashes
1 + // depth
(depth+1)/2; // common prefix
std::uint8_t* out = reinterpret_cast<
std::uint8_t*>(bf(result.second));
result.first = out;
ostream os(out, result.second);
write<varint>(os, type);
write<std::uint8_t>(os, depth);
write(os, vh.data(), n * 32);
for (unsigned d = 0; d < (depth+1)/2; ++d)
write<std::uint8_t>(os, common[d]);
return result;
}
}
std::array<std::uint8_t, varint_traits<
std::size_t>::max> vi;

View File

@@ -56,7 +56,6 @@ class FeatureCollections
"FeeEscalation",
"OwnerPaysFee",
"CompareFlowV1V2",
"SHAMapV2",
"PayChan",
"Flow",
"CompareTakerFlowCross",
@@ -344,7 +343,6 @@ extern uint256 const featureTickets;
extern uint256 const featureTrustSetAuth;
extern uint256 const featureOwnerPaysFee;
extern uint256 const featureCompareFlowV1V2;
extern uint256 const featureSHAMapV2;
extern uint256 const featurePayChan;
extern uint256 const featureFlow;
extern uint256 const featureCompareTakerFlowCross;

View File

@@ -79,9 +79,6 @@ public:
/** inner node in V1 tree */
static HashPrefix const innerNode;
/** inner node in V2 tree */
static HashPrefix const innerNodeV2;
/** ledger master data for signing */
static HashPrefix const ledgerMaster;

View File

@@ -84,7 +84,6 @@ detail::supportedAmendments ()
// uncommented at that time).
static std::vector<std::string> const supported
{
// "SHAMapV2",
"MultiSign",
// "Tickets",
"TrustSetAuth",
@@ -148,7 +147,6 @@ uint256 const featureTickets = *getRegisteredFeature("Tickets");
uint256 const featureTrustSetAuth = *getRegisteredFeature("TrustSetAuth");
uint256 const featureOwnerPaysFee = *getRegisteredFeature("OwnerPaysFee");
uint256 const featureCompareFlowV1V2 = *getRegisteredFeature("CompareFlowV1V2");
uint256 const featureSHAMapV2 = *getRegisteredFeature("SHAMapV2");
uint256 const featurePayChan = *getRegisteredFeature("PayChan");
uint256 const featureFlow = *getRegisteredFeature("Flow");
uint256 const featureCompareTakerFlowCross = *getRegisteredFeature("CompareTakerFlowCross");

View File

@@ -28,7 +28,6 @@ HashPrefix const HashPrefix::transactionID ('T', 'X', 'N');
HashPrefix const HashPrefix::txNode ('S', 'N', 'D');
HashPrefix const HashPrefix::leafNode ('M', 'L', 'N');
HashPrefix const HashPrefix::innerNode ('M', 'I', 'N');
HashPrefix const HashPrefix::innerNodeV2 ('I', 'N', 'R');
HashPrefix const HashPrefix::ledgerMaster ('L', 'W', 'R');
HashPrefix const HashPrefix::txSign ('S', 'T', 'X');
HashPrefix const HashPrefix::txMultiSign ('S', 'M', 'T');

View File

@@ -90,18 +90,6 @@ private:
bool full_ = false; // Map is believed complete in database
public:
class version
{
int v_;
public:
explicit version(int v) : v_(v) {}
friend bool operator==(version const& x, version const& y)
{return x.v_ == y.v_;}
friend bool operator!=(version const& x, version const& y)
{return !(x == y);}
};
using DeltaItem = std::pair<std::shared_ptr<SHAMapItem const>,
std::shared_ptr<SHAMapItem const>>;
using Delta = std::map<uint256, DeltaItem>;
@@ -113,15 +101,13 @@ public:
// build new map
SHAMap (
SHAMapType t,
Family& f,
version v
Family& f
);
SHAMap (
SHAMapType t,
uint256 const& hash,
Family& f,
version v);
Family& f);
Family const&
family() const
@@ -259,10 +245,6 @@ public:
std::function<void (SHAMapHash const&, const Blob&)>) const;
void setUnbacked ();
bool is_v2() const;
version get_version() const;
std::shared_ptr<SHAMap> make_v1() const;
std::shared_ptr<SHAMap> make_v2() const;
int unshare ();
void dump (bool withHashes = false) const;
@@ -350,7 +332,6 @@ private:
std::shared_ptr<SHAMapItem const> const& otherMapItem,
bool isFirstMap, Delta & differences, int & maxCount) const;
int walkSubTree (bool doWrite, NodeObjectType t, std::uint32_t seq);
bool isInconsistentNode(std::shared_ptr<SHAMapAbstractNode> const& node) const;
// Structure to track information about call to
// getMissingNodes while it's in progress
@@ -464,14 +445,6 @@ SHAMap::setUnbacked ()
backed_ = false;
}
inline
bool
SHAMap::is_v2() const
{
assert (root_);
return std::dynamic_pointer_cast<SHAMapInnerNodeV2>(root_) != nullptr;
}
//------------------------------------------------------------------------------
class SHAMap::const_iterator

View File

@@ -129,7 +129,7 @@ public:
virtual std::string getString (SHAMapNodeID const&) const;
virtual std::shared_ptr<SHAMapAbstractNode> clone(std::uint32_t seq) const = 0;
virtual uint256 const& key() const = 0;
virtual void invariants(bool is_v2, bool is_root = false) const = 0;
virtual void invariants(bool is_root = false) const = 0;
static std::shared_ptr<SHAMapAbstractNode>
make(Slice const& rawNode, std::uint32_t seq, SHANodeFormat format,
@@ -137,8 +137,6 @@ public:
SHAMapNodeID const& id = SHAMapNodeID{});
};
class SHAMapInnerNodeV2;
class SHAMapInnerNode
: public SHAMapAbstractNode
{
@@ -173,44 +171,7 @@ public:
void addRaw (Serializer&, SHANodeFormat format) const override;
std::string getString (SHAMapNodeID const&) const override;
uint256 const& key() const override;
void invariants(bool is_v2, bool is_root = false) const override;
friend std::shared_ptr<SHAMapAbstractNode>
SHAMapAbstractNode::make(Slice const& rawNode, std::uint32_t seq,
SHANodeFormat format, SHAMapHash const& hash, bool hashValid,
beast::Journal j, SHAMapNodeID const& id);
friend class SHAMapInnerNodeV2;
};
class SHAMapTreeNode;
// SHAMapInnerNodeV2 is a "version 2" inner node. It always has at least two children
// unless it is the root node and there is only one leaf in the tree, in which case
// that leaf is a direct child of the root.
class SHAMapInnerNodeV2
: public SHAMapInnerNode
{
uint256 common_ = {};
int depth_ = 64;
public:
explicit SHAMapInnerNodeV2(std::uint32_t seq);
SHAMapInnerNodeV2(std::uint32_t seq, int depth);
std::shared_ptr<SHAMapAbstractNode> clone(std::uint32_t seq) const override;
uint256 const& common() const;
int depth() const;
bool has_common_prefix(uint256 const& key) const;
int get_common_prefix(uint256 const& key) const;
void set_common(int depth, uint256 const& key);
bool updateHash () override;
void addRaw(Serializer& s, SHANodeFormat format) const override;
uint256 const& key() const override;
void setChildren(std::shared_ptr<SHAMapTreeNode> const& child1,
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_root = false) const override;
friend std::shared_ptr<SHAMapAbstractNode>
SHAMapAbstractNode::make(Slice const& rawNode, std::uint32_t seq,
@@ -237,7 +198,7 @@ public:
void addRaw (Serializer&, SHANodeFormat format) const override;
uint256 const& key() const override;
void invariants(bool is_v2, bool is_root = false) const override;
void invariants(bool is_root = false) const override;
public: // public only to SHAMap
@@ -366,35 +327,6 @@ SHAMapInnerNode::setFullBelowGen (std::uint32_t gen)
mFullBelowGen = gen;
}
// SHAMapInnerNodeV2
inline
SHAMapInnerNodeV2::SHAMapInnerNodeV2(std::uint32_t seq)
: SHAMapInnerNode(seq)
{
}
inline
SHAMapInnerNodeV2::SHAMapInnerNodeV2(std::uint32_t seq, int depth)
: SHAMapInnerNode(seq)
, depth_(depth)
{
}
inline
uint256 const&
SHAMapInnerNodeV2::common() const
{
return common_;
}
inline
int
SHAMapInnerNodeV2::depth() const
{
return depth_;
}
// SHAMapTreeNode
inline

View File

@@ -24,35 +24,27 @@ namespace ripple {
SHAMap::SHAMap (
SHAMapType t,
Family& f,
version v)
Family& f)
: f_ (f)
, journal_(f.journal())
, seq_ (1)
, state_ (SHAMapState::Modifying)
, type_ (t)
{
if (v == version{2})
root_ = std::make_shared<SHAMapInnerNodeV2>(seq_, 0);
else
root_ = std::make_shared<SHAMapInnerNode>(seq_);
root_ = std::make_shared<SHAMapInnerNode>(seq_);
}
SHAMap::SHAMap (
SHAMapType t,
uint256 const& hash,
Family& f,
version v)
Family& f)
: f_ (f)
, journal_(f.journal())
, seq_ (1)
, state_ (SHAMapState::Synching)
, type_ (t)
{
if (v == version{2})
root_ = std::make_shared<SHAMapInnerNodeV2>(seq_, 0);
else
root_ = std::make_shared<SHAMapInnerNode>(seq_);
root_ = std::make_shared<SHAMapInnerNode>(seq_);
}
SHAMap::~SHAMap ()
@@ -63,7 +55,7 @@ SHAMap::~SHAMap ()
std::shared_ptr<SHAMap>
SHAMap::snapShot (bool isMutable) const
{
auto ret = std::make_shared<SHAMap> (type_, f_, get_version());
auto ret = std::make_shared<SHAMap> (type_, f_);
SHAMap& newMap = *ret;
if (!isMutable)
@@ -84,72 +76,6 @@ SHAMap::snapShot (bool isMutable) const
return ret;
}
std::shared_ptr<SHAMap>
SHAMap::make_v2() const
{
assert(!is_v2());
auto ret = std::make_shared<SHAMap>(type_, f_, version{2});
ret->seq_ = seq_ + 1;
SharedPtrNodeStack stack;
for (auto leaf = peekFirstItem(stack); leaf != nullptr;
leaf = peekNextItem(leaf->peekItem()->key(), stack))
{
auto node_type = leaf->getType();
ret->addGiveItem(leaf->peekItem(),
node_type != SHAMapTreeNode::tnACCOUNT_STATE,
node_type == SHAMapTreeNode::tnTRANSACTION_MD);
}
NodeObjectType t;
switch (type_)
{
case SHAMapType::TRANSACTION:
t = hotTRANSACTION_NODE;
break;
case SHAMapType::STATE:
t = hotACCOUNT_NODE;
break;
default:
t = hotUNKNOWN;
break;
}
ret->flushDirty(t, ret->seq_);
ret->unshare();
return ret;
}
std::shared_ptr<SHAMap>
SHAMap::make_v1() const
{
assert(is_v2());
auto ret = std::make_shared<SHAMap>(type_, f_, version{1});
ret->seq_ = seq_ + 1;
SharedPtrNodeStack stack;
for (auto leaf = peekFirstItem(stack); leaf != nullptr;
leaf = peekNextItem(leaf->peekItem()->key(), stack))
{
auto node_type = leaf->getType();
ret->addGiveItem(leaf->peekItem(),
node_type != SHAMapTreeNode::tnACCOUNT_STATE,
node_type == SHAMapTreeNode::tnTRANSACTION_MD);
}
NodeObjectType t;
switch (type_)
{
case SHAMapType::TRANSACTION:
t = hotTRANSACTION_NODE;
break;
case SHAMapType::STATE:
t = hotACCOUNT_NODE;
break;
default:
t = hotUNKNOWN;
break;
}
ret->flushDirty(t, ret->seq_);
ret->unshare();
return ret;
}
void
SHAMap::dirtyUp (SharedPtrNodeStack& stack,
uint256 const& target, std::shared_ptr<SHAMapAbstractNode> child)
@@ -185,46 +111,19 @@ SHAMap::walkTowardsKey(uint256 const& id, SharedPtrNodeStack* stack) const
assert(stack == nullptr || stack->empty());
auto inNode = root_;
SHAMapNodeID nodeID;
auto const isv2 = is_v2();
while (inNode->isInner())
{
if (stack != nullptr)
stack->push({inNode, nodeID});
if (isv2)
{
auto n = std::static_pointer_cast<SHAMapInnerNodeV2>(inNode);
if (!n->has_common_prefix(id))
return nullptr;
}
auto const inner = std::static_pointer_cast<SHAMapInnerNode>(inNode);
auto const branch = nodeID.selectBranch (id);
if (inner->isEmptyBranch (branch))
return nullptr;
inNode = descendThrow (inner, branch);
if (isv2)
{
if (inNode->isInner())
{
auto n = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(inNode);
if (n == nullptr)
{
assert (false);
return nullptr;
}
nodeID = SHAMapNodeID{n->depth(), n->common()};
}
else
{
nodeID = SHAMapNodeID{64, inNode->key()};
}
}
else
{
nodeID = nodeID.getChildNodeID (branch);
}
nodeID = nodeID.getChildNodeID (branch);
}
if (stack != nullptr)
@@ -254,26 +153,6 @@ SHAMap::fetchNodeFromDB (SHAMapHash const& hash) const
{
node = SHAMapAbstractNode::make(makeSlice(obj->getData()),
0, snfPREFIX, hash, true, f_.journal());
if (node && node->isInner())
{
bool isv2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) != nullptr;
if (isv2 != is_v2())
{
auto root = std::dynamic_pointer_cast<SHAMapInnerNode>(root_);
assert(root);
assert(root->isEmpty());
if (isv2)
{
auto temp = make_v2();
swap(temp->root_, const_cast<std::shared_ptr<SHAMapAbstractNode>&>(root_));
}
else
{
auto temp = make_v1();
swap(temp->root_, const_cast<std::shared_ptr<SHAMapAbstractNode>&>(root_));
}
}
}
if (node)
canonicalize (hash, node);
}
@@ -390,7 +269,7 @@ SHAMapAbstractNode* SHAMap::descend (SHAMapInnerNode* parent, int branch) const
return ret;
std::shared_ptr<SHAMapAbstractNode> node = fetchNodeNT (parent->getChildHash (branch));
if (!node || isInconsistentNode(node))
if (!node)
return nullptr;
node = parent->canonicalizeChild (branch, std::move(node));
@@ -405,7 +284,7 @@ SHAMap::descend (std::shared_ptr<SHAMapInnerNode> const& parent, int branch) con
return node;
node = fetchNode (parent->getChildHash (branch));
if (!node || isInconsistentNode(node))
if (!node)
return nullptr;
node = parent->canonicalizeChild (branch, std::move(node));
@@ -443,19 +322,6 @@ SHAMap::descend (SHAMapInnerNode * parent, SHAMapNodeID const& parentID,
childNode = parent->canonicalizeChild (branch, std::move(childNode));
child = childNode.get ();
}
if (child && isInconsistentNode(childNode))
child = nullptr;
}
if (child && is_v2())
{
if (child->isInner())
{
auto n = static_cast<SHAMapInnerNodeV2*>(child);
return std::make_pair(child, SHAMapNodeID{n->depth(), n->key()});
}
return std::make_pair(child, SHAMapNodeID{64, child->key()});
}
return std::make_pair (child, parentID.getChildNodeID (branch));
@@ -497,8 +363,6 @@ SHAMap::descendAsync (SHAMapInnerNode* parent, int branch,
}
}
if (ptr && isInconsistentNode(ptr))
ptr = nullptr;
if (ptr)
ptr = parent->canonicalizeChild (branch, std::move(ptr));
@@ -539,18 +403,7 @@ SHAMap::firstBelow(std::shared_ptr<SHAMapAbstractNode> node,
if (stack.empty())
stack.push({inner, SHAMapNodeID{}});
else
{
if (is_v2())
{
auto inner2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(inner);
assert(inner2 != nullptr);
stack.push({inner2, {inner2->depth(), inner2->common()}});
}
else
{
stack.push({inner, stack.top().second.getChildNodeID(branch)});
}
}
stack.push({inner, stack.top().second.getChildNodeID(branch)});
for (int i = 0; i < 16;)
{
if (!inner->isEmptyBranch(i))
@@ -564,15 +417,7 @@ SHAMap::firstBelow(std::shared_ptr<SHAMapAbstractNode> node,
return n.get();
}
inner = std::static_pointer_cast<SHAMapInnerNode>(node);
if (is_v2())
{
auto inner2 = std::static_pointer_cast<SHAMapInnerNodeV2>(inner);
stack.push({inner2, {inner2->depth(), inner2->common()}});
}
else
{
stack.push({inner, stack.top().second.getChildNodeID(branch)});
}
stack.push({inner, stack.top().second.getChildNodeID(branch)});
i = 0; // scan all 16 branches of this new node
}
else
@@ -708,7 +553,6 @@ SHAMap::upper_bound(uint256 const& id) const
// item need not be in tree
SharedPtrNodeStack stack;
walkTowardsKey(id, &stack);
auto const isv2 = is_v2();
while (!stack.empty())
{
auto [node, nodeID] = stack.top();
@@ -721,22 +565,7 @@ SHAMap::upper_bound(uint256 const& id) const
else
{
auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
int branch;
if (isv2)
{
auto n = std::static_pointer_cast<SHAMapInnerNodeV2>(inner);
if (n->has_common_prefix(id))
branch = nodeID.selectBranch(id) + 1;
else if (id < n->common())
branch = 0;
else
branch = 16;
}
else
{
branch = nodeID.selectBranch(id) + 1;
}
for (; branch < 16; ++branch)
for (auto branch = nodeID.selectBranch(id) + 1; branch < 16; ++branch)
{
if (!inner->isEmptyBranch(branch))
{
@@ -797,61 +626,38 @@ bool SHAMap::delItem (uint256 const& id)
{
// we may have made this a node with 1 or 0 children
// And, if so, we need to remove this branch
int bc = node->getBranchCount();
if (is_v2())
const int bc = node->getBranchCount();
if (bc == 0)
{
assert(bc != 0);
if (bc == 1)
// no children below this branch
prevNode.reset ();
}
else if (bc == 1)
{
// If there's only one item, pull up on the thread
auto item = onlyBelow (node.get ());
if (item)
{
for (int i = 0; i < 16; ++i)
{
if (!node->isEmptyBranch (i))
{
prevNode = descendThrow(node, i);
node->setChild (i, nullptr);
break;
}
}
prevNode = std::make_shared<SHAMapTreeNode>(item, type, node->getSeq());
}
else // bc >= 2
else
{
// This node is now the end of the branch
prevNode = std::move(node);
prevNode = std::move (node);
}
}
else
{
if (bc == 0)
{
// no children below this branch
prevNode.reset ();
}
else if (bc == 1)
{
// If there's only one item, pull up on the thread
auto item = onlyBelow (node.get ());
if (item)
{
for (int i = 0; i < 16; ++i)
{
if (!node->isEmptyBranch (i))
{
node->setChild (i, nullptr);
break;
}
}
prevNode = std::make_shared<SHAMapTreeNode>(item, type, node->getSeq());
}
else
{
prevNode = std::move (node);
}
}
else
{
// This node is now the end of the branch
prevNode = std::move (node);
}
// This node is now the end of the branch
prevNode = std::move (node);
}
}
}
@@ -859,20 +665,6 @@ bool SHAMap::delItem (uint256 const& id)
return true;
}
static
uint256
prefix(unsigned depth, uint256 const& key)
{
uint256 r{};
auto x = r.begin();
auto y = key.begin();
for (auto i = 0; i < depth/2; ++i, ++x, ++y)
*x = *y;
if (depth & 1)
*x = *y & 0xF0;
return r;
}
bool
SHAMap::addGiveItem (std::shared_ptr<SHAMapItem const> const& item,
bool isTransaction, bool hasMeta)
@@ -900,97 +692,48 @@ SHAMap::addGiveItem (std::shared_ptr<SHAMapItem const> const& item,
return false;
}
node = unshareNode(std::move(node), nodeID);
if (is_v2())
if (node->isInner ())
{
if (node->isInner())
{
auto inner = std::static_pointer_cast<SHAMapInnerNodeV2>(node);
if (inner->has_common_prefix(tag))
{
int branch = nodeID.selectBranch(tag);
assert(inner->isEmptyBranch(branch));
auto newNode = std::make_shared<SHAMapTreeNode>(item, type, seq_);
inner->setChild(branch, newNode);
}
else
{
assert(!stack.empty());
auto parent = unshareNode(
std::static_pointer_cast<SHAMapInnerNodeV2>(stack.top().first),
stack.top().second);
stack.top().first = parent;
auto parent_depth = parent->depth();
auto depth = inner->get_common_prefix(tag);
auto new_inner = std::make_shared<SHAMapInnerNodeV2>(seq_);
nodeID = SHAMapNodeID{depth, prefix(depth, inner->common())};
new_inner->setChild(nodeID.selectBranch(inner->common()), inner);
nodeID = SHAMapNodeID{depth, prefix(depth, tag)};
new_inner->setChild(nodeID.selectBranch(tag),
std::make_shared<SHAMapTreeNode>(item, type, seq_));
new_inner->set_common(depth, prefix(depth, tag));
nodeID = SHAMapNodeID{parent_depth, prefix(parent_depth, tag)};
parent->setChild(nodeID.selectBranch(tag), new_inner);
node = new_inner;
}
}
else
{
auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
auto inner = std::make_shared<SHAMapInnerNodeV2>(seq_);
inner->setChildren(leaf, std::make_shared<SHAMapTreeNode>(item, type, seq_));
assert(!stack.empty());
auto parent = unshareNode(
std::static_pointer_cast<SHAMapInnerNodeV2>(stack.top().first),
stack.top().second);
stack.top().first = parent;
node = inner;
}
// easy case, we end on an inner node
auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
int branch = nodeID.selectBranch (tag);
assert (inner->isEmptyBranch (branch));
auto newNode = std::make_shared<SHAMapTreeNode> (item, type, seq_);
inner->setChild (branch, newNode);
}
else // !is_v2()
else
{
if (node->isInner ())
// this is a leaf node that has to be made an inner node holding two items
auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
std::shared_ptr<SHAMapItem const> otherItem = leaf->peekItem ();
assert (otherItem && (tag != otherItem->key()));
node = std::make_shared<SHAMapInnerNode>(node->getSeq());
int b1, b2;
while ((b1 = nodeID.selectBranch (tag)) ==
(b2 = nodeID.selectBranch (otherItem->key())))
{
// easy case, we end on an inner node
auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
int branch = nodeID.selectBranch (tag);
assert (inner->isEmptyBranch (branch));
auto newNode = std::make_shared<SHAMapTreeNode> (item, type, seq_);
inner->setChild (branch, newNode);
stack.push ({node, nodeID});
// we need a new inner node, since both go on same branch at this level
nodeID = nodeID.getChildNodeID (b1);
node = std::make_shared<SHAMapInnerNode> (seq_);
}
else
{
// this is a leaf node that has to be made an inner node holding two items
auto leaf = std::static_pointer_cast<SHAMapTreeNode>(node);
std::shared_ptr<SHAMapItem const> otherItem = leaf->peekItem ();
assert (otherItem && (tag != otherItem->key()));
node = std::make_shared<SHAMapInnerNode>(node->getSeq());
// we can add the two leaf nodes here
assert (node->isInner ());
int b1, b2;
std::shared_ptr<SHAMapTreeNode> newNode =
std::make_shared<SHAMapTreeNode> (item, type, seq_);
assert (newNode->isValid () && newNode->isLeaf ());
auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
inner->setChild (b1, newNode);
while ((b1 = nodeID.selectBranch (tag)) ==
(b2 = nodeID.selectBranch (otherItem->key())))
{
stack.push ({node, nodeID});
// we need a new inner node, since both go on same branch at this level
nodeID = nodeID.getChildNodeID (b1);
node = std::make_shared<SHAMapInnerNode> (seq_);
}
// we can add the two leaf nodes here
assert (node->isInner ());
std::shared_ptr<SHAMapTreeNode> newNode =
std::make_shared<SHAMapTreeNode> (item, type, seq_);
assert (newNode->isValid () && newNode->isLeaf ());
auto inner = std::static_pointer_cast<SHAMapInnerNode>(node);
inner->setChild (b1, newNode);
newNode = std::make_shared<SHAMapTreeNode> (otherItem, type, seq_);
assert (newNode->isValid () && newNode->isLeaf ());
inner->setChild (b2, newNode);
}
newNode = std::make_shared<SHAMapTreeNode> (otherItem, type, seq_);
assert (newNode->isValid () && newNode->isLeaf ());
inner->setChild (b2, newNode);
}
dirtyUp (stack, tag, node);
@@ -1175,10 +918,7 @@ SHAMap::walkSubTree (bool doWrite, NodeObjectType t, std::uint32_t seq)
if (node->isEmpty ())
{ // replace empty root with a new empty root
if (is_v2())
root_ = std::make_shared<SHAMapInnerNodeV2>(0, 0);
else
root_ = std::make_shared<SHAMapInnerNode>(0);
root_ = std::make_shared<SHAMapInnerNode>(0);
return 1;
}
@@ -1335,14 +1075,6 @@ SHAMap::canonicalize(SHAMapHash const& hash, std::shared_ptr<SHAMapAbstractNode>
f_.treecache().canonicalize (hash.as_uint256(), node);
}
SHAMap::version
SHAMap::get_version() const
{
if (is_v2())
return version{2};
return version{1};
}
void
SHAMap::invariants() const
{
@@ -1354,24 +1086,7 @@ SHAMap::invariants() const
for (auto leaf = peekFirstItem(stack); leaf != nullptr;
leaf = peekNextItem(leaf->peekItem()->key(), stack))
;
node->invariants(is_v2(), true);
}
bool
SHAMap::isInconsistentNode(std::shared_ptr<SHAMapAbstractNode> const& node) const
{
assert(root_);
assert(node);
if (std::dynamic_pointer_cast<SHAMapTreeNode>(node) != nullptr)
return false;
bool is_node_v2 = std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node) != nullptr;
assert (! is_node_v2 || (std::dynamic_pointer_cast<SHAMapInnerNodeV2>(node)->depth() != 0));
if (is_v2() == is_node_v2)
return false;
state_ = SHAMapState::Invalid;
return true;
node->invariants(true);
}
} // ripple

View File

@@ -220,10 +220,7 @@ void SHAMap::gmn_ProcessNodes (MissingNodes& mn, MissingNodes::StackEntry& se)
// Switch to processing the child node
node = static_cast<SHAMapInnerNode*>(d);
if (auto v2Node = dynamic_cast<SHAMapInnerNodeV2*>(node))
nodeID = SHAMapNodeID{v2Node->depth(), v2Node->key()};
else
nodeID = childID;
nodeID = childID;
firstChild = rand_int(255);
currentChild = 0;
fullBelow = true;
@@ -447,16 +444,10 @@ bool SHAMap::getNodeFat (SHAMapNodeID wanted,
return false;
node = descendThrow(inner, branch);
if (auto v2Node = dynamic_cast<SHAMapInnerNodeV2*>(node))
nodeID = SHAMapNodeID{v2Node->depth(), v2Node->key()};
else
nodeID = nodeID.getChildNodeID (branch);
nodeID = nodeID.getChildNodeID (branch);
}
if (node == nullptr ||
(dynamic_cast<SHAMapInnerNodeV2*>(node) != nullptr &&
!wanted.has_common_prefix(nodeID)) ||
(dynamic_cast<SHAMapInnerNodeV2*>(node) == nullptr && wanted != nodeID))
if (node == nullptr || wanted != nodeID)
{
JLOG(journal_.warn())
<< "peer requested node that is not in the map:\n"
@@ -497,12 +488,8 @@ bool SHAMap::getNodeFat (SHAMapNodeID wanted,
{
if (! inner->isEmptyBranch (i))
{
auto childNode = descendThrow (inner, i);
SHAMapNodeID childID;
if (auto v2Node = dynamic_cast<SHAMapInnerNodeV2*>(childNode))
childID = SHAMapNodeID{v2Node->depth(), v2Node->key()};
else
childID = nodeID.getChildNodeID (i);
auto const childNode = descendThrow (inner, i);
SHAMapNodeID const childID = nodeID.getChildNodeID (i);
if (childNode->isInner () &&
((depth > 1) || (bc == 1)))
@@ -625,14 +612,7 @@ SHAMap::addKnownNode (const SHAMapNodeID& node, Slice const& rawNode,
return SHAMapAddNode::useful ();
}
if (newNode && isInconsistentNode(newNode))
{
state_ = SHAMapState::Invalid;
return SHAMapAddNode::useful();
}
if ((std::dynamic_pointer_cast<SHAMapInnerNodeV2>(newNode) && !iNodeID.has_common_prefix(node)) ||
(!std::dynamic_pointer_cast<SHAMapInnerNodeV2>(newNode) && iNodeID != node))
if (iNodeID != node)
{
// Either this node is broken or we didn't request it (yet)
JLOG(journal_.warn()) << "unable to hook node " << node;
@@ -796,11 +776,6 @@ There's no point in including the leaves of transaction trees.
void SHAMap::getFetchPack (SHAMap const* have, bool includeLeaves, int max,
std::function<void (SHAMapHash const&, const Blob&)> func) const
{
if (have != nullptr && have->is_v2() != is_v2())
{
JLOG(journal_.info()) << "Can not get fetch pack when versions are different.";
return;
}
visitDifferences (have,
[includeLeaves, &max, &func] (SHAMapAbstractNode& smn) -> bool
{

View File

@@ -45,31 +45,7 @@ SHAMapInnerNode::clone(std::uint32_t seq) const
p->mHashes = mHashes;
std::lock_guard lock(childLock);
for (int i = 0; i < 16; ++i)
{
p->mChildren[i] = mChildren[i];
assert(std::dynamic_pointer_cast<SHAMapInnerNodeV2>(p->mChildren[i]) == nullptr);
}
return std::move(p);
}
std::shared_ptr<SHAMapAbstractNode>
SHAMapInnerNodeV2::clone(std::uint32_t seq) const
{
auto p = std::make_shared<SHAMapInnerNodeV2>(seq);
p->mHash = mHash;
p->mIsBranch = mIsBranch;
p->mFullBelowGen = mFullBelowGen;
p->mHashes = mHashes;
p->common_ = common_;
p->depth_ = depth_;
std::lock_guard lock(childLock);
for (int i = 0; i < 16; ++i)
{
p->mChildren[i] = mChildren[i];
if (p->mChildren[i] != nullptr)
assert(std::dynamic_pointer_cast<SHAMapInnerNodeV2>(p->mChildren[i]) != nullptr ||
std::dynamic_pointer_cast<SHAMapTreeNode>(p->mChildren[i]) != nullptr);
}
return std::move(p);
}
@@ -199,49 +175,6 @@ SHAMapAbstractNode::make(Slice const& rawNode, std::uint32_t seq, SHANodeFormat
return std::make_shared<SHAMapTreeNode>(item, tnTRANSACTION_MD, seq, hash);
return std::make_shared<SHAMapTreeNode>(item, tnTRANSACTION_MD, seq);
}
else if (type == 5)
{
// full v2 inner
if (len != 512)
Throw<std::runtime_error> ("invalid FI node");
auto ret = std::make_shared<SHAMapInnerNodeV2>(seq);
for (int i = 0; i < 16; ++i)
{
s.get256 (ret->mHashes[i].as_uint256(), i * 32);
if (ret->mHashes[i].isNonZero ())
ret->mIsBranch |= (1 << i);
}
ret->set_common(id.getDepth(), id.getNodeID());
if (hashValid)
ret->mHash = hash;
else
ret->updateHash();
return ret;
}
else if (type == 6)
{
auto ret = std::make_shared<SHAMapInnerNodeV2>(seq);
// compressed v2 inner
for (int i = 0; i < (len / 33); ++i)
{
int pos;
if (! s.get8 (pos, 32 + (i * 33)))
Throw<std::runtime_error> ("short CI node");
if ((pos < 0) || (pos >= 16))
Throw<std::runtime_error> ("invalid CI node");
s.get256 (ret->mHashes[pos].as_uint256(), i * 33);
if (ret->mHashes[pos].isNonZero ())
ret->mIsBranch |= (1 << pos);
}
ret->set_common(id.getDepth(), id.getNodeID());
if (hashValid)
ret->mHash = hash;
else
ret->updateHash();
return ret;
}
}
else if (format == snfPREFIX)
@@ -290,19 +223,14 @@ SHAMapAbstractNode::make(Slice const& rawNode, std::uint32_t seq, SHANodeFormat
return std::make_shared<SHAMapTreeNode>(item, tnACCOUNT_STATE, seq, hash);
return std::make_shared<SHAMapTreeNode>(item, tnACCOUNT_STATE, seq);
}
else if ((prefix == HashPrefix::innerNode) || (prefix == HashPrefix::innerNodeV2))
else if (prefix == HashPrefix::innerNode)
{
auto len = s.getLength();
bool isV2 = (prefix == HashPrefix::innerNodeV2);
if ((len < 512) || (!isV2 && (len != 512)) || (isV2 && (len == 512)))
if (len != 512)
Throw<std::runtime_error> ("invalid PIN node");
std::shared_ptr<SHAMapInnerNode> ret;
if (isV2)
ret = std::make_shared<SHAMapInnerNodeV2>(seq);
else
ret = std::make_shared<SHAMapInnerNode>(seq);
auto ret = std::make_shared<SHAMapInnerNode>(seq);
for (int i = 0; i < 16; ++i)
{
@@ -312,21 +240,6 @@ SHAMapAbstractNode::make(Slice const& rawNode, std::uint32_t seq, SHANodeFormat
ret->mIsBranch |= (1 << i);
}
if (isV2)
{
auto temp = std::static_pointer_cast<SHAMapInnerNodeV2>(ret);
s.get8(temp->depth_, 512);
auto n = (temp->depth_ + 1) / 2;
if (len != 512 + 1 + n)
Throw<std::runtime_error> ("invalid PIN node");
auto x = temp->common_.begin();
for (auto i = 0; i < n; ++i, ++x)
{
int byte;
s.get8(byte, 512+1+i);
*x = byte;
}
}
if (hashValid)
ret->mHash = hash;
else
@@ -470,52 +383,6 @@ SHAMapInnerNode::addRaw(Serializer& s, SHANodeFormat format) const
assert (false);
}
void
SHAMapInnerNodeV2::addRaw(Serializer& s, SHANodeFormat format) const
{
if (format == snfPREFIX)
{
assert(depth_ <= 64);
s.add32 (HashPrefix::innerNodeV2);
for (int i = 0 ; i < 16; ++i)
s.add256 (mHashes[i].as_uint256());
s.add8(depth_);
auto x = common_.begin();
for (auto i = 0; i < (depth_+1)/2; ++i, ++x)
s.add8(*x);
}
else
{
SHAMapInnerNode::addRaw(s, format);
if (format == snfWIRE)
{
auto& data = s.modData();
data.back() += 3;
}
}
}
bool
SHAMapInnerNodeV2::updateHash()
{
uint256 nh;
if (mIsBranch != 0)
{
Serializer s(580);
addRaw (s, snfPREFIX);
nh = s.getSHA512Half();
}
if (nh == mHash.as_uint256())
return false;
mHash = SHAMapHash{nh};
return true;
}
void
SHAMapTreeNode::addRaw(Serializer& s, SHANodeFormat format) const
{
@@ -717,118 +584,11 @@ SHAMapInnerNode::canonicalizeChild(int branch, std::shared_ptr<SHAMapAbstractNod
else
{
// 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::lock_guard 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;
}
return node;
}
bool
SHAMapInnerNodeV2::has_common_prefix(uint256 const& key) const
{
auto x = common_.begin();
auto y = key.begin();
for (unsigned i = 0; i < depth_/2; ++i, ++x, ++y)
{
if (*x != *y)
return false;
}
if (depth_ & 1)
{
auto i = depth_/2;
return (*(common_.begin() + i) & 0xF0) == (*(key.begin() + i) & 0xF0);
}
return true;
}
int
SHAMapInnerNodeV2::get_common_prefix(uint256 const& key) const
{
auto x = common_.begin();
auto y = key.begin();
auto r = 0;
for (unsigned i = 0; i < depth_/2; ++i, ++x, ++y, r += 2)
{
if (*x != *y)
{
if ((*x & 0xF0) == (*y & 0xF0))
++r;
return r;
}
}
if (depth_ & 1)
{
auto i = depth_/2;
if ((*(common_.begin() + i) & 0xF0) == (*(key.begin() + i) & 0xF0))
++r;
}
return r;
}
void
SHAMapInnerNodeV2::setChildren(std::shared_ptr<SHAMapTreeNode> const& child1,
std::shared_ptr<SHAMapTreeNode> const& child2)
{
assert(child1->peekItem()->key() != child2->peekItem()->key());
auto k1 = child1->peekItem()->key().begin();
auto k2 = child2->peekItem()->key().begin();
auto k = common_.begin();
for (depth_ = 0; *k1 == *k2; ++depth_, ++k1, ++k2, ++k)
*k = *k1;
unsigned b1;
unsigned b2;
if ((*k1 & 0xF0) == (*k2 & 0xF0))
{
*k = *k1 & 0xF0;
b1 = *k1 & 0x0F;
b2 = *k2 & 0x0F;
depth_ = 2*depth_ + 1;
}
else
{
b1 = *k1 >> 4;
b2 = *k2 >> 4;
depth_ = 2*depth_;
}
mChildren[b1] = child1;
mIsBranch |= 1 << b1;
mChildren[b2] = child2;
mIsBranch |= 1 << b2;
}
void
SHAMapInnerNodeV2::set_common(int depth, uint256 const& common)
{
depth_ = depth;
common_ = common;
}
uint256 const&
SHAMapInnerNode::key() const
{
@@ -837,12 +597,6 @@ SHAMapInnerNode::key() const
return x;
}
uint256 const&
SHAMapInnerNodeV2::key() const
{
return common_;
}
uint256 const&
SHAMapTreeNode::key() const
{
@@ -850,9 +604,8 @@ SHAMapTreeNode::key() const
}
void
SHAMapInnerNode::invariants(bool is_v2, bool is_root) const
SHAMapInnerNode::invariants(bool is_root) const
{
assert(!is_v2);
assert(mType == tnINNER);
unsigned count = 0;
for (int i = 0; i < 16; ++i)
@@ -861,7 +614,7 @@ SHAMapInnerNode::invariants(bool is_v2, bool is_root) const
{
assert((mIsBranch & (1 << i)) != 0);
if (mChildren[i] != nullptr)
mChildren[i]->invariants(is_v2);
mChildren[i]->invariants();
++count;
}
else
@@ -878,54 +631,7 @@ SHAMapInnerNode::invariants(bool is_v2, bool is_root) const
}
void
SHAMapInnerNodeV2::invariants(bool is_v2, bool is_root) const
{
assert(is_v2);
assert(mType == tnINNER);
unsigned count = 0;
for (int i = 0; i < 16; ++i)
{
if (mHashes[i].isNonZero())
{
assert((mIsBranch & (1 << i)) != 0);
if (mChildren[i] != nullptr)
{
assert(mHashes[i] == mChildren[i]->getNodeHash());
#ifndef NDEBUG
auto const& childID = mChildren[i]->key();
// Make sure this child it attached to the correct branch
SHAMapNodeID nodeID {depth(), common()};
assert (i == nodeID.selectBranch(childID));
#endif
assert(has_common_prefix(childID));
mChildren[i]->invariants(is_v2);
}
++count;
}
else
{
assert((mIsBranch & (1 << i)) == 0);
}
}
if (!is_root)
{
assert(mHash.isNonZero());
assert(count >= 2);
assert(depth_ > 0);
}
else
{
assert(depth_ == 0);
}
if (count == 0)
assert(mHash.isZero());
else
assert(mHash.isNonZero());
}
void
SHAMapTreeNode::invariants(bool, bool) const
SHAMapTreeNode::invariants(bool) const
{
assert(mType >= tnTRANSACTION_NM);
assert(mHash.isNonZero());

View File

@@ -1,80 +0,0 @@
//-----------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2015 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/app/ledger/Ledger.h>
#include <test/jtx.h>
#include <ripple/beast/unit_test.h>
namespace ripple {
namespace test {
// Test that converting a ledger to SHAMapV2
// works as expected
class SHAMapV2_test : public beast::unit_test::suite
{
void
testSHAMapV2()
{
jtx::Env env(*this);
Config config;
std::set<uint256> amendments;
std::vector<uint256> amendments_v;
amendments_v.push_back(from_hex_text<uint256>("12345"));
amendments.insert(from_hex_text<uint256>("12345"));
auto ledger =
std::make_shared<Ledger>(create_genesis, config,
amendments_v, env.app().family());
BEAST_EXPECT(! getSHAMapV2 (ledger->info()));
BEAST_EXPECT(ledger->stateMap().get_version() == SHAMap::version{1});
BEAST_EXPECT(ledger->txMap().get_version() == SHAMap::version{1});
BEAST_EXPECT(getEnabledAmendments(*ledger) == amendments);
ledger =
std::make_shared<Ledger>(*ledger, NetClock::time_point{});
BEAST_EXPECT(! getSHAMapV2 (ledger->info()));
BEAST_EXPECT(ledger->stateMap().get_version() == SHAMap::version{1});
BEAST_EXPECT(ledger->txMap().get_version() == SHAMap::version{1});
BEAST_EXPECT(getEnabledAmendments(*ledger) == amendments);
ledger->make_v2();
BEAST_EXPECT(getSHAMapV2 (ledger->info()));
BEAST_EXPECT(ledger->stateMap().get_version() == SHAMap::version{2});
BEAST_EXPECT(ledger->txMap().get_version() == SHAMap::version{2});
BEAST_EXPECT(getEnabledAmendments(*ledger) == amendments);
ledger = std::make_shared<Ledger>(*ledger, NetClock::time_point{});
BEAST_EXPECT(getSHAMapV2 (ledger->info()));
BEAST_EXPECT(ledger->stateMap().get_version() == SHAMap::version{2});
BEAST_EXPECT(ledger->txMap().get_version() == SHAMap::version{2});
BEAST_EXPECT(getEnabledAmendments(*ledger) == amendments);
}
void run() override
{
testSHAMapV2();
}
};
BEAST_DEFINE_TESTSUITE(SHAMapV2,ledger,ripple);
} // test
} // ripple

View File

@@ -122,7 +122,7 @@ public:
TestFamily f(journal);
std::shared_ptr <Table> t1 (std::make_shared <Table> (
SHAMapType::FREE, f, SHAMap::version{2}));
SHAMapType::FREE, f));
pass ();

View File

@@ -29,7 +29,7 @@
namespace ripple {
namespace tests {
class sync_test : public beast::unit_test::suite
class SHAMapSync_test : public beast::unit_test::suite
{
public:
beast::xor_shift_engine eng_;
@@ -90,18 +90,9 @@ public:
using namespace beast::severities;
test::SuiteJournal journal ("SHAMapSync_test", *this);
log << "Run, version 1\n" << std::endl;
run(SHAMap::version{1}, journal);
log << "Run, version 2\n" << std::endl;
run(SHAMap::version{2}, journal);
}
void run(SHAMap::version v, beast::Journal const& journal)
{
TestFamily f(journal), f2(journal);
SHAMap source (SHAMapType::FREE, f, v);
SHAMap destination (SHAMapType::FREE, f2, v);
SHAMap source (SHAMapType::FREE, f);
SHAMap destination (SHAMapType::FREE, f2);
int items = 10000;
for (int i = 0; i < items; ++i)
@@ -207,9 +198,10 @@ public:
log << "Checking destination invariants..." << std::endl;
destination.invariants();
}
};
BEAST_DEFINE_TESTSUITE(sync,shamap,ripple);
BEAST_DEFINE_TESTSUITE(SHAMapSync,shamap,ripple);
} // tests
} // ripple

View File

@@ -36,13 +36,6 @@ static_assert(!std::is_copy_assignable <SHAMap>{}, "");
static_assert(!std::is_move_constructible <SHAMap>{}, "");
static_assert(!std::is_move_assignable <SHAMap>{}, "");
static_assert( std::is_nothrow_destructible <SHAMap::version>{}, "");
static_assert(!std::is_default_constructible <SHAMap::version>{}, "");
static_assert( std::is_trivially_copy_constructible<SHAMap::version>{}, "");
static_assert( std::is_trivially_copy_assignable <SHAMap::version>{}, "");
static_assert( std::is_trivially_move_constructible<SHAMap::version>{}, "");
static_assert( std::is_trivially_move_assignable <SHAMap::version>{}, "");
static_assert( std::is_nothrow_destructible <SHAMap::const_iterator>{}, "");
static_assert( std::is_default_constructible<SHAMap::const_iterator>{}, "");
static_assert( std::is_copy_constructible <SHAMap::const_iterator>{}, "");
@@ -85,13 +78,6 @@ static_assert(!std::is_copy_assignable <SHAMapInnerNode>{}, "");
static_assert(!std::is_move_constructible <SHAMapInnerNode>{}, "");
static_assert(!std::is_move_assignable <SHAMapInnerNode>{}, "");
static_assert( std::is_nothrow_destructible <SHAMapInnerNodeV2>{}, "");
static_assert(!std::is_default_constructible<SHAMapInnerNodeV2>{}, "");
static_assert(!std::is_copy_constructible <SHAMapInnerNodeV2>{}, "");
static_assert(!std::is_copy_assignable <SHAMapInnerNodeV2>{}, "");
static_assert(!std::is_move_constructible <SHAMapInnerNodeV2>{}, "");
static_assert(!std::is_move_assignable <SHAMapInnerNodeV2>{}, "");
static_assert( std::is_nothrow_destructible <SHAMapTreeNode>{}, "");
static_assert(!std::is_default_constructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_copy_constructible <SHAMapTreeNode>{}, "");
@@ -123,13 +109,11 @@ public:
using namespace beast::severities;
test::SuiteJournal journal ("SHAMap_test", *this);
run (true, SHAMap::version{1}, journal);
run (false, SHAMap::version{1}, journal);
run (true, SHAMap::version{2}, journal);
run (false, SHAMap::version{2}, journal);
run (true, journal);
run (false, journal);
}
void run (bool backed, SHAMap::version v, beast::Journal const& journal)
void run (bool backed, beast::Journal const& journal)
{
if (backed)
testcase ("add/traverse backed");
@@ -146,7 +130,7 @@ public:
h4.SetHex ("b92891fe4ef6cee585fdc6fda2e09eb4d386363158ec3321b8123e5a772c6ca8");
h5.SetHex ("a92891fe4ef6cee585fdc6fda0e09eb4d386363158ec3321b8123e5a772c6ca7");
SHAMap sMap (SHAMapType::FREE, f, v);
SHAMap sMap (SHAMapType::FREE, f);
sMap.invariants();
if (! backed)
sMap.setUnbacked ();
@@ -208,8 +192,6 @@ public:
sMap.dump();
auto const is_v2 = sMap.is_v2();
if (backed)
testcase ("build/tear backed");
else
@@ -226,30 +208,16 @@ public:
keys[7].SetHex ("292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8");
std::vector<uint256> hashes(8);
if (is_v2)
{
hashes[0].SetHex ("90F77DA53895E34042DC8048518CC98AD24276D0A96CCA2C515A83FDAF9F9FC9");
hashes[1].SetHex ("425A3B6A68FAD9CB43B9981C7D0D39B942FE62110B437201057EE703F5E76390");
hashes[2].SetHex ("1B4BE72DD18F90F367D64C0147D2414329149724339F79958D6470E7C99E3F4A");
hashes[3].SetHex ("CCC18ED9B0C353278F02465E2E2F3A8A07427B458CF74C51D87ABE9C1B2ECAD8");
hashes[4].SetHex ("24AF98675227F387CE0E4932B71B099FE8BC66E5F07BE2DA70D7E7D98E16C8BC");
hashes[5].SetHex ("EAA373271474A9BF18F1CC240B40C7B5C83C7017977F1388771E56D5943F2B9B");
hashes[6].SetHex ("C7968A323A06BD46769B402B2A85A7FE7F37FCE99C0004A6197AD8E5D76F200D");
hashes[7].SetHex ("0A2412DBB16308706211E5FA5B0160817D54757B4DDC0CB105391A79D06B47BA");
}
else
{
hashes[0].SetHex ("B7387CFEA0465759ADC718E8C42B52D2309D179B326E239EB5075C64B6281F7F");
hashes[1].SetHex ("FBC195A9592A54AB44010274163CB6BA95F497EC5BA0A8831845467FB2ECE266");
hashes[2].SetHex ("4E7D2684B65DFD48937FFB775E20175C43AF0C94066F7D5679F51AE756795B75");
hashes[3].SetHex ("7A2F312EB203695FFD164E038E281839EEF06A1B99BFC263F3CECC6C74F93E07");
hashes[4].SetHex ("395A6691A372387A703FB0F2C6D2C405DAF307D0817F8F0E207596462B0E3A3E");
hashes[5].SetHex ("D044C0A696DE3169CC70AE216A1564D69DE96582865796142CE7D98A84D9DDE4");
hashes[6].SetHex ("76DCC77C4027309B5A91AD164083264D70B77B5E43E08AEDA5EBF94361143615");
hashes[7].SetHex ("DF4220E93ADC6F5569063A01B4DC79F8DB9553B6A3222ADE23DEA02BBE7230E5");
}
hashes[0].SetHex ("B7387CFEA0465759ADC718E8C42B52D2309D179B326E239EB5075C64B6281F7F");
hashes[1].SetHex ("FBC195A9592A54AB44010274163CB6BA95F497EC5BA0A8831845467FB2ECE266");
hashes[2].SetHex ("4E7D2684B65DFD48937FFB775E20175C43AF0C94066F7D5679F51AE756795B75");
hashes[3].SetHex ("7A2F312EB203695FFD164E038E281839EEF06A1B99BFC263F3CECC6C74F93E07");
hashes[4].SetHex ("395A6691A372387A703FB0F2C6D2C405DAF307D0817F8F0E207596462B0E3A3E");
hashes[5].SetHex ("D044C0A696DE3169CC70AE216A1564D69DE96582865796142CE7D98A84D9DDE4");
hashes[6].SetHex ("76DCC77C4027309B5A91AD164083264D70B77B5E43E08AEDA5EBF94361143615");
hashes[7].SetHex ("DF4220E93ADC6F5569063A01B4DC79F8DB9553B6A3222ADE23DEA02BBE7230E5");
SHAMap map (SHAMapType::FREE, f, v);
SHAMap map (SHAMapType::FREE, f);
if (! backed)
map.setUnbacked ();
@@ -261,24 +229,6 @@ public:
BEAST_EXPECT(map.getHash().as_uint256() == hashes[k]);
map.invariants();
}
if (v == SHAMap::version{1})
{
BEAST_EXPECT(!map.is_v2());
auto map_v2 = map.make_v2();
BEAST_EXPECT(map_v2 != nullptr);
BEAST_EXPECT(map_v2->is_v2());
map_v2->invariants();
auto m1 = map.begin();
auto e1 = map.end();
auto m2 = map_v2->begin();
auto e2 = map_v2->end();
for (; m1 != e1; ++m1, ++m2)
{
BEAST_EXPECT(m2 != e2);
BEAST_EXPECT(*m1 == *m2);
}
BEAST_EXPECT(m2 == e2);
}
for (int k = keys.size() - 1; k >= 0; --k)
{
BEAST_EXPECT(map.getHash().as_uint256() == hashes[k]);
@@ -305,7 +255,7 @@ public:
keys[7].SetHex ("292891fe4ef6cee585fdc6fda1e09eb4d386363158ec3321b8123e5a772c6ca8");
tests::TestFamily tf{journal};
SHAMap map{SHAMapType::FREE, tf, v};
SHAMap map{SHAMapType::FREE, tf};
if (! backed)
map.setUnbacked ();
for (auto const& k : keys)

View File

@@ -24,6 +24,5 @@
#include <test/ledger/Invariants_test.cpp>
#include <test/ledger/PaymentSandbox_test.cpp>
#include <test/ledger/PendingSaves_test.cpp>
#include <test/ledger/SHAMapV2_test.cpp>
#include <test/ledger/SkipList_test.cpp>
#include <test/ledger/View_test.cpp>