Skip to content

Commit

Permalink
mpt: Extract and use Kind for path encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Dec 21, 2023
1 parent 5917ee2 commit 6004d73
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 32 deletions.
47 changes: 18 additions & 29 deletions test/state/mpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ namespace evmone::state
{
namespace
{
/// The MPT node kind.
enum class Kind : uint8_t
{
leaf,
ext,
branch
};

/// The collection of nibbles (4-bit values) representing a path in a MPT.
struct Path
{
Expand All @@ -32,9 +40,8 @@ struct Path
size_t i = 0;
for (const auto b : key)
{
// static_cast is only needed in GCC <= 8.
nibbles[i++] = static_cast<uint8_t>(b >> 4);
nibbles[i++] = static_cast<uint8_t>(b & 0x0f);
nibbles[i++] = b >> 4;
nibbles[i++] = b & 0x0f;
}
}

Expand All @@ -44,24 +51,13 @@ struct Path
return {length - pos, &nibbles[pos]};
}

[[nodiscard]] bytes encode(bool extended) const
[[nodiscard]] bytes encode(Kind kind) const
{
bytes bs;
const auto is_even = length % 2 == 0;
if (is_even)
bs.push_back(0x00);
else
bs.push_back(0x10 | nibbles[0]);
for (size_t i = is_even ? 0 : 1; i < length; ++i)
{
const auto h = nibbles[i++];
const auto l = nibbles[i];
assert(h <= 0x0f);
assert(l <= 0x0f);
bs.push_back(static_cast<uint8_t>((h << 4) | l));
}
if (!extended)
bs[0] |= 0x20;
bytes bs{static_cast<uint8_t>(
(is_even ? 0x00 : (0x10 | nibbles[0])) | (kind == Kind::leaf ? 0x20 : 0x00))};
for (size_t i = is_even ? 0 : 1; i < length; i += 2)
bs.push_back(static_cast<uint8_t>((nibbles[i] << 4) | nibbles[i + 1]));
return bs;
}
};
Expand All @@ -70,17 +66,10 @@ struct Path
/// The MPT Node.
///
/// The implementation is based on StackTrie from go-ethereum.
// clang-tidy bug: https://github.com/llvm/llvm-project/issues/50006
// TODO(clang-tidy-17): bug https://github.com/llvm/llvm-project/issues/50006
// NOLINTNEXTLINE(bugprone-reserved-identifier)
class MPTNode
{
enum class Kind : uint8_t
{
leaf,
ext,
branch
};

static constexpr size_t num_children = 16;

Kind m_kind = Kind::leaf;
Expand Down Expand Up @@ -243,7 +232,7 @@ bytes MPTNode::encode() const // NOLINT(misc-no-recursion)
{
case Kind::leaf:
{
encoded = rlp::encode(m_path.encode(false)) + rlp::encode(m_value);
encoded = rlp::encode(m_path.encode(m_kind)) + rlp::encode(m_value);
break;
}
case Kind::branch:
Expand All @@ -263,7 +252,7 @@ bytes MPTNode::encode() const // NOLINT(misc-no-recursion)
}
case Kind::ext:
{
encoded = rlp::encode(m_path.encode(true)) + encode_child(*m_children[0]);
encoded = rlp::encode(m_path.encode(m_kind)) + encode_child(*m_children[0]);
break;
}
}
Expand Down
8 changes: 5 additions & 3 deletions test/state/mpt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ constexpr auto emptyMPTHash =
/// out of (key, value) pairs.
///
/// Limitations:
/// 1. All inserted keys must be of the same length (this is by MTP design?).
/// 2. Inserted values cannot be updated (by inserting the same key again).
/// 3. Inserted values cannot be erased.
/// 1. The keys must not be longer than 32 bytes.
/// 2. All inserted keys must be of the same length.
/// This comes from the spec (Yellow Paper Appendix D) - a branch node cannot store a value.
/// 3. Inserted values cannot be updated (by inserting the same key again).
/// 4. Inserted values cannot be erased.
class MPT
{
std::unique_ptr<class MPTNode> m_root;
Expand Down

0 comments on commit 6004d73

Please sign in to comment.