Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 3 additions & 1 deletion core/node/da_clients/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ ethabi.workspace = true
rust-kzg-bn254.workspace = true
ark-bn254.workspace = true
num-bigint.workspace = true
serial_test.workspace = true
zksync_web3_decl.workspace = true
zksync_eth_client.workspace = true
url.workspace = true

[dev-dependencies]
serial_test.workspace = true
100 changes: 43 additions & 57 deletions core/node/da_clients/src/eigen/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,9 @@ impl Verifier {
Ok(())
}

pub fn hash_encode_blob_header(&self, blob_header: BlobHeader) -> Vec<u8> {
pub fn hash_encode_blob_header(&self, blob_header: &BlobHeader) -> Vec<u8> {
let mut blob_quorums = vec![];
for quorum in blob_header.blob_quorum_params {
for quorum in &blob_header.blob_quorum_params {
let quorum = Token::Tuple(vec![
Token::Uint(ethabi::Uint::from(quorum.quorum_number)),
Token::Uint(ethabi::Uint::from(quorum.adversary_threshold_percentage)),
Expand Down Expand Up @@ -226,20 +226,16 @@ impl Verifier {
}
let mut computed_hash = leaf.to_vec();
for i in 0..proof.len() / 32 {
let mut combined = proof[i * 32..(i + 1) * 32]
.iter()
.chain(computed_hash.iter())
.cloned()
.collect::<Vec<u8>>();
let mut buffer = [0u8; 64];
if index % 2 == 0 {
combined = computed_hash
.iter()
.chain(proof[i * 32..(i + 1) * 32].iter())
.cloned()
.collect::<Vec<u8>>();
};
buffer[..32].copy_from_slice(&computed_hash);
buffer[32..].copy_from_slice(&proof[i * 32..(i + 1) * 32]);
} else {
buffer[..32].copy_from_slice(&proof[i * 32..(i + 1) * 32]);
buffer[32..].copy_from_slice(&computed_hash);
}
let mut keccak = Keccak::v256();
keccak.update(&combined);
keccak.update(&buffer);
let mut hash = [0u8; 32];
keccak.finalize(&mut hash);
computed_hash = hash.to_vec();
Expand All @@ -250,15 +246,15 @@ impl Verifier {
}

/// Verifies the certificate's batch root
pub fn verify_merkle_proof(&self, cert: BlobInfo) -> Result<(), VerificationError> {
let inclusion_proof = cert.blob_verification_proof.inclusion_proof;
let root = cert
pub fn verify_merkle_proof(&self, cert: &BlobInfo) -> Result<(), VerificationError> {
let inclusion_proof = &cert.blob_verification_proof.inclusion_proof;
let root = &cert
.blob_verification_proof
.batch_medatada
.batch_header
.batch_root;
let blob_index = cert.blob_verification_proof.blob_index;
let blob_header = cert.blob_header;
let blob_header = &cert.blob_header;

let blob_header_hash = self.hash_encode_blob_header(blob_header);
let mut keccak = Keccak::v256();
Expand All @@ -267,24 +263,24 @@ impl Verifier {
keccak.finalize(&mut leaf_hash);

let generated_root =
self.process_inclusion_proof(&inclusion_proof, &leaf_hash, blob_index)?;
self.process_inclusion_proof(inclusion_proof, &leaf_hash, blob_index)?;

if generated_root != root {
if generated_root != *root {
return Err(VerificationError::DifferentRoots);
}
Ok(())
}

fn hash_batch_metadata(
&self,
batch_header: BatchHeader,
signatory_record_hash: Vec<u8>,
batch_header: &BatchHeader,
signatory_record_hash: &[u8],
confirmation_block_number: u32,
) -> Vec<u8> {
let batch_header_token = Token::Tuple(vec![
Token::FixedBytes(batch_header.batch_root),
Token::Bytes(batch_header.quorum_numbers),
Token::Bytes(batch_header.quorum_signed_percentages),
Token::FixedBytes(batch_header.batch_root.clone()), // Clone only where necessary
Token::Bytes(batch_header.quorum_numbers.clone()),
Token::Bytes(batch_header.quorum_signed_percentages.clone()),
Token::Uint(ethabi::Uint::from(batch_header.reference_block_number)),
]);

Expand All @@ -297,7 +293,7 @@ impl Verifier {

let hash_token = Token::Tuple(vec![
Token::FixedBytes(header_hash.to_vec()),
Token::FixedBytes(signatory_record_hash),
Token::FixedBytes(signatory_record_hash.to_owned()), // Clone only if required
]);

let mut hash_encoded = encode(&[hash_token]);
Expand Down Expand Up @@ -330,7 +326,7 @@ impl Verifier {

async fn call_batch_id_to_metadata_hash(
&self,
blob_info: BlobInfo,
blob_info: &BlobInfo,
) -> Result<Vec<u8>, VerificationError> {
let context_block = self.get_context_block().await?;

Expand Down Expand Up @@ -361,21 +357,19 @@ impl Verifier {
}

/// Verifies the certificate batch hash
pub async fn verify_batch(&self, blob_info: BlobInfo) -> Result<(), VerificationError> {
let expected_hash = self
.call_batch_id_to_metadata_hash(blob_info.clone())
.await?;
pub async fn verify_batch(&self, blob_info: &BlobInfo) -> Result<(), VerificationError> {
let expected_hash = self.call_batch_id_to_metadata_hash(blob_info).await?;

if expected_hash == vec![0u8; 32] {
return Err(VerificationError::EmptyHash);
}

let actual_hash = self.hash_batch_metadata(
blob_info
&blob_info
.blob_verification_proof
.batch_medatada
.batch_header,
blob_info
&blob_info
.blob_verification_proof
.batch_medatada
.signatory_record_hash,
Expand All @@ -398,31 +392,23 @@ impl Verifier {
}

// Read the offset (first 32 bytes)
let offset = {
let mut offset_bytes = [0u8; 32];
offset_bytes.copy_from_slice(&encoded[0..32]);
usize::from_be_bytes(
offset_bytes[24..32]
.try_into()
.map_err(|_| "Offset is too large")?,
)
};
let offset = usize::from_be_bytes(
encoded[24..32]
.try_into()
.map_err(|_| "Offset is too large")?,
);

// Check if offset is valid
if offset + 32 > encoded.len() {
return Err("Offset points outside the encoded data".to_string());
}

// Read the length (32 bytes at the offset position)
let length = {
let mut length_bytes = [0u8; 32];
length_bytes.copy_from_slice(&encoded[offset..offset + 32]);
usize::from_be_bytes(
length_bytes[24..32]
.try_into()
.map_err(|_| "Offset is too large")?,
)
};
let length = usize::from_be_bytes(
encoded[offset + 24..offset + 32]
.try_into()
.map_err(|_| "Length is too large")?,
);

// Check if the length is valid
if offset + 32 + length > encoded.len() {
Expand Down Expand Up @@ -485,9 +471,9 @@ impl Verifier {
}

/// Verifies that the certificate's blob quorum params are correct
pub async fn verify_security_params(&self, cert: BlobInfo) -> Result<(), VerificationError> {
let blob_header = cert.blob_header;
let batch_header = cert.blob_verification_proof.batch_medatada.batch_header;
pub async fn verify_security_params(&self, cert: &BlobInfo) -> Result<(), VerificationError> {
let blob_header = &cert.blob_header;
let batch_header = &cert.blob_verification_proof.batch_medatada.batch_header;

let mut confirmed_quorums: HashMap<u32, bool> = HashMap::new();
for i in 0..blob_header.blob_quorum_params.len() {
Expand Down Expand Up @@ -536,9 +522,9 @@ impl Verifier {
&self,
cert: BlobInfo,
) -> Result<(), VerificationError> {
self.verify_batch(cert.clone()).await?;
self.verify_merkle_proof(cert.clone())?;
self.verify_security_params(cert.clone()).await?;
self.verify_batch(&cert).await?;
self.verify_merkle_proof(&cert)?;
self.verify_security_params(&cert).await?;
Ok(())
}
}
16 changes: 8 additions & 8 deletions core/node/da_clients/src/eigen/verifier_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ mod test {
quorum_indexes: vec![0, 1],
},
};
let result = verifier.verify_merkle_proof(cert);
let result = verifier.verify_merkle_proof(&cert);
assert!(result.is_ok());
}

Expand Down Expand Up @@ -293,7 +293,7 @@ mod test {
quorum_indexes: vec![0, 1],
},
};
let result = verifier.verify_merkle_proof(cert);
let result = verifier.verify_merkle_proof(&cert);
assert!(result.is_ok());
}

Expand Down Expand Up @@ -330,7 +330,7 @@ mod test {
},
],
};
let result = verifier.hash_encode_blob_header(blob_header);
let result = verifier.hash_encode_blob_header(&blob_header);
let expected = "ba4675a31c9bf6b2f7abfdcedd34b74645cb7332b35db39bff00ae8516a67393";
assert_eq!(result, hex::decode(expected).unwrap());
}
Expand Down Expand Up @@ -369,7 +369,7 @@ mod test {
},
],
};
let result = verifier.hash_encode_blob_header(blob_header);
let result = verifier.hash_encode_blob_header(&blob_header);
let expected = "ba4675a31c9bf6b2f7abfdcedd34b74645cb7332b35db39bff00ae8516a67393";
assert_eq!(result, hex::decode(expected).unwrap());
}
Expand Down Expand Up @@ -493,7 +493,7 @@ mod test {
quorum_indexes: vec![0, 1],
},
};
let result = verifier.verify_batch(cert).await;
let result = verifier.verify_batch(&cert).await;
assert!(result.is_ok());
}

Expand Down Expand Up @@ -601,7 +601,7 @@ mod test {
quorum_indexes: vec![0, 1],
},
};
let result = verifier.verify_batch(cert).await;
let result = verifier.verify_batch(&cert).await;
assert!(result.is_ok());
}

Expand Down Expand Up @@ -683,7 +683,7 @@ mod test {
quorum_indexes: vec![0, 1],
},
};
let result = verifier.verify_security_params(cert).await;
let result = verifier.verify_security_params(&cert).await;
assert!(result.is_ok());
}

Expand Down Expand Up @@ -808,7 +808,7 @@ mod test {
quorum_indexes: vec![0, 1],
},
};
let result = verifier.verify_security_params(cert).await;
let result = verifier.verify_security_params(&cert).await;
assert!(result.is_ok());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,12 @@ pub struct GetBlobFromDB {

#[async_trait::async_trait]
impl GetBlobData for GetBlobFromDB {
async fn get_blob_data(&self, input: &'_ str) -> anyhow::Result<Option<Vec<u8>>> {
let pool = self.pool.clone();
let input = input.to_string();
let mut conn = pool.connection_tagged("eigen_client").await?;
async fn get_blob_data(&self, input: &str) -> anyhow::Result<Option<Vec<u8>>> {
let mut conn = self.pool.connection_tagged("eigen_client").await?;
let batch = conn
.data_availability_dal()
.get_blob_data_by_blob_id(&input)
.await?;
drop(conn);
Ok(batch.map(|b| b.pubdata))
}
}
Loading