forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Qi Zhou
committed
May 29, 2024
1 parent
5526db5
commit 3b19488
Showing
2 changed files
with
139 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
library LibDA { | ||
uint256 constant DA_TYPE_CALLDATA = 0; | ||
uint256 constant DA_TYPE_EIP4844 = 1; | ||
|
||
function getClaimsHash(uint256 daType, uint256 nelemebts, bytes memory data) internal view returns (bytes32 root) { | ||
if (daType == DA_TYPE_EIP4844) { | ||
// TODO: may specify which blob? | ||
root = blobhash(0); | ||
require(root != bytes32(0), "root must not zero"); | ||
return root; | ||
} | ||
|
||
require(daType == DA_TYPE_CALLDATA, "unsupported DA type"); | ||
require(nelemebts * 32 == data.length, "data must 32 * n"); | ||
require(nelemebts > 0, "data must not empty"); | ||
|
||
while (nelemebts != 1) { | ||
for (uint256 i = 0 ; i < nelemebts / 2; i++) { | ||
bytes32 hash; | ||
uint256 roff = i * 32 * 2; | ||
uint256 woff = i * 32; | ||
assembly { | ||
hash := keccak256(add(add(data, 0x20), roff), 64) | ||
mstore(add(add(data, 0x20), woff), hash) | ||
} | ||
} | ||
|
||
// directly copy the last item | ||
if (nelemebts % 2 == 1) { | ||
uint256 roff = (nelemebts - 1) * 32; | ||
uint256 woff = (nelemebts / 2) * 32; | ||
bytes32 hash; | ||
assembly { | ||
hash := mload(add(add(data, 0x20), roff)) | ||
mstore(add(add(data, 0x20), woff), hash) | ||
} | ||
} | ||
|
||
nelemebts = (nelemebts + 1) / 2; | ||
} | ||
|
||
assembly { | ||
root := mload(add(data, 0x20)) | ||
} | ||
} | ||
|
||
function verifyClaimHash(uint256 daType, bytes32 root, uint256 nelements, uint256 idx, bytes32 claimHash, bytes memory proof) internal pure { | ||
require(daType == 0, "unsupported DA type"); | ||
bytes32 hash = claimHash; | ||
uint256 proofOff = 0; | ||
while (nelements != 1) { | ||
if (idx != nelements - 1 || nelements % 2 == 0) { | ||
bytes32 pHash; | ||
require(proofOff < proof.length, "no enough proof"); | ||
assembly { | ||
pHash := mload(add(add(proof, 0x20), proofOff)) | ||
} | ||
proofOff += 32; | ||
if (idx % 2 == 0) { | ||
hash = keccak256(abi.encode(hash, pHash)); | ||
} else { | ||
hash = keccak256(abi.encode(pHash, hash)); | ||
} | ||
} | ||
nelements = (nelements + 1) / 2; | ||
idx = idx / 2; | ||
} | ||
require(root == hash, "proof failed"); | ||
} | ||
} | ||
|
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,65 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.15; | ||
|
||
import { Test } from "forge-std/Test.sol"; | ||
import { LibDA } from "src/dispute/lib/LibDA.sol"; | ||
|
||
/// @notice Tests for `LibDA` | ||
contract LibDA_Test is Test { | ||
function test_calldata_one() public view { | ||
bytes32 root; | ||
bytes memory input = "00000000000000000000000000000000"; | ||
root = LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 1, input); | ||
assertEq(root, bytes32("00000000000000000000000000000000")); | ||
input = "10000000000000000000000000000001"; | ||
root = LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 1, input); | ||
assertEq(root, bytes32("10000000000000000000000000000001")); | ||
} | ||
|
||
function test_calldata_two() public view { | ||
bytes32 root; | ||
bytes memory input = "0000000000000000000000000000000010000000000000000000000000000001"; | ||
root = LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 2, input); | ||
assertEq(root, keccak256(abi.encode(bytes32("00000000000000000000000000000000"), bytes32("10000000000000000000000000000001")))); | ||
} | ||
|
||
function test_calldata_three() public view { | ||
bytes32 root; | ||
bytes memory input = "000000000000000000000000000000001000000000000000000000000000000120000000000000000000000000000002"; | ||
root = LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 3, input); | ||
assertEq(root, keccak256(abi.encode( | ||
keccak256(abi.encode(bytes32("00000000000000000000000000000000"), bytes32("10000000000000000000000000000001"))), | ||
bytes32("20000000000000000000000000000002") | ||
))); | ||
} | ||
|
||
function test_calldata_seven() public view { | ||
bytes32 root; | ||
bytes memory input = "00000000000000000000000000000000100000000000000000000000000000012000000000000000000000000000000230000000000000000000000000000003400000000000000000000000000000045000000000000000000000000000000560000000000000000000000000000006"; | ||
root = LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 7, input); | ||
assertEq(root, | ||
keccak256(abi.encode( | ||
keccak256(abi.encode( | ||
keccak256(abi.encode( | ||
bytes32("00000000000000000000000000000000"), | ||
bytes32("10000000000000000000000000000001"))), | ||
keccak256(abi.encode( | ||
bytes32("20000000000000000000000000000002"), | ||
bytes32("30000000000000000000000000000003"))))), | ||
keccak256(abi.encode( | ||
keccak256(abi.encode( | ||
bytes32("40000000000000000000000000000004"), | ||
bytes32("50000000000000000000000000000005"))), | ||
bytes32("60000000000000000000000000000006"))) | ||
))); | ||
} | ||
|
||
function test_calldata_prove_three() public view { | ||
bytes32 root; | ||
bytes memory input = "000000000000000000000000000000001000000000000000000000000000000120000000000000000000000000000002"; | ||
root = LibDA.getClaimsHash(LibDA.DA_TYPE_CALLDATA, 3, input); | ||
LibDA.verifyClaimHash(LibDA.DA_TYPE_CALLDATA, root, 3, 0, "00000000000000000000000000000000", "1000000000000000000000000000000120000000000000000000000000000002"); | ||
LibDA.verifyClaimHash(LibDA.DA_TYPE_CALLDATA, root, 3, 1, "10000000000000000000000000000001", "0000000000000000000000000000000020000000000000000000000000000002"); | ||
LibDA.verifyClaimHash(LibDA.DA_TYPE_CALLDATA, root, 3, 2, "20000000000000000000000000000002", bytes.concat(keccak256(abi.encode(bytes32("00000000000000000000000000000000"), bytes32("10000000000000000000000000000001"))))); | ||
} | ||
} |