mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-29 06:55:49 +00:00
Remove SHAMap V2
This commit is contained in:
committed by
Manoj doshi
parent
33ab0cd7bd
commit
7228b2e068
@@ -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
|
||||
#[===============================[
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -314,7 +314,6 @@ public:
|
||||
|
||||
bool assertSane (beast::Journal ledgerJ) const;
|
||||
|
||||
void make_v2();
|
||||
void invariants() const;
|
||||
void unshare() const;
|
||||
private:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
@@ -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 ();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user