Skip to content

Commit

Permalink
Merge pull request #349 from chainbound/lore/chore/batch-contract-calls
Browse files Browse the repository at this point in the history
fix(sidecar): split public key hashes into chunks to avoid EL limits
  • Loading branch information
thedevbirb authored Oct 31, 2024
2 parents cc2e330 + 1ac5084 commit 1599420
Showing 1 changed file with 53 additions and 38 deletions.
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

0 comments on commit 1599420

Please sign in to comment.