Skip to content

Commit

Permalink
dev(better_theoros): Works with N signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
akhercha committed Nov 2, 2024
1 parent 4430538 commit 653d3dd
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 24 deletions.
11 changes: 11 additions & 0 deletions rust/theoros/src/rpc/evm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,15 @@ impl HyperlaneValidatorsMapping {
pub fn chain_names(&self) -> Vec<EvmChainName> {
self.0.keys().cloned().collect()
}

/// Get the index of a validator for a chain
pub fn validator_index(&self, chain_name: &EvmChainName, searched_validator: &Felt) -> Option<u8> {
match self.0.get(chain_name) {
Some(validators) => validators
.iter()
.position(|validator| validator == searched_validator)
.and_then(|pos| pos.try_into().ok()),
None => None,
}
}
}
4 changes: 2 additions & 2 deletions rust/theoros/src/storage/checkpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@ impl SignedCheckpointsStorage {

// For the provided list of validators, returns all their signed checkpoints for the
// provided message_id.
pub async fn get(&self, validators: &[Felt], searched_nonce: u32) -> Vec<SignedCheckpointWithMessageId> {
pub async fn get(&self, validators: &[Felt], searched_nonce: u32) -> Vec<(Felt, SignedCheckpointWithMessageId)> {
let lock = self.0.read().await;

let mut checkpoints = Vec::new();
// Iterate over the map with tuple key (validator, message_id)
for ((validator, nonce), checkpoint) in lock.iter() {
// Only include if validator is in the provided list and message_id matches
if nonce == &searched_nonce && validators.contains(validator) {
checkpoints.push(checkpoint.clone());
checkpoints.push((*validator, checkpoint.clone()));
}
}

Expand Down
48 changes: 26 additions & 22 deletions rust/theoros/src/types/calldata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::str::FromStr;
use crate::{
configs::evm_config::EvmChainName,
constants::{HYPERLANE_VERSION, PRAGMA_MAJOR_VERSION, PRAGMA_MINOR_VERSION, TRAILING_HEADER_SIZE},
types::hyperlane::{CheckpointWithMessageId, DispatchUpdate, DispatchUpdateInfos},
types::hyperlane::{CheckpointWithMessageId, DispatchUpdate},
types::state::AppState,
};

Expand All @@ -32,36 +32,44 @@ pub struct Calldata {

impl Calldata {
pub async fn build_from(state: &AppState, chain_name: EvmChainName, feed_id: String) -> anyhow::Result<Calldata> {
let update_info: DispatchUpdateInfos = state
// Get latest update for this feed
let update_info = state
.storage
.latest_update_per_feed()
.get(&hex_str_to_u256(&feed_id).unwrap())
.get(&hex_str_to_u256(&feed_id)?)
.await?
.context("No update found")?;

// Get validators and their signatures
let validators =
state.hyperlane_validators_mapping.get_validators(chain_name).context("No validators found")?;

let checkpoints = state.storage.signed_checkpoints().get(validators, update_info.nonce).await;

let checkpoint_infos = checkpoints.last().unwrap();

anyhow::ensure!(!checkpoints.is_empty(), "No signatures found");

let signatures: Vec<ValidatorSignature> = checkpoints
.iter()
.filter_map(|(validator, signed_checkpoint)| {
state
.hyperlane_validators_mapping
.validator_index(&chain_name, validator)
.map(|idx| ValidatorSignature { validator_index: idx, signature: signed_checkpoint.signature })
})
.collect();

// Build payload using first checkpoint (all validators sign the same checkpoint since it's the same nonce)
let update = match update_info.update {
DispatchUpdate::SpotMedian { update, feed_id: _ } => update,
DispatchUpdate::SpotMedian { update, .. } => update,
};

let payload = Payload {
checkpoint: checkpoint_infos.value.clone(),
// TODO: We only handle 1 update per calldata. See if possible to have more.
// TODO: If not remove this and consider it to be always one?
checkpoint: checkpoints[0].1.value.clone(),
num_updates: 1,
// TODO: Remove proof
proof_len: 0,
proof: vec![],
update_data_len: update.to_bytes().len() as u16,
update_data: update.to_bytes(),
feed_id: U256::from_str(&feed_id).unwrap(),
// TODO: publish_time is already available in the update metadata. Remove.
feed_id: U256::from_str(&feed_id)?,
publish_time: update.metadata.timestamp,
};

Expand All @@ -70,23 +78,19 @@ impl Calldata {
emitter_chain_id: update_info.emitter_chain_id,
emitter_address: update_info.emitter_address,
nonce: update_info.nonce,
// TODO: Adapt for N signers
signers_len: 1_u8,
signatures: vec![ValidatorSignature { validator_index: 0, signature: checkpoint_infos.signature }],
// TODO: Means we store once again the timestamp? Delete this?
signers_len: signatures.len() as u8,
signatures,
timestamp: update.metadata.timestamp,
payload,
};

let calldata = Calldata {
Ok(Calldata {
major_version: PRAGMA_MAJOR_VERSION,
minor_version: PRAGMA_MINOR_VERSION,
trailing_header_size: TRAILING_HEADER_SIZE,
hyperlane_msg_size: hyperlane_message.as_bytes().len().try_into().unwrap(),
hyperlane_msg_size: hyperlane_message.as_bytes().len().try_into()?,
hyperlane_msg: hyperlane_message,
};

Ok(calldata)
})
}
}

Expand Down

0 comments on commit 653d3dd

Please sign in to comment.