Skip to content

Commit

Permalink
add LibDA.sol
Browse files Browse the repository at this point in the history
  • Loading branch information
Qi Zhou committed May 29, 2024
1 parent 5526db5 commit 3b19488
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
74 changes: 74 additions & 0 deletions packages/contracts-bedrock/src/dispute/lib/LibDA.sol
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");
}
}

65 changes: 65 additions & 0 deletions packages/contracts-bedrock/test/dispute/lib/LibDA.t.sol
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")))));
}
}

0 comments on commit 3b19488

Please sign in to comment.