Skip to content

Commit

Permalink
Merge branch 'kl/sync-layer-reorg' into bh/full-merkle-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
benceharomi committed Jun 28, 2024
2 parents abb6685 + 4279113 commit beaa0a6
Show file tree
Hide file tree
Showing 37 changed files with 1,265 additions and 983 deletions.
2 changes: 1 addition & 1 deletion contracts-review-prep.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ For clarity, we only developed a framework, the exact logic for custom tokens an

### Major changes

In order to achieve it, we separated the liquidity managing logic from the Shared Bridges to `Asset Handlers`. The basic cases will be handled by `Native Token Vaults`, which are handling all of the standard `ERC20 tokens`, as well as `ETH`.
In order to achieve it, we separated the liquidity managing logic from the Shared Bridge to `Asset Handlers`. The basic cases will be handled by `Native Token Vaults`, which are handling all of the standard `ERC20 tokens`, as well as `ETH`.

### New concepts

Expand Down
2 changes: 2 additions & 0 deletions da-contracts/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CHAIN_ETH_NETWORK=hardhat
ETH_CLIENT_WEB3_URL=http://127.0.0.1:8545
92 changes: 92 additions & 0 deletions da-contracts/contracts/CalldataDA.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

// solhint-disable gas-custom-errors, reason-string

// TODO: maybe move it here
import {BLOB_SIZE_BYTES} from "./DAUtils.sol";

uint256 constant BLOBS_SUPPORTED = 6;

/// @notice Contract that contains the functionality for process the calldata DA.
/// @dev The expected l2DAValidator that should be used with it `RollupL2DAValidator`.
abstract contract CalldataDA {
/// @notice Parses the input that the l2 Da validator has provided to the contract.
/// @param _l2DAValidatorOutputHash The hash of the output of the L2 DA validator.
/// @param _maxBlobsSupported The maximal number of blobs supported by the chain.
/// @param _operatorDAInput The DA input by the operator provided on L1.
function _processL2RollupDAValidatorOutputHash(
bytes32 _l2DAValidatorOutputHash,
uint256 _maxBlobsSupported,
bytes calldata _operatorDAInput
)
internal
pure
returns (
bytes32 stateDiffHash,
bytes32 fullPubdataHash,
bytes32[] memory blobsLinearHashes,
uint256 blobsProvided,
bytes calldata l1DaInput
)
{
// The preimage under the hash `l2DAValidatorOutputHash` is expected to be in the following format:
// - First 32 bytes are the hash of the uncompressed state diff.
// - Then, there is a 32-byte hash of the full pubdata.
// - Then, there is the 1-byte number of blobs published.
// - Then, there are linear hashes of the published blobs, 32 bytes each.

// Check that it accommodates enough pubdata for the state diff hash, hash of pubdata + the number of blobs.
require(_operatorDAInput.length >= 32 + 32 + 1, "too small");

stateDiffHash = bytes32(_operatorDAInput[:32]);
fullPubdataHash = bytes32(_operatorDAInput[32:64]);
blobsProvided = uint256(uint8(_operatorDAInput[64]));

require(blobsProvided <= _maxBlobsSupported, "invalid number of blobs");

// Note that the API of the contract requires that the returned blobs linear hashes have length of
// the `_maxBlobsSupported`
blobsLinearHashes = new bytes32[](_maxBlobsSupported);

require(_operatorDAInput.length >= 65 + 32 * blobsProvided, "invalid blobs hashes");

uint256 ptr = 65;

for (uint256 i = 0; i < blobsProvided; ++i) {
// Take the 32 bytes of the blob linear hash
blobsLinearHashes[i] = bytes32(_operatorDAInput[ptr:ptr + 32]);
ptr += 32;
}

// Now, we need to double check that the provided input was indeed retutned by the L2 DA validator.
require(keccak256(_operatorDAInput[:ptr]) == _l2DAValidatorOutputHash, "invalid l2 DA output hash");

// The rest of the output were provided specifically by the operator
l1DaInput = _operatorDAInput[ptr:];
}

/// @notice Verify that the calldata DA was correctly provided.
/// todo: better doc comments
function _processCalldataDA(
uint256 _blobsProvided,
bytes32 _fullPubdataHash,
uint256 _maxBlobsSupported,
bytes calldata _pubdataInput
) internal pure returns (bytes32[] memory blobCommitments, bytes calldata _pubdata) {
// We typically do not know whether we'll use calldata or blobs at the time when
// we start proving the batch. That's why the blob commitment for a single blob is still present in the case of calldata.

blobCommitments = new bytes32[](_maxBlobsSupported);

require(_blobsProvided == 1, "one one blob with calldata");

_pubdata = _pubdataInput[:_pubdataInput.length - 32];

// FIXME: allow larger lengths for SyncLayer-based chains.
require(_pubdata.length <= BLOB_SIZE_BYTES, "cz");
require(_fullPubdataHash == keccak256(_pubdata), "wp");
blobCommitments[0] = bytes32(_pubdataInput[_pubdataInput.length - 32:_pubdataInput.length]);
}
}
37 changes: 37 additions & 0 deletions da-contracts/contracts/DAUtils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

/// @dev Total number of bytes in a blob. Blob = 4096 field elements * 31 bytes per field element
/// @dev EIP-4844 defines it as 131_072 but we use 4096 * 31 within our circuits to always fit within a field element
/// @dev Our circuits will prove that a EIP-4844 blob and our internal blob are the same.
uint256 constant BLOB_SIZE_BYTES = 126_976;

/// @dev Enum used to determine the source of pubdata. At first we will support calldata and blobs but this can be extended.
enum PubdataSource {
Calldata,
Blob
}

/// @dev BLS Modulus value defined in EIP-4844 and the magic value returned from a successful call to the
/// point evaluation precompile
uint256 constant BLS_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513;

/// @dev Packed pubdata commitments.
/// @dev Format: list of: opening point (16 bytes) || claimed value (32 bytes) || commitment (48 bytes) || proof (48 bytes)) = 144 bytes
uint256 constant PUBDATA_COMMITMENT_SIZE = 144;

/// @dev Offset in pubdata commitment of blobs for claimed value
uint256 constant PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET = 16;

/// @dev Offset in pubdata commitment of blobs for kzg commitment
uint256 constant PUBDATA_COMMITMENT_COMMITMENT_OFFSET = 48;

/// @dev For each blob we expect that the commitment is provided as well as the marker whether a blob with such commitment has been published before.
uint256 constant BLOB_DA_INPUT_SIZE = PUBDATA_COMMITMENT_SIZE + 32;

/// @dev Address of the point evaluation precompile used for EIP-4844 blob verification.
address constant POINT_EVALUATION_PRECOMPILE_ADDR = address(0x0A);

/// @dev The address of the special smart contract that can send arbitrary length message as an L2 log
address constant L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR = address(0x8008);
34 changes: 34 additions & 0 deletions da-contracts/contracts/IL1DAValidator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;

struct L1DAValidatorOutput {
/// @dev The hash of the uncompressed state diff.
bytes32 stateDiffHash;
/// @dev The hashes of the blobs on L1. The array is dynamic to account for forward compatibility.
/// The length of it must be equal to `maxBlobsSupported`.
bytes32[] blobsLinearHashes;
/// @dev The commitments to the blobs on L1. The array is dynamic to account for forward compatibility.
/// Its length must be equal to the length of blobsLinearHashes.
/// @dev If the system supports more blobs than returned, the rest of the array should be filled with zeros.
bytes32[] blobsOpeningCommitments;
}

// TODO: require EIP165 support as this will allow changes for future compatibility.
interface IL1DAValidator {
/// @notice The function that checks the data availability for the given batch input.
/// @param chainId The chain id of the chain that is being committed.
/// @param l2DAValidatorOutputHash The hash of that was returned by the l2DAValidator.
/// @param operatorDAInput The DA input by the operator provided on L1.
/// @param maxBlobsSupported The maximal number of blobs supported by the chain.
/// We provide this value for future compatibility.
/// This is needed because the corresponding `blobsLinearHashes`/`blobsOpeningCommitments`
/// in the `L1DAValidatorOutput` struct will have to have this length as it is required
/// to be static by the circuits.
function checkDA(
uint256 chainId,
bytes32 l2DAValidatorOutputHash,
bytes calldata operatorDAInput,
uint256 maxBlobsSupported
) external returns (L1DAValidatorOutput memory output);
}
11 changes: 11 additions & 0 deletions da-contracts/contracts/IL1Messenger.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.24;
/**
* @author Matter Labs
* @custom:security-contact [email protected]
* @notice The interface of the L1 Messenger contract, responsible for sending messages to L1.
*/
interface IL1Messenger {
function sendToL1(bytes memory _message) external returns (bytes32);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ pragma solidity 0.8.24;

// solhint-disable gas-custom-errors, reason-string

import {IL1DAValidator, L1DAValidatorOutput} from "../chain-interfaces/IL1DAValidator.sol";
import {POINT_EVALUATION_PRECOMPILE_ADDR} from "../../common/Config.sol";
import {IL1DAValidator, L1DAValidatorOutput} from "./IL1DAValidator.sol";

import {CalldataDA} from "./CalldataDA.sol";

// TODO: maybe move it here
import {PubdataSource, BLS_MODULUS, PUBDATA_COMMITMENT_SIZE, PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET, PUBDATA_COMMITMENT_COMMITMENT_OFFSET, BLOB_DA_INPUT_SIZE} from "../chain-interfaces/IExecutor.sol";
import {PubdataSource, BLS_MODULUS, PUBDATA_COMMITMENT_SIZE, PUBDATA_COMMITMENT_CLAIMED_VALUE_OFFSET, PUBDATA_COMMITMENT_COMMITMENT_OFFSET, BLOB_DA_INPUT_SIZE, POINT_EVALUATION_PRECOMPILE_ADDR} from "./DAUtils.sol";

uint256 constant BLOBS_SUPPORTED = 6;

Expand Down Expand Up @@ -170,11 +169,9 @@ contract RollupL1DAValidator is IL1DAValidator, CalldataDA {
require(result == BLS_MODULUS, "precompile unexpected output");
}

function _getBlobVersionedHash(uint256) internal view virtual returns (bytes32 versionedHash) {
// FIXME: enable blobs
revert("Blobs not supported on this codebase yet");
// assembly {
// versionedHash := blobhash(_index)
// }
function _getBlobVersionedHash(uint256 _index) internal view virtual returns (bytes32 versionedHash) {
assembly {
versionedHash := blobhash(_index)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.24;

// solhint-disable gas-custom-errors, reason-string

import {IL1DAValidator, L1DAValidatorOutput} from "../chain-interfaces/IL1DAValidator.sol";
import {IL1DAValidator, L1DAValidatorOutput} from "./IL1DAValidator.sol";

contract ValidiumL1DAValidator is IL1DAValidator {
function checkDA(
Expand Down
32 changes: 32 additions & 0 deletions da-contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[profile.default]
src = 'contracts'
out = 'out'
libs = ['node_modules', 'lib']
remappings = [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"l2-contracts/=../l2-contracts/contracts/"
]
allow_paths = ["../l2-contracts/contracts"]
fs_permissions = [
{ access = "read", path = "../system-contracts/bootloader/build/artifacts" },
{ access = "read", path = "../system-contracts/artifacts-zk/contracts-preprocessed" },
{ access = "read", path = "../l2-contracts/artifacts-zk/" },
{ access = "read", path = "./script-config" },
{ access = "read-write", path = "./script-out" },
{ access = "read", path = "./out" }
]
cache_path = 'cache-forge'
test = 'test/foundry'
solc_version = "0.8.24"
evm_version = "cancun"
ignored_error_codes = [
"missing-receive-ether",
"code-size",
]
ignored_warnings_from = [
"test",
"contracts/dev-contracts"
]

# See more config options https://github.com/foundry-rs/foundry/tree/master/crates/config
57 changes: 57 additions & 0 deletions da-contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import "@nomiclabs/hardhat-ethers";
import "@nomiclabs/hardhat-etherscan";
import "@nomiclabs/hardhat-waffle";
import "hardhat-contract-sizer";
import "hardhat-gas-reporter";
import "hardhat-typechain";
import "solidity-coverage";

// If no network is specified, use the default config
if (!process.env.CHAIN_ETH_NETWORK) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
require("dotenv").config();
}

export default {
defaultNetwork: "env",
solidity: {
version: "0.8.24",
settings: {
optimizer: {
enabled: true,
runs: 9999999,
},
outputSelection: {
"*": {
"*": ["storageLayout"],
},
},
evmVersion: "cancun",
},
},
contractSizer: {
runOnCompile: false,
except: ["dev-contracts", "zksync/libraries", "common/libraries"],
},
paths: {
sources: "./contracts",
},
networks: {
env: {
url: process.env.ETH_CLIENT_WEB3_URL?.split(",")[0],
},
hardhat: {
allowUnlimitedContractSize: false,
forking: {
url: "https://eth-goerli.g.alchemy.com/v2/" + process.env.ALCHEMY_KEY,
enabled: process.env.TEST_CONTRACTS_FORK === "1",
},
},
},
etherscan: {
apiKey: process.env.MISC_ETHERSCAN_API_KEY,
},
gasReporter: {
enabled: true,
},
};
66 changes: 66 additions & 0 deletions da-contracts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"name": "da-contracts",
"version": "0.1.0",
"license": "MIT",
"engines": {
"node": ">=16"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.0",
"@nomiclabs/hardhat-etherscan": "^3.1.0",
"@nomiclabs/hardhat-waffle": "^2.0.0",
"@openzeppelin/contracts": "4.9.5",
"@openzeppelin/contracts-upgradeable": "4.9.5",
"@typechain/ethers-v5": "^2.0.0",
"@types/argparse": "^1.0.36",
"@types/chai": "^4.2.21",
"@types/chai-as-promised": "^7.1.4",
"@types/mocha": "^8.2.3",
"argparse": "^1.0.10",
"axios": "^0.21.1",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.1",
"chalk": "^4.1.0",
"collections": "^5.1.12",
"commander": "^8.3.0",
"eslint": "^8.51.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-prettier": "^5.0.1",
"ethereum-waffle": "^4.0.10",
"ethereumjs-abi": "^0.6.8",
"ethers": "^5.7.0",
"ethjs": "^0.4.0",
"fs": "^0.0.1-security",
"handlebars": "^4.7.6",
"hardhat": "=2.22.2",
"hardhat-contract-sizer": "^2.0.2",
"hardhat-gas-reporter": "^1.0.9",
"hardhat-typechain": "^0.3.3",
"jsonwebtoken": "^8.5.1",
"markdownlint-cli": "^0.33.0",
"merkletreejs": "^0.3.11",
"mocha": "^9.0.2",
"path": "^0.12.7",
"querystring": "^0.2.0",
"solc": "0.8.17",
"solhint": "^3.6.2",
"solidity-coverage": "^0.8.5",
"ts-generator": "^0.1.1",
"ts-node": "^10.1.0",
"typechain": "^4.0.0",
"typescript": "^4.6.4",
"zksync-ethers": "5.8.0-beta.5"
},
"scripts": {
"build": "hardhat compile ",
"build-l1": "harhdat compile",
"clean": "hardhat clean",
"clean:foundry": "forge clean",
"verify": "hardhat run --network env scripts/verify.ts"
},
"dependencies": {
"dotenv": "^16.0.3",
"solhint-plugin-prettier": "^0.0.5"
}
}
Loading

0 comments on commit beaa0a6

Please sign in to comment.