Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Verify blob L1 #287

Draft
wants to merge 20 commits into
base: da-eigen-implementation-m0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,233 changes: 1,176 additions & 57 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion core/bin/zksync_server/src/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ impl MainNodeBuilder {
.add_layer(ObjectStorageClientWiringLayer::new(config));
}
DAClient::EigenDA(config) => {
self.node.add_layer(EigenDAWiringLayer::new(config));
self.node.add_layer(EigenDAWiringLayer::new(config, self.contracts_config.eigenda_verifier_addr.unwrap()));
}
}

Expand Down
2 changes: 2 additions & 0 deletions core/lib/config/src/configs/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub struct ContractsConfig {
// Used by the RPC API and by the node builder in wiring the BaseTokenRatioProvider layer.
pub base_token_addr: Option<Address>,
pub chain_admin_addr: Option<Address>,
pub eigenda_verifier_addr: Option<Address>,
}

impl ContractsConfig {
Expand All @@ -61,6 +62,7 @@ impl ContractsConfig {
base_token_addr: Some(Address::repeat_byte(0x14)),
ecosystem_contracts: Some(EcosystemContracts::for_tests()),
chain_admin_addr: Some(Address::repeat_byte(0x18)),
eigenda_verifier_addr: Some(Address::repeat_byte(0x19)),
}
}
}
1 change: 1 addition & 0 deletions core/lib/config/src/testonly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ impl Distribution<configs::ContractsConfig> for EncodeDist {
ecosystem_contracts: self.sample(rng),
base_token_addr: self.sample_opt(|| rng.gen()),
chain_admin_addr: self.sample_opt(|| rng.gen()),
eigenda_verifier_addr: self.sample_opt(|| rng.gen()),
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion core/lib/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ const LOADNEXT_CONTRACT_FILE: &str =
"etc/contracts-test-data/artifacts-zk/contracts/loadnext/loadnext_contract.sol/LoadnextContract.json";
const LOADNEXT_SIMPLE_CONTRACT_FILE: &str =
"etc/contracts-test-data/artifacts-zk/contracts/loadnext/loadnext_contract.sol/Foo.json";

const EIGENDA_VERIFIER_CONTRACT_FILE: (&str, &str) = (
"eigenda",
"EigendaVerifier.sol/EigendaVerifier.json",
);
fn home_path() -> PathBuf {
Workspace::locate().core()
}
Expand Down Expand Up @@ -162,6 +165,10 @@ pub fn verifier_contract() -> Contract {
load_contract_for_both_compilers(VERIFIER_CONTRACT_FILE)
}

pub fn eigenda_verifier_contract() -> Contract {
load_contract_for_both_compilers(EIGENDA_VERIFIER_CONTRACT_FILE)
}

#[derive(Debug, Clone)]
pub struct TestContract {
/// Contract bytecode to be used for sending deploy transaction.
Expand Down
2 changes: 2 additions & 0 deletions core/lib/env_config/src/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ mod tests {
}),
base_token_addr: Some(SHARED_BRIDGE_ETHER_TOKEN_ADDRESS),
chain_admin_addr: Some(addr("0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347ff")),
eigenda_verifier_addr: None,
}
}

Expand All @@ -98,6 +99,7 @@ CONTRACTS_STATE_TRANSITION_PROXY_ADDR="0xd90f1c081c6117241624e97cb6147257c3cb209
CONTRACTS_TRANSPARENT_PROXY_ADMIN_ADDR="0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347e5"
CONTRACTS_BASE_TOKEN_ADDR="0x0000000000000000000000000000000000000001"
CONTRACTS_CHAIN_ADMIN_ADDR="0xdd6fa5c14e7550b4caf2aa2818d24c69cbc347ff"
CONTRACTS_EIGENDA_VERIFIER_ADDR=""
"#;
lock.set_env(config);

Expand Down
7 changes: 7 additions & 0 deletions core/lib/protobuf_config/src/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ impl ProtoRepr for proto::Contracts {
.map(|x| parse_h160(x))
.transpose()
.context("chain_admin_addr")?,
eigenda_verifier_addr: l1
.eigenda_verifier_addr
.as_ref()
.map(|x| parse_h160(x))
.transpose()
.context("eigenda_verifier_addr")?,
})
}

Expand Down Expand Up @@ -139,6 +145,7 @@ impl ProtoRepr for proto::Contracts {
multicall3_addr: Some(format!("{:?}", this.l1_multicall3_addr)),
base_token_addr: this.base_token_addr.map(|a| format!("{:?}", a)),
chain_admin_addr: this.chain_admin_addr.map(|a| format!("{:?}", a)),
eigenda_verifier_addr: this.eigenda_verifier_addr.map(|a| format!("{:?}", a)),
}),
l2: Some(proto::L2 {
testnet_paymaster_addr: this.l2_testnet_paymaster_addr.map(|a| format!("{:?}", a)),
Expand Down
1 change: 1 addition & 0 deletions core/lib/protobuf_config/src/proto/config/contracts.proto
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ message L1 {
optional string multicall3_addr = 6; // required; H160
optional string base_token_addr = 7; // required; H160
optional string chain_admin_addr = 8; // required; H160
optional string eigenda_verifier_addr = 9 ; // optional; h160
}

message L2 {
Expand Down
4 changes: 4 additions & 0 deletions core/node/da_clients/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ zksync_types.workspace = true
zksync_object_store.workspace = true
zksync_da_client.workspace = true
zksync_env_config.workspace = true
zksync_eth_client.workspace = true
zksync_contracts.workspace = true
futures.workspace = true

# Avail dependencies
Expand All @@ -41,3 +43,5 @@ subxt-signer = { workspace = true, features = ["sr25519", "native"] }
# EigenDA dependencies
reqwest = { version = "0.12" }
http = "1"
rlp.workspace = true
ethers = { version = "2.0.0-rc.1", features = ["abigen", "etherscan"] }
219 changes: 219 additions & 0 deletions core/node/da_clients/src/blob_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
use rlp::Decodable;
use rlp::DecoderError;
use rlp::Rlp;
use zksync_types::web3::contract::Tokenizable;
use zksync_types::web3::contract::Tokenize;
use zksync_types::ethabi::Token;
use zksync_types::U256;

#[derive(Debug)]
pub struct G1Commitment {
pub x: Vec<u8>,
pub y: Vec<u8>,
}

impl Decodable for G1Commitment {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
let x: Vec<u8> = rlp.val_at(0)?; // Decode first element as Vec<u8>
let y: Vec<u8> = rlp.val_at(1)?; // Decode second element as Vec<u8>

Ok(G1Commitment { x, y })
}
}

impl Tokenize for G1Commitment {
fn into_tokens(self) -> Vec<Token> {

let x = Token::Uint(U256::from_big_endian(&self.x));
let y = Token::Uint(U256::from_big_endian(&self.y));

vec![x, y]
}
}

#[derive(Debug)]
pub struct BlobQuorumParam {
pub quorum_number: u32,
pub adversary_threshold_percentage: u32,
pub confirmation_threshold_percentage: u32,
pub chunk_length: u32
}

impl Decodable for BlobQuorumParam {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
Ok(BlobQuorumParam {
quorum_number: rlp.val_at(0)?,
adversary_threshold_percentage: rlp.val_at(1)?,
confirmation_threshold_percentage: rlp.val_at(2)?,
chunk_length: rlp.val_at(3)?,
})
}
}

impl Tokenize for BlobQuorumParam {
fn into_tokens(self) -> Vec<Token> {

let quorum_number = Token::Uint(U256::from(self.quorum_number));
let adversary_threshold_percentage = Token::Uint(U256::from(self.adversary_threshold_percentage));
let confirmation_threshold_percentage = Token::Uint(U256::from(self.confirmation_threshold_percentage));
let chunk_length = Token::Uint(U256::from(self.chunk_length));

vec![quorum_number, adversary_threshold_percentage,confirmation_threshold_percentage,chunk_length]
}
}

#[derive(Debug)]
pub struct BlobHeader {
pub commitment: G1Commitment,
pub data_length: u32,
pub blob_quorum_params: Vec<BlobQuorumParam>
}

impl Decodable for BlobHeader {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
let commitment: G1Commitment = rlp.val_at(0)?;
let data_length: u32 = rlp.val_at(1)?;
let blob_quorum_params: Vec<BlobQuorumParam> = rlp.list_at(2)?;

Ok(BlobHeader {
commitment,
data_length,
blob_quorum_params,
})
}
}

impl Tokenize for BlobHeader {
fn into_tokens(self) -> Vec<Token> {
let commitment = self.commitment.into_tokens();
let data_length = Token::Uint(U256::from(self.data_length));
let blob_quorum_params = self.blob_quorum_params.into_iter().map(|quorum| Token::Tuple(quorum.into_tokens())).collect();

vec![Token::Tuple(commitment), data_length,Token::Array(blob_quorum_params)]
}
}

#[derive(Debug)]
pub struct BatchHeader {
pub batch_root: Vec<u8>,
pub quorum_numbers: Vec<u8>,
pub quorum_signed_percentages: Vec<u8>,
pub reference_block_number: u32
}

impl Decodable for BatchHeader {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
Ok(BatchHeader {
batch_root: rlp.val_at(0)?,
quorum_numbers: rlp.val_at(1)?,
quorum_signed_percentages: rlp.val_at(2)?,
reference_block_number: rlp.val_at(3)?,
})
}
}

impl Tokenize for BatchHeader {
fn into_tokens(self) -> Vec<Token> {
let batch_root = Token::FixedBytes(self.batch_root);
let quorum_numbers = self.quorum_numbers.into_token();
let quorum_signed_percentages = self.quorum_signed_percentages.into_token();
let reference_block_number = Token::Uint(U256::from(self.reference_block_number));

vec![batch_root, quorum_numbers,quorum_signed_percentages,reference_block_number]
}
}

#[derive(Debug)]
pub struct BatchMetadata {
pub batch_header: BatchHeader,
pub signatory_record_hash: Vec<u8>,
pub fee: Vec<u8>,
pub confirmation_block_number: u32,
pub batch_header_hash: Vec<u8>
}

impl Decodable for BatchMetadata {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
let batch_header: BatchHeader = rlp.val_at(0)?;

Ok(BatchMetadata {
batch_header,
signatory_record_hash: rlp.val_at(1)?,
fee: rlp.val_at(2)?,
confirmation_block_number: rlp.val_at(3)?,
batch_header_hash: rlp.val_at(4)?,
})
}
}

impl Tokenize for BatchMetadata {
fn into_tokens(self) -> Vec<Token> {
let batch_header = self.batch_header.into_tokens();
let signatory_record_hash = Token::FixedBytes(self.signatory_record_hash);
let confirmation_block_number = Token::Uint(U256::from(self.confirmation_block_number));

vec![Token::Tuple(batch_header), signatory_record_hash,confirmation_block_number]
}
}

#[derive(Debug)]
pub struct BlobVerificationProof {
pub batch_id: u32,
pub blob_index: u32,
pub batch_medatada: BatchMetadata,
pub inclusion_proof: Vec<u8>,
pub quorum_indexes: Vec<u8>
}

impl Decodable for BlobVerificationProof {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
Ok(BlobVerificationProof {
batch_id: rlp.val_at(0)?,
blob_index: rlp.val_at(1)?,
batch_medatada: rlp.val_at(2)?,
inclusion_proof: rlp.val_at(3)?,
quorum_indexes: rlp.val_at(4)?,
})
}
}

impl Tokenize for BlobVerificationProof {
fn into_tokens(self) -> Vec<Token> {
let batch_id = Token::Uint(U256::from(self.batch_id));
let blob_index = Token::Uint(U256::from(self.blob_index));
let batch_medatada = self.batch_medatada.into_tokens();
let inclusion_proof = self.inclusion_proof.into_token();
let quorum_indexes = self.quorum_indexes.into_token();

vec![batch_id, blob_index,Token::Tuple(batch_medatada),inclusion_proof,quorum_indexes]
}
}

#[derive(Debug)]
pub struct BlobInfo {
pub blob_header: BlobHeader,
pub blob_verification_proof: BlobVerificationProof
}

impl Decodable for BlobInfo {
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
let blob_header: BlobHeader = rlp.val_at(0)?;
let blob_verification_proof: BlobVerificationProof = rlp.val_at(1)?;

Ok(BlobInfo {
blob_header,
blob_verification_proof,
})
}
}

impl Tokenize for BlobInfo {
fn into_tokens(self) -> Vec<Token> {
let blob_header = self.blob_header.into_tokens();
let blob_verification_proof = self.blob_verification_proof.into_tokens();

vec![Token::Tuple(vec![Token::Tuple(blob_header),Token::Tuple(blob_verification_proof)])]
}
}


Loading
Loading