diff --git a/bolt-sidecar/src/chain_io/manager.rs b/bolt-sidecar/src/chain_io/manager.rs index 8479e7bdb..bf4c01174 100644 --- a/bolt-sidecar/src/chain_io/manager.rs +++ b/bolt-sidecar/src/chain_io/manager.rs @@ -53,56 +53,70 @@ impl BoltManager { commitment_signer_pubkey: Address, ) -> eyre::Result> { let hashes_with_preimages = utils::pubkey_hashes(keys); - let hashes = hashes_with_preimages.keys().cloned().collect::>(); + let mut hashes = hashes_with_preimages.keys().cloned().collect::>(); - let returndata = self.0.getProposerStatuses(hashes).call().await; + let mut proposers_statuses = Vec::with_capacity(hashes.len()); - // TODO: clean this after https://github.com/alloy-rs/alloy/issues/787 is merged - let error = match returndata.map(|data| data.statuses) { - Ok(statuses) => { - for status in &statuses { - if !status.active { - bail!( + while !hashes.is_empty() { + // No more than 1_000 at a time to avoid EL config limits + // + // TODO: write an unsafe function that splits a vec into owned chunks without + // allocating + let hashes_chunk = hashes.drain(..1_000.min(hashes.len())).collect::>(); + + let returndata = self.0.getProposerStatuses(hashes_chunk).call().await; + + // TODO: clean this after https://github.com/alloy-rs/alloy/issues/787 is merged + let error = match returndata.map(|data| data.statuses) { + Ok(statuses) => { + for status in &statuses { + if !status.active { + bail!( "validator with public key {:?} and public key hash {:?} is not active in Bolt", hashes_with_preimages.get(&status.pubkeyHash), status.pubkeyHash ); - } else if status.operator != commitment_signer_pubkey { - bail!(generate_operator_keys_mismatch_error( - status.pubkeyHash, - commitment_signer_pubkey, - status.operator - )); + } else if status.operator != commitment_signer_pubkey { + bail!(generate_operator_keys_mismatch_error( + status.pubkeyHash, + commitment_signer_pubkey, + status.operator + )); + } } - } - return Ok(statuses); - } - Err(error) => match error { - ContractError::TransportError(TransportError::ErrorResp(err)) => { - let data = err.data.unwrap_or_default(); - let data = data.get().trim_matches('"'); - let data = Bytes::from_str(data)?; + proposers_statuses.extend(statuses); - BoltManagerContractErrors::abi_decode(&data, true)? + continue; + } + Err(error) => match error { + ContractError::TransportError(TransportError::ErrorResp(err)) => { + let data = err.data.unwrap_or_default(); + let data = data.get().trim_matches('"'); + let data = Bytes::from_str(data)?; + + BoltManagerContractErrors::abi_decode(&data, true)? + } + e => return Err(e)?, + }, + }; + + match error { + BoltManagerContractErrors::ValidatorDoesNotExist(ValidatorDoesNotExist { + pubkeyHash: pubkey_hash, + }) => { + bail!("ValidatorDoesNotExist -- validator with public key {:?} and public key hash {:?} is not registered in Bolt", hashes_with_preimages.get(&pubkey_hash), pubkey_hash); + } + BoltManagerContractErrors::InvalidQuery(_) => { + bail!("InvalidQuery -- invalid zero public key hash"); + } + BoltManagerContractErrors::KeyNotFound(_) => { + bail!("KeyNotFound -- operator associated with commitment signer public key {:?} is not registered in Bolt", commitment_signer_pubkey); } - e => return Err(e)?, - }, - }; - - match error { - BoltManagerContractErrors::ValidatorDoesNotExist(ValidatorDoesNotExist { - pubkeyHash: pubkey_hash, - }) => { - bail!("ValidatorDoesNotExist -- validator with public key {:?} and public key hash {:?} is not registered in Bolt", hashes_with_preimages.get(&pubkey_hash), pubkey_hash); - } - BoltManagerContractErrors::InvalidQuery(_) => { - bail!("InvalidQuery -- invalid zero public key hash"); - } - BoltManagerContractErrors::KeyNotFound(_) => { - bail!("KeyNotFound -- operator associated with commitment signer public key {:?} is not registered in Bolt", commitment_signer_pubkey); } } + + Ok(proposers_statuses) } } @@ -159,6 +173,7 @@ mod tests { use super::BoltManager; #[tokio::test] + #[ignore = "requires Chainbound tailnet"] async fn test_verify_validator_pubkeys() { let url = Url::parse("http://remotebeast:48545").expect("valid url"); let manager =