diff --git a/core/node/da_clients/src/eigen/generated/EigenDAServiceManager.json b/core/node/da_clients/src/eigen/generated/EigenDAServiceManager.json deleted file mode 100644 index 486978b2dfb7..000000000000 --- a/core/node/da_clients/src/eigen/generated/EigenDAServiceManager.json +++ /dev/null @@ -1 +0,0 @@ -[{"type":"constructor","inputs":[{"name":"__avsDirectory","type":"address","internalType":"contract IAVSDirectory"},{"name":"__rewardsCoordinator","type":"address","internalType":"contract IRewardsCoordinator"},{"name":"__registryCoordinator","type":"address","internalType":"contract IRegistryCoordinator"},{"name":"__stakeRegistry","type":"address","internalType":"contract IStakeRegistry"}],"stateMutability":"nonpayable"},{"type":"function","name":"BLOCK_STALE_MEASURE","inputs":[],"outputs":[{"name":"","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"STORE_DURATION_BLOCKS","inputs":[],"outputs":[{"name":"","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"THRESHOLD_DENOMINATOR","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"avsDirectory","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"batchId","inputs":[],"outputs":[{"name":"","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"batchIdToBatchMetadataHash","inputs":[{"name":"","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"blsApkRegistry","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBLSApkRegistry"}],"stateMutability":"view"},{"type":"function","name":"checkSignatures","inputs":[{"name":"msgHash","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"},{"name":"referenceBlockNumber","type":"uint32","internalType":"uint32"},{"name":"params","type":"tuple","internalType":"struct IBLSSignatureChecker.NonSignerStakesAndSignature","components":[{"name":"nonSignerQuorumBitmapIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"nonSignerPubkeys","type":"tuple[]","internalType":"struct BN254.G1Point[]","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"quorumApks","type":"tuple[]","internalType":"struct BN254.G1Point[]","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"apkG2","type":"tuple","internalType":"struct BN254.G2Point","components":[{"name":"X","type":"uint256[2]","internalType":"uint256[2]"},{"name":"Y","type":"uint256[2]","internalType":"uint256[2]"}]},{"name":"sigma","type":"tuple","internalType":"struct BN254.G1Point","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"quorumApkIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"totalStakeIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"nonSignerStakeIndices","type":"uint32[][]","internalType":"uint32[][]"}]}],"outputs":[{"name":"","type":"tuple","internalType":"struct IBLSSignatureChecker.QuorumStakeTotals","components":[{"name":"signedStakeForQuorum","type":"uint96[]","internalType":"uint96[]"},{"name":"totalStakeForQuorum","type":"uint96[]","internalType":"uint96[]"}]},{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"confirmBatch","inputs":[{"name":"batchHeader","type":"tuple","internalType":"struct IEigenDAServiceManager.BatchHeader","components":[{"name":"blobHeadersRoot","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"},{"name":"signedStakeForQuorums","type":"bytes","internalType":"bytes"},{"name":"referenceBlockNumber","type":"uint32","internalType":"uint32"}]},{"name":"nonSignerStakesAndSignature","type":"tuple","internalType":"struct IBLSSignatureChecker.NonSignerStakesAndSignature","components":[{"name":"nonSignerQuorumBitmapIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"nonSignerPubkeys","type":"tuple[]","internalType":"struct BN254.G1Point[]","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"quorumApks","type":"tuple[]","internalType":"struct BN254.G1Point[]","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"apkG2","type":"tuple","internalType":"struct BN254.G2Point","components":[{"name":"X","type":"uint256[2]","internalType":"uint256[2]"},{"name":"Y","type":"uint256[2]","internalType":"uint256[2]"}]},{"name":"sigma","type":"tuple","internalType":"struct BN254.G1Point","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"quorumApkIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"totalStakeIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"nonSignerStakeIndices","type":"uint32[][]","internalType":"uint32[][]"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"createAVSRewardsSubmission","inputs":[{"name":"rewardsSubmissions","type":"tuple[]","internalType":"struct IRewardsCoordinator.RewardsSubmission[]","components":[{"name":"strategiesAndMultipliers","type":"tuple[]","internalType":"struct IRewardsCoordinator.StrategyAndMultiplier[]","components":[{"name":"strategy","type":"address","internalType":"contract IStrategy"},{"name":"multiplier","type":"uint96","internalType":"uint96"}]},{"name":"token","type":"address","internalType":"contract IERC20"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"startTimestamp","type":"uint32","internalType":"uint32"},{"name":"duration","type":"uint32","internalType":"uint32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"delegation","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IDelegationManager"}],"stateMutability":"view"},{"type":"function","name":"deregisterOperatorFromAVS","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getOperatorRestakedStrategies","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"getRestakeableStrategies","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"_pauserRegistry","type":"address","internalType":"contract IPauserRegistry"},{"name":"_initialPausedStatus","type":"uint256","internalType":"uint256"},{"name":"_initialOwner","type":"address","internalType":"address"},{"name":"_batchConfirmers","type":"address[]","internalType":"address[]"},{"name":"_rewardsInitiator","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isBatchConfirmer","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"latestServeUntilBlock","inputs":[{"name":"referenceBlockNumber","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pause","inputs":[{"name":"newPausedStatus","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pauseAll","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"paused","inputs":[{"name":"index","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"pauserRegistry","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IPauserRegistry"}],"stateMutability":"view"},{"type":"function","name":"quorumAdversaryThresholdPercentages","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"quorumConfirmationThresholdPercentages","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"quorumNumbersRequired","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"registerOperatorToAVS","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"operatorSignature","type":"tuple","internalType":"struct ISignatureUtils.SignatureWithSaltAndExpiry","components":[{"name":"signature","type":"bytes","internalType":"bytes"},{"name":"salt","type":"bytes32","internalType":"bytes32"},{"name":"expiry","type":"uint256","internalType":"uint256"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"registryCoordinator","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IRegistryCoordinator"}],"stateMutability":"view"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rewardsInitiator","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"setBatchConfirmer","inputs":[{"name":"_batchConfirmer","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPauserRegistry","inputs":[{"name":"newPauserRegistry","type":"address","internalType":"contract IPauserRegistry"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRewardsInitiator","inputs":[{"name":"newRewardsInitiator","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setStaleStakesForbidden","inputs":[{"name":"value","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stakeRegistry","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStakeRegistry"}],"stateMutability":"view"},{"type":"function","name":"staleStakesForbidden","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"taskNumber","inputs":[],"outputs":[{"name":"","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"trySignatureAndApkVerification","inputs":[{"name":"msgHash","type":"bytes32","internalType":"bytes32"},{"name":"apk","type":"tuple","internalType":"struct BN254.G1Point","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]},{"name":"apkG2","type":"tuple","internalType":"struct BN254.G2Point","components":[{"name":"X","type":"uint256[2]","internalType":"uint256[2]"},{"name":"Y","type":"uint256[2]","internalType":"uint256[2]"}]},{"name":"sigma","type":"tuple","internalType":"struct BN254.G1Point","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]}],"outputs":[{"name":"pairingSuccessful","type":"bool","internalType":"bool"},{"name":"siganatureIsValid","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"unpause","inputs":[{"name":"newPausedStatus","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateAVSMetadataURI","inputs":[{"name":"_metadataURI","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"BatchConfirmed","inputs":[{"name":"batchHeaderHash","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"batchId","type":"uint32","indexed":false,"internalType":"uint32"}],"anonymous":false},{"type":"event","name":"BatchConfirmerStatusChanged","inputs":[{"name":"batchConfirmer","type":"address","indexed":false,"internalType":"address"},{"name":"status","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint8","indexed":false,"internalType":"uint8"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"newPausedStatus","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PauserRegistrySet","inputs":[{"name":"pauserRegistry","type":"address","indexed":false,"internalType":"contract IPauserRegistry"},{"name":"newPauserRegistry","type":"address","indexed":false,"internalType":"contract IPauserRegistry"}],"anonymous":false},{"type":"event","name":"RewardsInitiatorUpdated","inputs":[{"name":"prevRewardsInitiator","type":"address","indexed":false,"internalType":"address"},{"name":"newRewardsInitiator","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StaleStakesForbiddenUpdate","inputs":[{"name":"value","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"newPausedStatus","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false}] diff --git a/core/node/da_clients/src/eigen/verifier.rs b/core/node/da_clients/src/eigen/verifier.rs index f3edd0b26b63..3db332a9c691 100644 --- a/core/node/da_clients/src/eigen/verifier.rs +++ b/core/node/da_clients/src/eigen/verifier.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, fs::File, io::BufReader, str::FromStr}; use ark_bn254::{Fq, G1Affine}; -use ethabi::{encode, Contract, Token}; +use ethabi::{encode, Token}; use rust_kzg_bn254::{blob::Blob, kzg::Kzg, polynomial::PolynomialFormat}; use tiny_keccak::{Hasher, Keccak}; use zksync_basic_types::web3::CallRequest; @@ -52,7 +52,6 @@ pub struct Verifier { kzg: Kzg, cfg: VerifierConfig, signing_client: PKSigningClient, - contract: Contract, } impl Verifier { @@ -60,11 +59,6 @@ impl Verifier { const BATCH_ID_TO_METADATA_HASH_FUNCTION_SELECTOR: [u8; 4] = [236, 203, 191, 201]; const QUORUM_ADVERSARY_THRESHOLD_PERCENTAGES_FUNCTION_SELECTOR: [u8; 4] = [134, 135, 254, 174]; const QUORUM_NUMBERS_REQUIRED_FUNCTION_SELECTOR: [u8; 4] = [225, 82, 52, 255]; - #[cfg(test)] - const FILE_PATH: &str = "./src/eigen/generated/EigenDAServiceManager.json"; - - #[cfg(not(test))] - const FILE_PATH: &str = "./core/node/da_clients/src/eigen/generated/EigenDAServiceManager.json"; pub fn new(cfg: VerifierConfig) -> Result { let srs_points_to_load = cfg.max_blob_size / 32; let kzg = Kzg::setup( @@ -98,17 +92,10 @@ impl Verifier { client, ); - let file = - File::open(Self::FILE_PATH).map_err(|_| VerificationError::ServiceManagerError)?; - let reader = BufReader::new(file); - let contract = - Contract::load(reader).map_err(|_| VerificationError::ServiceManagerError)?; - Ok(Self { kzg, cfg, signing_client, - contract, }) } @@ -290,11 +277,6 @@ impl Verifier { async fn verify_batch(&self, cert: BlobInfo) -> Result<(), VerificationError> { let context_block = self.get_context_block().await?; - let fn_batch_id_to_batch_metadata_hash = self - .contract - .function("batchIdToBatchMetadataHash") - .map_err(|_| VerificationError::ServiceManagerError)?; - let mut data = Self::BATCH_ID_TO_METADATA_HASH_FUNCTION_SELECTOR.to_vec(); let mut batch_id_vec = [0u8; 32]; U256::from(cert.blob_verification_proof.batch_id).to_big_endian(&mut batch_id_vec); @@ -319,18 +301,7 @@ impl Verifier { .await .map_err(|_| VerificationError::ServiceManagerError)?; - let expected_hash = fn_batch_id_to_batch_metadata_hash - .decode_output(&res.0) - .map_err(|_| VerificationError::ServiceManagerError)?; - - if expected_hash.len() != 1 { - return Err(VerificationError::ServiceManagerError); - } - - let expected_hash: Vec = match expected_hash[0].clone() { - Token::FixedBytes(hash) => hash, - _ => return Err(VerificationError::ServiceManagerError), - }; + let expected_hash = res.0.to_vec(); if expected_hash == vec![0u8; 32] { return Err(VerificationError::EmptyHash); @@ -352,6 +323,49 @@ impl Verifier { Ok(()) } + fn decode_bytes(&self, encoded: Vec) -> Result, String> { + // Ensure the input has at least 64 bytes (offset + length) + if encoded.len() < 64 { + return Err("Encoded data is too short".to_string()); + } + + // 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")?, + ) + }; + + // 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")?, + ) + }; + + // Check if the length is valid + if offset + 32 + length > encoded.len() { + return Err("Length extends beyond the encoded data".to_string()); + } + + // Extract the bytes data + let data = encoded[offset + 32..offset + 32 + length].to_vec(); + Ok(data) + } + async fn get_quorum_adversary_threshold( &self, quorum_number: u32, @@ -374,26 +388,12 @@ impl Verifier { .await .map_err(|_| VerificationError::ServiceManagerError)?; - let fn_quorum_adv_percentages = self - .contract - .function("quorumAdversaryThresholdPercentages") - .map_err(|_| VerificationError::ServiceManagerError)?; - - let percentages = fn_quorum_adv_percentages - .decode_output(&res.0) + let percentages = self + .decode_bytes(res.0.to_vec()) .map_err(|_| VerificationError::ServiceManagerError)?; - if percentages.len() != 1 { - return Err(VerificationError::ServiceManagerError); - } - - match percentages[0].clone() { - Token::Bytes(percentages) => { - if percentages.len() > quorum_number as usize { - return Ok(percentages[quorum_number as usize]); - } - } - _ => return Err(VerificationError::ServiceManagerError), + if percentages.len() > quorum_number as usize { + return Ok(percentages[quorum_number as usize]); } Ok(0) } @@ -452,30 +452,15 @@ impl Verifier { .await .map_err(|_| VerificationError::ServiceManagerError)?; - let fn_quorum_numbers_required = self - .contract - .function("quorumNumbersRequired") - .map_err(|_| VerificationError::ServiceManagerError)?; - - let required_quorums = fn_quorum_numbers_required - .decode_output(&res.0) + let required_quorums = self + .decode_bytes(res.0.to_vec()) .map_err(|_| VerificationError::ServiceManagerError)?; - if required_quorums.len() != 1 { - return Err(VerificationError::ServiceManagerError); - } - - match required_quorums[0].clone() { - Token::Bytes(quorums) => { - for quorum in quorums { - if !confirmed_quorums.contains_key(&(quorum as u32)) { - return Err(VerificationError::QuorumNotConfirmed); - } - } + for quorum in required_quorums { + if !confirmed_quorums.contains_key(&(quorum as u32)) { + return Err(VerificationError::QuorumNotConfirmed); } - _ => return Err(VerificationError::ServiceManagerError), } - Ok(()) }