Commit 9d435aec authored by smartcontracts's avatar smartcontracts Committed by GitHub

style(ctb): clean MerkleTrie and SecureMerkleTrie (#3006)

Cleans up natspec in the MerkleTrie and SecureMerkleTrie contracts.
parent ae4440b3
---
'@eth-optimism/contracts-bedrock': patch
---
Cleans up natspec in MerkleTrie and SecureMerkleTrie contracts
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/* Library Imports */
import { BytesUtils } from "../BytesUtils.sol";
import { RLPReader } from "../rlp/RLPReader.sol";
import { RLPWriter } from "../rlp/RLPWriter.sol";
/**
* @title MerkleTrie
* @notice MerkleTrie is a small library for verifying standard Ethereum Merkle-Patricia trie
* inclusion proofs. By default, this library assumes a hexary trie. One can change the
* trie radix constant to support other trie radixes.
*/
library MerkleTrie {
/*******************
* Data Structures *
*******************/
/**
* @notice Struct representing a node in the trie.
*/
struct TrieNode {
bytes encoded;
RLPReader.RLPItem[] decoded;
}
/**********************
* Contract Constants *
**********************/
// TREE_RADIX determines the number of elements per branch node.
/**
* @notice Determines the number of elements per branch node.
*/
uint256 constant TREE_RADIX = 16;
// Branch nodes have TREE_RADIX elements plus an additional `value` slot.
/**
* @notice Branch nodes have TREE_RADIX elements and one value element.
*/
uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;
// Leaf nodes and extension nodes always have two elements, a `path` and a `value`.
/**
* @notice Leaf nodes and extension nodes have two elements, a `path` and a `value`.
*/
uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;
// Prefixes are prepended to the `path` within a leaf or extension node and
// allow us to differentiate between the two node types. `ODD` or `EVEN` is
// determined by the number of nibbles within the unprefixed `path`. If the
// number of nibbles if even, we need to insert an extra padding nibble so
// the resulting prefixed `path` has an even number of nibbles.
/**
* @notice Prefix for even-nibbled extension node paths.
*/
uint8 constant PREFIX_EXTENSION_EVEN = 0;
/**
* @notice Prefix for odd-nibbled extension node paths.
*/
uint8 constant PREFIX_EXTENSION_ODD = 1;
/**
* @notice Prefix for even-nibbled leaf node paths.
*/
uint8 constant PREFIX_LEAF_EVEN = 2;
/**
* @notice Prefix for odd-nibbled leaf node paths.
*/
uint8 constant PREFIX_LEAF_ODD = 3;
// Just a utility constant. RLP represents `NULL` as 0x80.
/**
* @notice RLP representation of `NULL`.
*/
bytes1 constant RLP_NULL = bytes1(0x80);
/**********************
* Internal Functions *
**********************/
/**
* @notice Verifies a proof that a given key/value pair is present in the
* Merkle trie.
* @param _key Key of the node to search for, as a hex string.
* @notice Verifies a proof that a given key/value pair is present in the trie.
*
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike
* traditional Merkle trees, this proof is executed top-down and consists
* of a list of RLP-encoded nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return _verified `true` if the k/v pair exists in the trie, `false` otherwise.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
* trees, this proof is executed top-down and consists of a list of RLP-encoded
* nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the included proof is
* correctly constructed.
*
* @return Whether or not the proof is valid.
*/
function verifyInclusionProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
) internal pure returns (bool _verified) {
) internal pure returns (bool) {
(bool exists, bytes memory value) = get(_key, _proof, _root);
return (exists && BytesUtils.equal(_value, value));
}
/**
* @notice Retrieves the value associated with a given key.
* @param _key Key to search for, as hex bytes.
*
* @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie.
* @return _exists Whether or not the key exists.
* @return _value Value of the key if it exists.
* @param _root Known root of the Merkle trie.
*
* @return Whether or not the key exists.
* @return Value of the key if it exists.
*/
function get(
bytes memory _key,
bytes memory _proof,
bytes32 _root
) internal pure returns (bool _exists, bytes memory _value) {
) internal pure returns (bool, bytes memory) {
TrieNode[] memory proof = _parseProof(_proof);
(uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(
proof,
......@@ -99,18 +114,16 @@ library MerkleTrie {
return (exists, value);
}
/*********************
* Private Functions *
*********************/
/**
* @notice Walks through a proof using a provided key.
*
* @param _proof Inclusion proof to walk through.
* @param _key Key to use for the walk.
* @param _root Known root of the trie.
* @return _pathLength Length of the final path
* @return _keyRemainder Portion of the key remaining after the walk.
* @return _isFinalNode Whether or not we've hit a dead end.
* @param _key Key to use for the walk.
* @param _root Known root of the trie.
*
* @return Length of the final path
* @return Portion of the key remaining after the walk.
* @return Whether or not we've hit a dead end.
*/
function _walkNodePath(
TrieNode[] memory _proof,
......@@ -120,9 +133,9 @@ library MerkleTrie {
private
pure
returns (
uint256 _pathLength,
bytes memory _keyRemainder,
bool _isFinalNode
uint256,
bytes memory,
bool
)
{
uint256 pathLength = 0;
......@@ -223,10 +236,12 @@ library MerkleTrie {
/**
* @notice Parses an RLP-encoded proof into something more useful.
*
* @param _proof RLP-encoded proof to parse.
* @return _parsed Proof parsed into easily accessible structs.
*
* @return Proof parsed into easily accessible structs.
*/
function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) {
function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory) {
RLPReader.RLPItem[] memory nodes = RLPReader.readList(_proof);
TrieNode[] memory proof = new TrieNode[](nodes.length);
......@@ -239,13 +254,14 @@ library MerkleTrie {
}
/**
* @notice Picks out the ID for a node. Node ID is referred to as the
* "hash" within the specification, but nodes < 32 bytes are not actually
* hashed.
* @notice Picks out the ID for a node. Node ID is referred to as the "hash" within the
* specification, but nodes < 32 bytes are not actually hashed.
*
* @param _node Node to pull an ID for.
* @return _nodeID ID for the node, depending on the size of its contents.
*
* @return ID for the node, depending on the size of its contents.
*/
function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) {
function _getNodeID(RLPReader.RLPItem memory _node) private pure returns (bytes32) {
bytes memory nodeID;
if (_node.length < 32) {
......@@ -261,33 +277,38 @@ library MerkleTrie {
/**
* @notice Gets the path for a leaf or extension node.
*
* @param _node Node to get a path for.
* @return _path Node path, converted to an array of nibbles.
*
* @return Node path, converted to an array of nibbles.
*/
function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) {
function _getNodePath(TrieNode memory _node) private pure returns (bytes memory) {
return BytesUtils.toNibbles(RLPReader.readBytes(_node.decoded[0]));
}
/**
* @notice Gets the path for a node.
*
* @param _node Node to get a value for.
* @return _value Node value, as hex bytes.
*
* @return Node value, as hex bytes.
*/
function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) {
function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory) {
return RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]);
}
/**
* @notice Utility; determines the number of nibbles shared between two
* nibble arrays.
* @notice Utility; determines the number of nibbles shared between two nibble arrays.
*
* @param _a First nibble array.
* @param _b Second nibble array.
* @return _shared Number of shared nibbles.
*
* @return Number of shared nibbles.
*/
function _getSharedNibbleLength(bytes memory _a, bytes memory _b)
private
pure
returns (uint256 _shared)
returns (uint256)
{
uint256 i = 0;
while (_a.length > i && _b.length > i && _a[i] == _b[i]) {
......
......@@ -6,61 +6,60 @@ import { MerkleTrie } from "./MerkleTrie.sol";
/**
* @title SecureMerkleTrie
* @notice SecureMerkleTrie is a thin wrapper around the MerkleTrie library that hashes the input
* keys. Ethereum's state trie hashes input keys before storing them.
*/
library SecureMerkleTrie {
/**********************
* Internal Functions *
**********************/
/**
* @notice Verifies a proof that a given key/value pair is present in the
* Merkle trie.
* @param _key Key of the node to search for, as a hex string.
* @notice Verifies a proof that a given key/value pair is present in the Merkle trie.
*
* @param _key Key of the node to search for, as a hex string.
* @param _value Value of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike
* traditional Merkle trees, this proof is executed top-down and consists
* of a list of RLP-encoded nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the
* included proof is correctly constructed.
* @return _verified `true` if the k/v pair exists in the trie, `false` otherwise.
* @param _proof Merkle trie inclusion proof for the desired node. Unlike traditional Merkle
* trees, this proof is executed top-down and consists of a list of RLP-encoded
* nodes that make a path down to the target node.
* @param _root Known root of the Merkle trie. Used to verify that the included proof is
* correctly constructed.
*
* @return Whether or not the proof is valid.
*/
function verifyInclusionProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
) internal pure returns (bool _verified) {
) internal pure returns (bool) {
bytes memory key = _getSecureKey(_key);
return MerkleTrie.verifyInclusionProof(key, _value, _proof, _root);
}
/**
* @notice Retrieves the value associated with a given key.
* @param _key Key to search for, as hex bytes.
*
* @param _key Key to search for, as hex bytes.
* @param _proof Merkle trie inclusion proof for the key.
* @param _root Known root of the Merkle trie.
* @return _exists Whether or not the key exists.
* @return _value Value of the key if it exists.
* @param _root Known root of the Merkle trie.
*
* @return Whether or not the key exists.
* @return Value of the key if it exists.
*/
function get(
bytes memory _key,
bytes memory _proof,
bytes32 _root
) internal pure returns (bool _exists, bytes memory _value) {
) internal pure returns (bool, bytes memory) {
bytes memory key = _getSecureKey(_key);
return MerkleTrie.get(key, _proof, _root);
}
/*********************
* Private Functions *
*********************/
/**
* Computes the secure counterpart to a key.
* @param _key Key to get a secure key from.
* @return _secureKey Secure version of the key.
* @notice Computes the hashed version of the input key.
*
* @param _key Key to hash.
*
* @return Hashed version of the key.
*/
function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) {
function _getSecureKey(bytes memory _key) private pure returns (bytes memory) {
return abi.encodePacked(keccak256(_key));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment