-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added initial changes to support multiple Merkle trees in the storage. #2953
Merged
HristoStaykov
merged 9 commits into
vmware:storage/changes_for_eth_support
from
HristoStaykov:WIP_support_mutiple_mpts
Mar 31, 2023
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
0e49cbf
Added initial changes to support multiple Merkle trees in the storage.
HristoStaykov 7341f5a
Fix for sparse_merkle_storage_serialization_unit_test.
HristoStaykov 3309a76
Serialization fixes.
HristoStaykov 519dd97
Addressed clang-tidy warnings.
HristoStaykov 85e64f8
Moved address to be the first field in InternalNodeKey.
HristoStaykov d3fd201
Added Address field to LeafKey.
HristoStaykov 5667051
Fix for kvbc/test/sparse_merkle_storage/serialization_unit_test.
HristoStaykov ec0309d
Clang tidy report fixes.
HristoStaykov 1f605ed
Renamed address to custom_prefix.
HristoStaykov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,6 +53,57 @@ class Version { | |
Type value_ = 0; | ||
}; | ||
|
||
// A type safe custom prefix wrapper | ||
class CustomPrefix { | ||
public: | ||
using Type = std::string; | ||
using SIZE_PREFIX_TYPE = std::uint8_t; | ||
static constexpr auto SIZE_IN_BYTES = 20 * sizeof(std::uint8_t); | ||
static constexpr auto SIZE_PREFIX_BYTES = sizeof(std::uint8_t); | ||
static constexpr auto TOTAL_SIZE = SIZE_PREFIX_BYTES + SIZE_IN_BYTES; | ||
|
||
public: | ||
CustomPrefix() = default; | ||
CustomPrefix(size_t size) { | ||
ConcordAssert(size <= SIZE_IN_BYTES); | ||
prefix_.assign('\0', size); | ||
} | ||
CustomPrefix(const Type& val) : prefix_(val) { ConcordAssert(val.size() <= SIZE_IN_BYTES); } | ||
CustomPrefix(Type&& val) : prefix_(std::move(val)) { ConcordAssert(val.size() <= SIZE_IN_BYTES); } | ||
|
||
void set(std::uint8_t pos, char c) { | ||
ConcordAssert(pos < prefix_.size()); | ||
prefix_[pos] = c; | ||
} | ||
char get(std::uint8_t pos) const { | ||
ConcordAssert(pos < prefix_.size()); | ||
return prefix_[pos]; | ||
} | ||
bool operator==(const CustomPrefix& other) const { return prefix_ == other.prefix_; } | ||
bool operator!=(const CustomPrefix& other) const { return prefix_ != other.prefix_; } | ||
bool operator<(const CustomPrefix& other) const { return prefix_ < other.prefix_; } | ||
|
||
const Type& value() const { return prefix_; } | ||
size_t size() const { return prefix_.size(); } | ||
|
||
protected: | ||
Type prefix_; | ||
}; | ||
|
||
class PaddedCustomPrefix : public CustomPrefix { | ||
public: | ||
template <class T> | ||
PaddedCustomPrefix(T&& arg) : CustomPrefix(std::forward<T>(arg)) {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this template can accept other types than std::string? |
||
char get(std::uint8_t pos) const { | ||
ConcordAssert(pos < SIZE_IN_BYTES); | ||
if (pos < prefix_.size()) { | ||
return prefix_[pos]; | ||
} else { | ||
return '\0'; | ||
} | ||
} | ||
}; | ||
|
||
// A nibble is 4 bits, stored in the lower bits of a byte. | ||
class Nibble { | ||
public: | ||
|
@@ -243,7 +294,7 @@ class NibblePath { | |
NibblePath() : num_nibbles_(0) {} | ||
NibblePath(size_t num_nibbles, const std::vector<uint8_t>& path) : num_nibbles_(num_nibbles), path_(path) { | ||
ConcordAssert(num_nibbles < Hash::MAX_NIBBLES); | ||
ConcordAssert(path.size() == (num_nibbles % 2 ? (num_nibbles + 1) / 2 : num_nibbles / 2)); | ||
ConcordAssert(path.size() == pathLengthInBytes(num_nibbles)); | ||
} | ||
|
||
bool operator==(const NibblePath& other) const { return num_nibbles_ == other.num_nibbles_ && path_ == other.path_; } | ||
|
@@ -263,6 +314,11 @@ class NibblePath { | |
return false; | ||
} | ||
|
||
// Return the count of elements (bytes) in path_ | ||
static size_t pathLengthInBytes(size_t num_nibbles) { | ||
return (num_nibbles % 2 ? (num_nibbles + 1) / 2 : num_nibbles / 2); | ||
} | ||
|
||
// Return the length of the path_ in nibbles | ||
size_t length() const { return num_nibbles_; } | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,34 +24,47 @@ namespace sparse_merkle { | |
// are part of the batch by pointing to their containing BatchedInternalNode. | ||
class InternalNodeKey { | ||
public: | ||
InternalNodeKey(Version version, const NibblePath& path) : version_(version), path_(path) {} | ||
template <class T> | ||
InternalNodeKey(T&& custom_prefix, Version version, const NibblePath& path) | ||
: custom_prefix_(std::forward<T>(custom_prefix)), version_(version), path_(path) {} | ||
|
||
// Return the root of a sparse merkle tree at a given version. | ||
static InternalNodeKey root(Version version) { return InternalNodeKey(version, NibblePath()); } | ||
template <class T> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above, do we need to template it? As far as I only std::string satisfies it |
||
static InternalNodeKey root(T&& custom_prefix, Version version) { | ||
return InternalNodeKey(std::forward<T>(custom_prefix), version, NibblePath()); | ||
} | ||
|
||
bool operator==(const InternalNodeKey& other) const { return version_ == other.version_ && path_ == other.path_; } | ||
bool operator==(const InternalNodeKey& other) const { | ||
return custom_prefix_ == other.custom_prefix_ && version_ == other.version_ && path_ == other.path_; | ||
} | ||
|
||
// Compare by version then by path | ||
// Compare by address, version and then by path | ||
bool operator<(const InternalNodeKey& other) const { | ||
if (version_ == other.version_) { | ||
return path_ < other.path_; | ||
if (custom_prefix_ != other.custom_prefix_) { | ||
return custom_prefix_ < other.custom_prefix_; | ||
} | ||
return version_ < other.version_; | ||
if (version_ != other.version_) { | ||
return version_ < other.version_; | ||
} | ||
return path_ < other.path_; | ||
} | ||
|
||
std::string toString() const { | ||
if (path_.empty()) { | ||
return std::string("<ROOT>") + "-" + version_.toString(); | ||
return custom_prefix_.value() + std::string("-<ROOT>") + "-" + version_.toString(); | ||
} | ||
return path_.toString() + "-" + version_.toString(); | ||
return custom_prefix_.value() + "-" + path_.toString() + "-" + version_.toString(); | ||
} | ||
|
||
Version version() const { return version_; } | ||
|
||
const CustomPrefix& customPrefix() const { return custom_prefix_; } | ||
|
||
const NibblePath& path() const { return path_; } | ||
NibblePath& path() { return path_; } | ||
|
||
private: | ||
CustomPrefix custom_prefix_; | ||
Version version_; | ||
NibblePath path_; | ||
}; | ||
|
@@ -63,36 +76,46 @@ class InternalNodeKey { | |
// merkle tree. | ||
class LeafKey { | ||
public: | ||
static constexpr auto SIZE_IN_BYTES = Hash::SIZE_IN_BYTES + Version::SIZE_IN_BYTES; | ||
static constexpr auto SIZE_IN_BYTES = PaddedCustomPrefix::TOTAL_SIZE + Hash::SIZE_IN_BYTES + Version::SIZE_IN_BYTES; | ||
|
||
public: | ||
LeafKey(Hash key, Version version) : key_(key), version_(version) {} | ||
template <class T> | ||
LeafKey(Hash key, Version version, T&& address) : key_(key), version_(version), prefix_(std::forward<T>(address)) {} | ||
LeafKey(Hash key, Version version) : key_(key), version_(version), prefix_("") {} | ||
|
||
bool operator==(const LeafKey& other) const { return key_ == other.key_ && version_ == other.version_; } | ||
bool operator==(const LeafKey& other) const { | ||
return prefix_ == other.prefix_ && key_ == other.key_ && version_ == other.version_; | ||
} | ||
bool operator!=(const LeafKey& other) const { return !(*this == other); } | ||
|
||
// Compare by key_ then version_ | ||
// Compare by prefix_, key_ and then version_ | ||
bool operator<(const LeafKey& other) const { | ||
if (key_ < other.key_) { | ||
return true; | ||
if (prefix_ != other.prefix_) { | ||
return prefix_ < other.prefix_; | ||
} | ||
if (key_ != other.key_) { | ||
return key_ < other.key_; | ||
} | ||
return key_ == other.key_ && version_ < other.version_; | ||
return version_ < other.version_; | ||
} | ||
|
||
std::string toString() const { return key_.toString() + "-" + version_.toString(); } | ||
std::string toString() const { return key_.toString() + "-" + version_.toString() + "-" + prefix_.value(); } | ||
|
||
Nibble getNibble(const size_t n) const { | ||
ConcordAssert(n < Hash::MAX_NIBBLES); | ||
return key_.getNibble(n); | ||
} | ||
|
||
const PaddedCustomPrefix& customPrefix() const { return prefix_; } | ||
|
||
Version version() const { return version_; } | ||
|
||
const Hash& hash() const { return key_; } | ||
|
||
private: | ||
Hash key_; | ||
Version version_; | ||
PaddedCustomPrefix prefix_; | ||
}; | ||
|
||
std::ostream& operator<<(std::ostream& os, const LeafKey&); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not to use std::string directly?