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

fix(sidecar): split public key hashes into chunks to avoid EL limits #349

Merged
merged 2 commits into from
Oct 31, 2024
Merged
Changes from all 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
91 changes: 53 additions & 38 deletions bolt-sidecar/src/chain_io/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,56 +53,70 @@ impl BoltManager {
commitment_signer_pubkey: Address,
) -> eyre::Result<Vec<ProposerStatus>> {
let hashes_with_preimages = utils::pubkey_hashes(keys);
let hashes = hashes_with_preimages.keys().cloned().collect::<Vec<_>>();
let mut hashes = hashes_with_preimages.keys().cloned().collect::<Vec<_>>();

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::<Vec<_>>();

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)
}
}

Expand Down Expand Up @@ -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 =
Expand Down
Loading