Commit 139a4b4f authored by George Hotz's avatar George Hotz

modify Lib_MerkleTrie to support trie in storage

parent c63d2d8c
...@@ -2,25 +2,16 @@ ...@@ -2,25 +2,16 @@
pragma solidity ^0.7.3; pragma solidity ^0.7.3;
import "./lib/Lib_Keccak256.sol"; import "./lib/Lib_Keccak256.sol";
import "hardhat/console.sol"; //import "hardhat/console.sol";
//import "./lib/Lib_MerkleTrie.sol"; import "./lib/Lib_MerkleTrie.sol";
import { Lib_RLPReader } from "./lib/Lib_RLPReader.sol"; //import { Lib_RLPReader } from "./lib/Lib_RLPReader.sol";
import { Lib_BytesUtils } from "./lib/Lib_BytesUtils.sol"; //import { Lib_BytesUtils } from "./lib/Lib_BytesUtils.sol";
contract MIPSMemory { contract MIPSMemory {
// TODO: the trie library should read and write from this as appropriate // TODO: the trie library should read and write from this as appropriate
mapping(bytes32 => bytes) public trie; mapping(bytes32 => bytes) public trie;
uint256 constant TREE_RADIX = 16;
uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1;
uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2;
uint8 constant PREFIX_EXTENSION_EVEN = 0;
uint8 constant PREFIX_EXTENSION_ODD = 1;
uint8 constant PREFIX_LEAF_EVEN = 2;
uint8 constant PREFIX_LEAF_ODD = 3;
function AddTrieNode(bytes calldata anything) public { function AddTrieNode(bytes calldata anything) public {
trie[keccak256(anything)] = anything; trie[keccak256(anything)] = anything;
} }
...@@ -142,17 +133,18 @@ contract MIPSMemory { ...@@ -142,17 +133,18 @@ contract MIPSMemory {
(uint32(a3) << 0); (uint32(a3) << 0);
} }
/*bool exists; bool exists;
bytes memory value; bytes memory value;
(exists, value) = Lib_MerkleTrie.get(tb(addr), proofs[stateHash][addr], stateHash); (exists, value) = Lib_MerkleTrie.get(tb(addr>>2), trie, stateHash);
if (!exists) { if (!exists) {
// this is uninitialized memory // this is uninitialized memory
return 0; return 0;
} else { } else {
return fb(value); return fb(value);
}*/ }
bytes memory key = Lib_BytesUtils.toNibbles(tb(addr>>2));
/*bytes memory key = Lib_BytesUtils.toNibbles(tb(addr>>2));
bytes32 cnode = stateHash; bytes32 cnode = stateHash;
uint256 idx = 0; uint256 idx = 0;
...@@ -189,8 +181,8 @@ contract MIPSMemory { ...@@ -189,8 +181,8 @@ contract MIPSMemory {
} else { } else {
revert("node in trie broken"); revert("node in trie broken");
} }
} }*/
//return fb(get(tb(addr>>2), stateHash));
} }
} }
\ No newline at end of file
...@@ -58,68 +58,6 @@ library Lib_MerkleTrie { ...@@ -58,68 +58,6 @@ library Lib_MerkleTrie {
* Internal Functions * * 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.
* @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.
*/
function verifyInclusionProof(
bytes memory _key,
bytes memory _value,
bytes memory _proof,
bytes32 _root
)
internal
pure
returns (
bool _verified
)
{
(
bool exists,
bytes memory value
) = get(_key, _proof, _root);
return (
exists && Lib_BytesUtils.equal(_value, value)
);
}
/**
* @notice Verifies a proof that a given key is *not* present in
* the Merkle trie.
* @param _key Key of the node to search for, as a hex string.
* @param _proof Merkle trie inclusion proof for the node *nearest* 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 key is absent in the trie, `false` otherwise.
*/
function verifyExclusionProof(
bytes memory _key,
bytes memory _proof,
bytes32 _root
)
internal
pure
returns (
bool _verified
)
{
(
bool exists,
) = get(_key, _proof, _root);
return exists == false;
}
/** /**
* @notice Updates a Merkle trie and returns a new root hash. * @notice Updates a Merkle trie and returns a new root hash.
* @param _key Key of the node to update, as a hex string. * @param _key Key of the node to update, as a hex string.
...@@ -144,7 +82,7 @@ library Lib_MerkleTrie { ...@@ -144,7 +82,7 @@ library Lib_MerkleTrie {
) )
{ {
// Special case when inserting the very first node. // Special case when inserting the very first node.
if (_root == KECCAK256_RLP_NULL_BYTES) { /*if (_root == KECCAK256_RLP_NULL_BYTES) {
return getSingleNodeRootHash(_key, _value); return getSingleNodeRootHash(_key, _value);
} }
...@@ -152,31 +90,41 @@ library Lib_MerkleTrie { ...@@ -152,31 +90,41 @@ library Lib_MerkleTrie {
(uint256 pathLength, bytes memory keyRemainder, ) = _walkNodePath(proof, _key, _root); (uint256 pathLength, bytes memory keyRemainder, ) = _walkNodePath(proof, _key, _root);
TrieNode[] memory newPath = _getNewPath(proof, pathLength, keyRemainder, _value); TrieNode[] memory newPath = _getNewPath(proof, pathLength, keyRemainder, _value);
return _getUpdatedTrieRoot(newPath, _key); return _getUpdatedTrieRoot(newPath, _key);*/
}
function getRawNode(bytes memory encoded) private view returns (TrieNode memory) {
return TrieNode({
encoded: encoded,
decoded: Lib_RLPReader.readList(encoded)
});
}
function getTrieNode(mapping(bytes32 => bytes) storage trie, bytes32 nodeId) private view returns (TrieNode memory) {
return getRawNode(trie[nodeId]);
} }
/** /**
* @notice Retrieves the value associated with a given key. * @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 trie Merkle trie
* @param _root Known root of the Merkle trie. * @param _root Known root of the Merkle trie.
* @return _exists Whether or not the key exists. * @return _exists Whether or not the key exists.
* @return _value Value of the key if it exists. * @return _value Value of the key if it exists.
*/ */
function get( function get(
bytes memory _key, bytes memory _key,
bytes memory _proof, mapping(bytes32 => bytes) storage trie,
bytes32 _root bytes32 _root
) )
internal internal
pure view
returns ( returns (
bool _exists, bool _exists,
bytes memory _value bytes memory _value
) )
{ {
TrieNode[] memory proof = _parseProof(_proof); (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode, TrieNode memory finalNode) = _walkNodePath(trie, _key, _root);
(uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath(proof, _key, _root);
bool exists = keyRemainder.length == 0; bool exists = keyRemainder.length == 0;
...@@ -185,7 +133,7 @@ library Lib_MerkleTrie { ...@@ -185,7 +133,7 @@ library Lib_MerkleTrie {
"Provided proof is invalid." "Provided proof is invalid."
); );
bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(''); bytes memory value = exists ? _getNodeValue(finalNode) : bytes('');
return ( return (
exists, exists,
...@@ -222,37 +170,44 @@ library Lib_MerkleTrie { ...@@ -222,37 +170,44 @@ library Lib_MerkleTrie {
/** /**
* @notice Walks through a proof using a provided key. * @notice Walks through a proof using a provided key.
* @param _proof Inclusion proof to walk through. * @param trie Merkle trie
* @param _key Key to use for the walk. * @param _key Key to use for the walk.
* @param _root Known root of the trie. * @param _root Known root of the trie.
* @return _pathLength Length of the final path * @return _pathLength Length of the final path
* @return _keyRemainder Portion of the key remaining after the walk. * @return _keyRemainder Portion of the key remaining after the walk.
* @return _isFinalNode Whether or not we've hit a dead end. * @return _isFinalNode Whether or not we've hit a dead end.
* @return _finalNode The final node
*/ */
function _walkNodePath( function _walkNodePath(
TrieNode[] memory _proof, mapping(bytes32 => bytes) storage trie,
bytes memory _key, bytes memory _key,
bytes32 _root bytes32 _root
) )
private private
pure view
returns ( returns (
uint256 _pathLength, uint256 _pathLength,
bytes memory _keyRemainder, bytes memory _keyRemainder,
bool _isFinalNode bool _isFinalNode,
TrieNode memory _finalNode
) )
{ {
uint256 pathLength = 0; uint256 pathLength = 0;
bytes memory key = Lib_BytesUtils.toNibbles(_key); bytes memory key = Lib_BytesUtils.toNibbles(_key);
bytes32 currentNodeID = _root; bytes32 currentNodeID = _root;
uint256 currentNodeLength = 32;
uint256 currentKeyIndex = 0; uint256 currentKeyIndex = 0;
uint256 currentKeyIncrement = 0; uint256 currentKeyIncrement = 0;
TrieNode memory currentNode; TrieNode memory currentNode;
// Proof is top-down, so we start at the first element (root). // Proof is top-down, so we start at the first element (root).
for (uint256 i = 0; i < _proof.length; i++) { while (true) {
currentNode = _proof[i]; if (currentNodeLength >= 32) {
currentNode = getTrieNode(trie, currentNodeID);
} else {
currentNode = getRawNode(Lib_BytesUtils.slice(abi.encodePacked(currentNodeID), 0, currentNodeLength));
}
currentKeyIndex += currentKeyIncrement; currentKeyIndex += currentKeyIncrement;
// Keep track of the proof elements we actually need. // Keep track of the proof elements we actually need.
...@@ -288,7 +243,7 @@ library Lib_MerkleTrie { ...@@ -288,7 +243,7 @@ library Lib_MerkleTrie {
// Figure out what the next node ID should be and continue. // Figure out what the next node ID should be and continue.
uint8 branchKey = uint8(key[currentKeyIndex]); uint8 branchKey = uint8(key[currentKeyIndex]);
Lib_RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey]; Lib_RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey];
currentNodeID = _getNodeID(nextNode); (currentNodeID, currentNodeLength) = _getNodeID(nextNode);
currentKeyIncrement = 1; currentKeyIncrement = 1;
continue; continue;
} }
...@@ -322,7 +277,7 @@ library Lib_MerkleTrie { ...@@ -322,7 +277,7 @@ library Lib_MerkleTrie {
} else { } else {
// Our extension shares some nibbles. // Our extension shares some nibbles.
// Carry on to the next node. // Carry on to the next node.
currentNodeID = _getNodeID(currentNode.decoded[1]); (currentNodeID, currentNodeLength) = _getNodeID(currentNode.decoded[1]);
currentKeyIncrement = sharedNibbleLength; currentKeyIncrement = sharedNibbleLength;
continue; continue;
} }
...@@ -336,7 +291,7 @@ library Lib_MerkleTrie { ...@@ -336,7 +291,7 @@ library Lib_MerkleTrie {
// If our node ID is NULL, then we're at a dead end. // If our node ID is NULL, then we're at a dead end.
bool isFinalNode = currentNodeID == bytes32(RLP_NULL); bool isFinalNode = currentNodeID == bytes32(RLP_NULL);
return (pathLength, Lib_BytesUtils.slice(key, currentKeyIndex), isFinalNode); return (pathLength, Lib_BytesUtils.slice(key, currentKeyIndex), isFinalNode, currentNode);
} }
/** /**
...@@ -579,7 +534,8 @@ library Lib_MerkleTrie { ...@@ -579,7 +534,8 @@ library Lib_MerkleTrie {
private private
pure pure
returns ( returns (
bytes32 _nodeID bytes32 _nodeID,
uint length
) )
{ {
bytes memory nodeID; bytes memory nodeID;
...@@ -592,7 +548,7 @@ library Lib_MerkleTrie { ...@@ -592,7 +548,7 @@ library Lib_MerkleTrie {
nodeID = Lib_RLPReader.readBytes(_node); nodeID = Lib_RLPReader.readBytes(_node);
} }
return Lib_BytesUtils.toBytes32(nodeID); return (Lib_BytesUtils.toBytes32(nodeID), _node.length);
} }
/** /**
......
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