Skip to content

Commit

Permalink
rely on MurkyBase for verifyProof; update testing dependencies; --via…
Browse files Browse the repository at this point in the history
…-ir, optimize in pipeline
  • Loading branch information
dmfxyz committed Mar 26, 2024
1 parent 4fd7baf commit 37f31fb
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 78 deletions.
2 changes: 1 addition & 1 deletion lib/openzeppelin-contracts
40 changes: 3 additions & 37 deletions src/CompleteMerkle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ contract CompleteMerkle is MurkyBase {
* HASHING FUNCTION *
*
*/
/// @notice WARNING: LEFT FOR REFERENCE ONLY, NOT USED BY CompleteMerkle (all hashing functions are written in inline).
/// @dev WARNING: LEFT FOR REFERENCE ONLY, NOT USED BY CompleteMerkle (all hashing functions are written in inline).
/// @notice Hash function used when verifying proofs.
/// @dev WARNING: This method is only used by verifyProof (inherited from MurkyBase.sol).
// If modified, you **MUST** ensure the inline assembly methods in buildTree and getProof are modified to match.
function hashLeafPairs(bytes32 left, bytes32 right) public pure override returns (bytes32 _hash) {
assembly {
switch lt(left, right)
Expand Down Expand Up @@ -84,41 +85,6 @@ contract CompleteMerkle is MurkyBase {
return tree[0];
}

/// @notice Verifies a merkle proof and value given the expected root
/// @param root The merkle root expected, generated by getRoot function
/// @param proof The inclusion proof, generated by getProof function
/// @param valueToProve The value you are try to prove inclusion of
/// @return valid bool indicating whether the inclusion proof and value are valid or not
function verifyProof(bytes32 root, bytes32[] memory proof, bytes32 valueToProve)
external
pure
override
returns (bool)
{
assembly {
function hash_leafs(left, right) -> _hash {
switch lt(left, right)
case 0 {
mstore(0x0, right)
mstore(0x20, left)
}
default {
mstore(0x0, left)
mstore(0x20, right)
}
_hash := keccak256(0x0, 0x40)
}
let roll := mload(0x40)
mstore(roll, valueToProve)
let len := mload(proof)
for { let i := 0 } lt(i, len) { i := add(i, 1) } {
mstore(roll, hash_leafs(mload(roll), mload(add(add(proof, 0x20), mul(i, 0x20)))))
}
mstore(roll, eq(mload(roll), root))
return(roll, 0x20)
}
}

/// @notice Generates proof for given set of data and target index
/// @dev Note that this returns a dynamic memory array constructed via assembly.
/// This may cause issues with certain REPL interpreters (e.g. Chisel).
Expand Down
48 changes: 14 additions & 34 deletions src/test/CompleteMerkle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ import "openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol";
import "openzeppelin-contracts/contracts/utils/Strings.sol";
import "forge-std/console.sol";

contract CompleteMerkleTest is Test {
contract GasComparisonTests is Test {
CompleteMerkle m;
Merkle GAS_COMP_MERKLE;

function setUp() public {
m = new CompleteMerkle();
GAS_COMP_MERKLE = new Merkle();
}

function testGenerateProof(bytes32[] memory data, uint256 node) public {
function testGenerateProof(bytes32[] memory data, uint256 node) public view {
vm.assume(data.length > 1);
vm.assume(node < data.length);
bytes32 root = m.getRoot(data);
Expand All @@ -31,7 +30,7 @@ contract CompleteMerkleTest is Test {
assertEq(rollingHash, root);
}

function testVerifyProofSucceedsForGoodValue(bytes32[] memory data, uint256 node) public {
function testVerifyProofSucceedsForGoodValue(bytes32[] memory data, uint256 node) public view {
vm.assume(data.length > 1);
vm.assume(node < data.length);
bytes32 root = m.getRoot(data);
Expand All @@ -40,7 +39,7 @@ contract CompleteMerkleTest is Test {
assertTrue(m.verifyProof(root, proof, valueToProve));
}

function testVerifyProofFailsForBadValue(bytes32[] memory data, bytes32 valueToProve, uint256 node) public {
function testVerifyProofFailsForBadValue(bytes32[] memory data, bytes32 valueToProve, uint256 node) public view {
vm.assume(data.length > 1);
vm.assume(node < data.length);
vm.assume(valueNotInArray(data, valueToProve));
Expand All @@ -49,7 +48,16 @@ contract CompleteMerkleTest is Test {
assertFalse(m.verifyProof(root, proof, valueToProve));
}

// function testVerifyProofOzForGasComparison(bytes32[] memory data, uint256 node) public {
function testVerifyProofOzForGasComparison(bytes32[] memory data, uint256 node) public view {
vm.assume(data.length > 1);
vm.assume(node < data.length);
bytes32 root = m.getRoot(data);
bytes32[] memory proof = m.getProof(data, node);
bytes32 valueToProve = data[node];
assertTrue(MerkleProof.verify(proof, root, valueToProve));
}

// function testVerifyProofOzForGasComparison(bytes32[] memory data, uint256 node) public view {
// vm.assume(data.length > 1);
// vm.assume(node < data.length);
// bytes32 root = m.getRoot(data);
Expand Down Expand Up @@ -78,32 +86,4 @@ contract CompleteMerkleTest is Test {
}
return true;
}

function testRootGenerationBasicExampleLen6() public {
bytes32[] memory data = new bytes32[](6);

data[0] = 0xcf0e8c2fa63ea2b3726dbea696df21baec00c4cdb37deeab03a15f190659544c; // sha3(alice, address(0x0))
data[1] = 0xafeb0ccce3b008968e7ffbfc7482d85551f5f90e713b8441449d808d25e9cc64; // sha3(bob, address(0x0))
data[2] = 0x7f37e8358c0d3959e3e800344c357551753c24a55d5d987cef461e933b137a02; // sha3(charlie, address(0x0))
data[3] = 0xde1820ee7887b5ae922f14f423bb2e7a6595e423f1a0c0a82a2ddeed09a92a25;
data[4] = 0xcac6fc160d04af9e1fd8f0c71cf8d333453b39589d3846524462ee7737bd728d;
data[5] = 0x1688f29243f54ddded6dedcbbc8dae64ef939f0b967d0fa56a6e5938febb5f79;
//bytes32[] memory tree = m._getTree(data);
bytes32 root = m.getRoot(data);
assertEq(root, root);
}

function testRootGenerationRegularMerkle6ForGas() public {
bytes32[] memory data = new bytes32[](6);

data[0] = 0xcf0e8c2fa63ea2b3726dbea696df21baec00c4cdb37deeab03a15f190659544c; // sha3(alice, address(0x0))
data[1] = 0xafeb0ccce3b008968e7ffbfc7482d85551f5f90e713b8441449d808d25e9cc64; // sha3(bob, address(0x0))
data[2] = 0x7f37e8358c0d3959e3e800344c357551753c24a55d5d987cef461e933b137a02; // sha3(charlie, address(0x0))
data[3] = 0xde1820ee7887b5ae922f14f423bb2e7a6595e423f1a0c0a82a2ddeed09a92a25;
data[4] = 0xcac6fc160d04af9e1fd8f0c71cf8d333453b39589d3846524462ee7737bd728d;
data[5] = 0x1688f29243f54ddded6dedcbbc8dae64ef939f0b967d0fa56a6e5938febb5f79;
//bytes32[] memory tree = m._getTree(data);
bytes32 root = GAS_COMP_MERKLE.getRoot(data);
assertEq(root, root);
}
}
6 changes: 3 additions & 3 deletions src/test/StandardInput.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ contract StandardizedInputTest is Test {
}
}

function testXorkleVerifyProofStandard() public {
function testXorkleVerifyProofStandard() public view {
bytes32[] memory _data = _getData();
bytes32 root = x.getRoot(_data);
for (uint256 i = 0; i < leaves.length; ++i) {
Expand All @@ -46,7 +46,7 @@ contract StandardizedInputTest is Test {
}
}

function testMerkleVerifyProofStandard() public {
function testMerkleVerifyProofStandard() public view {
bytes32[] memory _data = _getData();
bytes32 root = m.getRoot(_data);
for (uint256 i = 0; i < leaves.length; ++i) {
Expand All @@ -62,7 +62,7 @@ contract StandardizedInputTest is Test {
}
}

function testCompleteMerkleVerifyProofStandard() public {
function testCompleteMerkleVerifyProofStandard() public view {
bytes32[] memory _data = _getData();
bytes32 root = cm.getRoot(_data);
for (uint256 i = 0; i < leaves.length; ++i) {
Expand Down
3 changes: 1 addition & 2 deletions src/test/Xorkle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ pragma solidity ^0.8.4;
import "../Xorkle.sol";
import "forge-std/Test.sol";

contract ContractTest is DSTest {
contract ContractTest is Test {
Xorkle m;
Vm vm = Vm(HEVM_ADDRESS);

function setUp() public {
m = new Xorkle();
Expand Down

0 comments on commit 37f31fb

Please sign in to comment.