Skip to content

Commit

Permalink
checkpoint≈
Browse files Browse the repository at this point in the history
  • Loading branch information
dmfxyz committed Mar 20, 2024
1 parent f75f8d5 commit 6a3f9fc
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 32 deletions.
52 changes: 52 additions & 0 deletions differential_testing/scripts/oz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { StandardMerkleTree } from "@openzeppelin/merkle-tree";
import fs from "fs";

let zero_address = "0x0000000000000000000000000000000000000000"
let alice = "0x328809Bc894f92807417D2dAD6b7C998c1aFdac6"
let bob = "0x1D96F2f6BeF1202E4Ce1Ff6Dad0c2CB002861d3e"
let eve = "0xa959355654849CbEAbBf65235f8235833b9e031D"
let james = "0xA5817DBBE42fa5B457943E5Ad5e74910F65f5EFC"
let mallory = "0x8707f238936c12c309bfc2B9959C35828AcFc512"
let janice = "0x07b76d8ab8736f096D8346b559b76D5483dE8223"

let values = [[alice, zero_address], [bob, zero_address], [eve, zero_address]]
const tree = StandardMerkleTree.of(values, ["address", "address"], { sortLeaves: false })
console.log(tree.render())
console.log(tree.root)
console.log("Hello, world!")

//3
// 0) 10d772be44576d1c88a8039062ea3cd6163862f2deca298213e35b18cbd85490
// ├─ 1) 1f5affa775ec35a292a1007fbd25c4dad11b1ecf29c70ba165f7d790411a7dc2
// │ ├─ 3) afeb0ccce3b008968e7ffbfc7482d85551f5f90e713b8441449d808d25e9cc64
// │ └─ 4) cf0e8c2fa63ea2b3726dbea696df21baec00c4cdb37deeab03a15f190659544c
// └─ 2) 7f37e8358c0d3959e3e800344c357551753c24a55d5d987cef461e933b137a02
// 0x10d772be44576d1c88a8039062ea3cd6163862f2deca298213e35b18cbd85490


// 5
// 0) e0c1356e7bc3ae6e7a3f1d1db657fdd88f043cf540e8ef3ca1a7f22fac936703
// ├─ 1) 31402893ac96730ca199f7679e2472bce6b60f8c88afdd7f487033238a375af0
// │ ├─ 3) 1f5affa775ec35a292a1007fbd25c4dad11b1ecf29c70ba165f7d790411a7dc2
// │ │ ├─ 7) afeb0ccce3b008968e7ffbfc7482d85551f5f90e713b8441449d808d25e9cc64 // bob
// │ │ └─ 8) cf0e8c2fa63ea2b3726dbea696df21baec00c4cdb37deeab03a15f190659544c // alice
// │ └─ 4) cac6fc160d04af9e1fd8f0c71cf8d333453b39589d3846524462ee7737bd728d // mallory
// └─ 2) 794c8357546dd238e25fde7680d946e1eb4ba92397e9931ca97b5c64ca9775a3
// ├─ 5) de1820ee7887b5ae922f14f423bb2e7a6595e423f1a0c0a82a2ddeed09a92a25 // james
// └─ 6) 7f37e8358c0d3959e3e800344c357551753c24a55d5d987cef461e933b137a02 // eve
// 0xe0c1356e7bc3ae6e7a3f1d1db657fdd88f043cf540e8ef3ca1a7f22fac936703


// 6
// 0) 82e830e6e22a0b487eac4fc6868317898b8c2131d21821dd2c8d723306afeb0a
// ├─ 1) 1a77f6ba079228404f8a434f3d62289a262f4e78d16a8be5473b044515120deb
// │ ├─ 3) 794c8357546dd238e25fde7680d946e1eb4ba92397e9931ca97b5c64ca9775a3
// │ │ ├─ 7) de1820ee7887b5ae922f14f423bb2e7a6595e423f1a0c0a82a2ddeed09a92a25
// │ │ └─ 8) 7f37e8358c0d3959e3e800344c357551753c24a55d5d987cef461e933b137a02
// │ └─ 4) 1f5affa775ec35a292a1007fbd25c4dad11b1ecf29c70ba165f7d790411a7dc2
// │ ├─ 9) afeb0ccce3b008968e7ffbfc7482d85551f5f90e713b8441449d808d25e9cc64
// │ └─ 10) cf0e8c2fa63ea2b3726dbea696df21baec00c4cdb37deeab03a15f190659544c
// └─ 2) eeb03bc48fd388de1b111ab743c9a72e8a4d80c3619b70901d155c40880d6eae
// ├─ 5) 1688f29243f54ddded6dedcbbc8dae64ef939f0b967d0fa56a6e5938febb5f79
// └─ 6) cac6fc160d04af9e1fd8f0c71cf8d333453b39589d3846524462ee7737bd728d
// 0x82e830e6e22a0b487eac4fc6868317898b8c2131d21821dd2c8d723306afeb0a
57 changes: 57 additions & 0 deletions src/CompleteMerkle.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./common/MurkyBase.sol";

/// @notice Nascent, simple, kinda efficient (and improving!) Merkle proof generator and verifier
/// @author dmfxyz
/// @dev Note Generic Merkle Tree
contract CompleteMerkle is MurkyBase {
/**
*
* HASHING FUNCTION *
*
*/

/// ascending sort and concat prior to hashing
function hashLeafPairs(bytes32 left, bytes32 right) public pure override returns (bytes32 _hash) {
assembly {
switch lt(left, right)
case 0 {
mstore(0x0, right)
mstore(0x20, left)
}
default {
mstore(0x0, left)
mstore(0x20, right)
}
_hash := keccak256(0x0, 0x40)
_hash := keccak256(0x0, 0x40)
}
}

function _getTree(bytes32[] memory data) public pure returns (bytes32[] memory) {
require(data.length > 1, "won't generate root for single leaf");
bytes32[] memory tree = new bytes32[](2 * data.length - 1);
assembly {
//let pos := mload(tree)
let iter := mload(data)
let y := add(sub(mload(tree), iter), 1)
for {let i := add(data, mul(iter, 0x20))} gt(i, iter) { i := sub(i, 0x20)} {
mstore(add(tree, mul(y, 0x20)), mload(i))
y := add(y, 1)

}
}
return tree;
}

function getRoot(bytes32[] memory data) public pure override returns (bytes32) {
bytes32[] memory tree = _getTree(data);
for (uint256 i = tree.length - 1; i > 0; i -= 2) {
uint256 posToWrite = (i - 1) / 2;
tree[posToWrite] = hashLeafPairs(tree[i - 1], tree[i]);
}
return tree[0];
}
}
2 changes: 1 addition & 1 deletion src/common/MurkyBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ abstract contract MurkyBase {
* PROOF GENERATION *
*
*/
function getRoot(bytes32[] memory data) public pure returns (bytes32) {
function getRoot(bytes32[] memory data) public pure virtual returns (bytes32) {
require(data.length > 1, "won't generate root for single leaf");
while (data.length > 1) {
data = hashLevel(data);
Expand Down
102 changes: 71 additions & 31 deletions src/test/OZMerkle.t.sol
Original file line number Diff line number Diff line change
@@ -1,42 +1,45 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;

import "../OZMerkle.sol";
import "../Merkle.sol";
import "../CompleteMerkle.sol";
import "forge-std/Test.sol";
import "openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol";
import "openzeppelin-contracts/contracts/utils/Strings.sol";
import "forge-std/console.sol";

contract ContractTest is Test {
OZMerkle m;
Merkle m;
CompleteMerkle cm;

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

function testHashes(bytes32 left, bytes32 right) public {
bytes32 hAssem = m.hashLeafPairs(left, right);
bytes memory packed;
if (left <= right) {
packed = abi.encodePacked(left, right);
} else {
if (right == bytes32(0x0)) {
packed = abi.encodePacked(left, left);
} else {
packed = abi.encodePacked(right, left);
}
}
bytes32 hNaive = keccak256(packed);
assertEq(hAssem, hNaive);
}
// function testHashes(bytes32 left, bytes32 right) public {
// bytes32 hAssem = m.hashLeafPairs(left, right);
// bytes memory packed;
// if (left <= right) {
// packed = abi.encodePacked(left, right);
// } else {
// if (right == bytes32(0x0)) {
// packed = abi.encodePacked(left, left);
// } else {
// packed = abi.encodePacked(right, left);
// }
// }
// bytes32 hNaive = keccak256(packed);
// assertEq(hAssem, hNaive);
// }

function testHashesDuplicateOddLeaf(bytes32 left) public {
bytes32 right = bytes32(0x0);
bytes32 hAssem = m.hashLeafPairs(left, right);
bytes memory packed = abi.encodePacked(left, left);
bytes32 hNaive = keccak256(packed);
assertEq(hAssem, hNaive);
}
// function testHashesDuplicateOddLeaf(bytes32 left) public {
// bytes32 right = bytes32(0x0);
// bytes32 hAssem = m.hashLeafPairs(left, right);
// bytes memory packed = abi.encodePacked(left, left);
// bytes32 hNaive = keccak256(packed);
// assertEq(hAssem, hNaive);
// }

// function testGenerateProof(bytes32[] memory data, uint256 node) public {
// vm.assume(data.length > 1);
Expand All @@ -47,6 +50,7 @@ contract ContractTest is Test {

// bytes32 rollingHash = valueToProve;
// for (uint256 i = 0; i < proof.length; ++i) {

// rollingHash = m.hashLeafPairs(rollingHash, proof[i]);
// }
// assertEq(rollingHash, root);
Expand Down Expand Up @@ -100,13 +104,49 @@ contract ContractTest is Test {
// return true;
// }

function testExampleIssue() public {
function testRootGenerationBasicExampleLen3() public {
bytes32[] memory data = new bytes32[](3);
data[0] = 0xcf0e8c2fa63ea2b3726dbea696df21baec00c4cdb37deeab03a15f190659544c; // sha3(alice, address(0x0))
data[1] = 0xafeb0ccce3b008968e7ffbfc7482d85551f5f90e713b8441449d808d25e9cc64; // sha3(bob, address(0x0))
data[2] = 0x7f37e8358c0d3959e3e800344c357551753c24a55d5d987cef461e933b137a02; // sha3(charlie, address(0x0))
bytes32[] memory tree = cm._getTree(data);
bytes32 root = cm.getRoot(data);
assertEq(root, bytes32(0x10d772be44576d1c88a8039062ea3cd6163862f2deca298213e35b18cbd85490));
}

function testRootGenerationBasicExampleLen5() public {
bytes32[] memory data = new bytes32[](5);

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;
bytes32 elem;
assembly {
elem := mload(data)
}
emit log_bytes32((elem));
bytes32[] memory tree = cm._getTree(data);
// for (uint256 i = 0; i < tree.length; ++i) {
// emit log_bytes32(tree[i]);
// }
bytes32 root = cm.getRoot(data);
assertEq(root, bytes32(0xe0c1356e7bc3ae6e7a3f1d1db657fdd88f043cf540e8ef3ca1a7f22fac936703));
}

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 = cm._getTree(data);
bytes32 root = cm.getRoot(data);
assertEq(root, bytes32(0x82e830e6e22a0b487eac4fc6868317898b8c2131d21821dd2c8d723306afeb0a));

data[0] = 0x68a111560bac738d202dd1cb92633026df6d2022f075a73497bd57bcebe5a1b8;
data[1] = 0x4db3d4123a675f46edfdaf2b994d2862142194936b7429376b372e6c8cf46b8b;
data[2] = 0xd1421691e1b6f8c16692c05ca6df90c00f07e14907be5369c4589790cd51d158;
bytes32 root = m.getRoot(data);
emit log_bytes32(root);
}
}

0 comments on commit 6a3f9fc

Please sign in to comment.