-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/master' into feat/dispute-kit-fo…
…rest
- Loading branch information
Showing
7 changed files
with
2,268 additions
and
1,841 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
/** | ||
* @authors: [@shotaronowhere] | ||
* @reviewers: [] | ||
* @auditors: [] | ||
* @bounties: [] | ||
* @deployments: [] | ||
*/ | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
/** | ||
* @title MerkleProof | ||
* @author Shotaro N. - <shawtarohgn@gmail.com> | ||
* @dev A set of funcitons to verify merkle proofs. | ||
*/ | ||
contract MerkleProof { | ||
/** @dev Validates membership of leaf in merkle tree with merkle proof. | ||
* @param proof The merkle proof. | ||
* @param leaf The leaf to validate membership in merkle tree. | ||
* @param merkleRoot The root of the merkle tree. | ||
*/ | ||
function validateProof( | ||
bytes32[] memory proof, | ||
bytes32 leaf, | ||
bytes32 merkleRoot | ||
) internal pure returns (bool) { | ||
return (merkleRoot == calculateRoot(proof, leaf)); | ||
} | ||
|
||
/** @dev Validates membership of leaf in merkle tree with merkle proof. | ||
* @param proof The merkle proof. | ||
* @param data The data to validate membership in merkle tree. | ||
* @param merkleRoot The root of the merkle tree. | ||
*/ | ||
function validateProof( | ||
bytes32[] memory proof, | ||
bytes memory data, | ||
bytes32 merkleRoot | ||
) public pure returns (bool) { | ||
return validateProof(proof, sha256(data), merkleRoot); | ||
} | ||
|
||
/** @dev Calculates merkle root from proof. | ||
* @param proof The merkle proof. | ||
* @param leaf The leaf to validate membership in merkle tree.. | ||
*/ | ||
function calculateRoot(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { | ||
uint256 proofLength = proof.length; | ||
require(proofLength <= 64, "Invalid Proof"); | ||
bytes32 h = leaf; | ||
for (uint256 i = 0; i < proofLength; i++) { | ||
bytes32 proofElement = proof[i]; | ||
// effecient hash | ||
if (proofElement > h) | ||
assembly { | ||
mstore(0x00, h) | ||
mstore(0x20, proofElement) | ||
h := keccak256(0x00, 0x40) | ||
} | ||
else | ||
assembly { | ||
mstore(0x00, proofElement) | ||
mstore(0x20, h) | ||
h := keccak256(0x00, 0x40) | ||
} | ||
} | ||
return h; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
/** | ||
* @authors: [@shotaronowhere] | ||
* @reviewers: [] | ||
* @auditors: [] | ||
* @bounties: [] | ||
* @deployments: [] | ||
*/ | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
/** | ||
* @title MerkleTreeHistory | ||
* @author Shotaro N. - <shawtarohgn@gmail.com> | ||
* @dev An efficient append only merkle tree with history. | ||
*/ | ||
contract MerkleTreeHistory { | ||
// ***************************** // | ||
// * Storage * // | ||
// ***************************** // | ||
|
||
// merkle tree representation | ||
// supports 2^64 messages. | ||
bytes32[64] public branch; | ||
uint256 public count; | ||
|
||
// block number => merkle root history | ||
mapping(uint256 => bytes32) private history; | ||
|
||
// ************************************* // | ||
// * State Modifiers * // | ||
// ************************************* // | ||
|
||
/** @dev Append data into merkle tree. | ||
* `O(log(n))` where | ||
* `n` is the number of leaves. | ||
* Note: Although each insertion is O(log(n)), | ||
* Complexity of n insertions is O(n). | ||
* @param data The data to insert in the merkle tree. | ||
*/ | ||
function append(bytes memory data) public { | ||
// Differentiate leaves from interior nodes with different | ||
// hash functions to prevent 2nd order pre-image attack. | ||
// https://flawed.net.nz/2018/02/21/attacking-merkle-trees-with-a-second-preimage-attack/ | ||
bytes32 leaf = sha256(data); | ||
uint256 size = count + 1; | ||
count = size; | ||
uint256 hashBitField = (size ^ (size - 1)) & size; | ||
uint256 height; | ||
while ((hashBitField & 1) == 0) { | ||
bytes32 node = branch[height]; | ||
if (node > leaf) | ||
assembly { | ||
// effecient hash | ||
mstore(0x00, leaf) | ||
mstore(0x20, node) | ||
leaf := keccak256(0x00, 0x40) | ||
} | ||
else | ||
assembly { | ||
// effecient hash | ||
mstore(0x00, node) | ||
mstore(0x20, leaf) | ||
leaf := keccak256(0x00, 0x40) | ||
} | ||
hashBitField /= 2; | ||
height = height + 1; | ||
} | ||
branch[height] = leaf; | ||
} | ||
|
||
/** @dev Saves the merkle root state in history and resets. | ||
* `O(log(n))` where | ||
* `n` is the number of leaves. | ||
*/ | ||
function reset() internal { | ||
history[block.number] = getMerkleRoot(); | ||
count = 0; | ||
} | ||
|
||
/** @dev Gets the merkle root history | ||
* `O(log(n))` where | ||
* `n` is the number of leaves. | ||
* @param blocknumber requested blocknumber. | ||
*/ | ||
function getMerkleRootHistory(uint256 blocknumber) public view returns (bytes32) { | ||
if (blocknumber == block.number) return getMerkleRoot(); | ||
|
||
return history[blocknumber]; | ||
} | ||
|
||
/** @dev Gets the current merkle root. | ||
* `O(log(n))` where | ||
* `n` is the number of leaves. | ||
*/ | ||
function getMerkleRoot() public view returns (bytes32) { | ||
bytes32 node; | ||
uint256 size = count; | ||
uint256 height = 0; | ||
bool isFirstHash = true; | ||
while (size > 0) { | ||
if ((size & 1) == 1) { | ||
// avoid redundant calculation | ||
if (isFirstHash) { | ||
node = branch[height]; | ||
isFirstHash = false; | ||
} else { | ||
bytes32 hash = branch[height]; | ||
// effecient hash | ||
if (hash > node) | ||
assembly { | ||
mstore(0x00, node) | ||
mstore(0x20, hash) | ||
node := keccak256(0x00, 0x40) | ||
} | ||
else | ||
assembly { | ||
mstore(0x00, hash) | ||
mstore(0x20, node) | ||
node := keccak256(0x00, 0x40) | ||
} | ||
} | ||
} | ||
size /= 2; | ||
height++; | ||
} | ||
return node; | ||
} | ||
} |
Oops, something went wrong.