|
|
|
@ -9,7 +9,7 @@ use std::time::{Duration, Instant}; |
|
|
|
|
use async_trait::async_trait; |
|
|
|
|
use ethers::abi::Token; |
|
|
|
|
use ethers::providers::Middleware; |
|
|
|
|
use ethers::types::{Selector, H160, H256, U256}; |
|
|
|
|
use ethers::types::{Selector, H160, H256}; |
|
|
|
|
use eyre::Result; |
|
|
|
|
use tokio::sync::RwLock; |
|
|
|
|
use tracing::instrument; |
|
|
|
@ -112,7 +112,7 @@ where |
|
|
|
|
chain_name: String, |
|
|
|
|
#[allow(dead_code)] |
|
|
|
|
provider: Arc<M>, |
|
|
|
|
threshold_cache: RwLock<ExpiringCache<u32, U256>>, |
|
|
|
|
threshold_cache: RwLock<ExpiringCache<u32, u8>>, |
|
|
|
|
validators_cache: RwLock<ExpiringCache<u32, Vec<H160>>>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -170,23 +170,16 @@ where |
|
|
|
|
checkpoint: &MultisigSignedCheckpoint, |
|
|
|
|
proof: Proof, |
|
|
|
|
) -> Result<Vec<u8>, ChainCommunicationError> { |
|
|
|
|
let threshold = self.threshold(checkpoint.checkpoint.mailbox_domain).await?; |
|
|
|
|
let validator_addresses: Vec<H160> = self |
|
|
|
|
.validators(checkpoint.checkpoint.mailbox_domain) |
|
|
|
|
.await?; |
|
|
|
|
let validators: Vec<H256> = validator_addresses.iter().map(|&x| H256::from(x)).collect(); |
|
|
|
|
let validator_tokens: Vec<Token> = validators |
|
|
|
|
.iter() |
|
|
|
|
.map(|x| Token::FixedBytes(x.to_fixed_bytes().into())) |
|
|
|
|
.collect(); |
|
|
|
|
let root_bytes = checkpoint.checkpoint.root.to_fixed_bytes().into(); |
|
|
|
|
|
|
|
|
|
let index_bytes = checkpoint.checkpoint.index.to_be_bytes().into(); |
|
|
|
|
|
|
|
|
|
let proof_tokens: Vec<Token> = proof |
|
|
|
|
.path |
|
|
|
|
.iter() |
|
|
|
|
.map(|x| Token::FixedBytes(x.to_fixed_bytes().into())) |
|
|
|
|
.collect(); |
|
|
|
|
let prefix = ethers::abi::encode(&[ |
|
|
|
|
Token::FixedBytes(checkpoint.checkpoint.root.to_fixed_bytes().into()), |
|
|
|
|
Token::Uint(U256::from(checkpoint.checkpoint.index)), |
|
|
|
|
let mailbox_and_proof_bytes = ethers::abi::encode(&[ |
|
|
|
|
Token::FixedBytes( |
|
|
|
|
checkpoint |
|
|
|
|
.checkpoint |
|
|
|
@ -195,20 +188,42 @@ where |
|
|
|
|
.into(), |
|
|
|
|
), |
|
|
|
|
Token::FixedArray(proof_tokens), |
|
|
|
|
Token::Uint(threshold), |
|
|
|
|
]); |
|
|
|
|
let suffix = ethers::abi::encode(&[Token::FixedArray(validator_tokens)]); |
|
|
|
|
|
|
|
|
|
let threshold = self.threshold(checkpoint.checkpoint.mailbox_domain).await?; |
|
|
|
|
let threshold_bytes = threshold.to_be_bytes().into(); |
|
|
|
|
|
|
|
|
|
let validator_addresses: Vec<H160> = self |
|
|
|
|
.validators(checkpoint.checkpoint.mailbox_domain) |
|
|
|
|
.await?; |
|
|
|
|
|
|
|
|
|
// The ethers encoder likes to zero-pad non word-aligned byte arrays.
|
|
|
|
|
// Thus, we pack the signatures, which are not word-aligned, ourselves.
|
|
|
|
|
let signature_vecs: Vec<Vec<u8>> = |
|
|
|
|
order_signatures(&validator_addresses, &checkpoint.signatures); |
|
|
|
|
let signature_bytes = signature_vecs.concat(); |
|
|
|
|
let metadata = [prefix, signature_bytes, suffix].concat(); |
|
|
|
|
|
|
|
|
|
let validators: Vec<H256> = validator_addresses.iter().map(|&x| H256::from(x)).collect(); |
|
|
|
|
let validator_tokens: Vec<Token> = validators |
|
|
|
|
.iter() |
|
|
|
|
.map(|x| Token::FixedBytes(x.to_fixed_bytes().into())) |
|
|
|
|
.collect(); |
|
|
|
|
let validator_bytes = ethers::abi::encode(&[Token::FixedArray(validator_tokens)]); |
|
|
|
|
|
|
|
|
|
let metadata = [ |
|
|
|
|
root_bytes, |
|
|
|
|
index_bytes, |
|
|
|
|
mailbox_and_proof_bytes, |
|
|
|
|
threshold_bytes, |
|
|
|
|
signature_bytes, |
|
|
|
|
validator_bytes, |
|
|
|
|
] |
|
|
|
|
.concat(); |
|
|
|
|
Ok(metadata) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[instrument(err, ret, skip(self))] |
|
|
|
|
async fn threshold(&self, domain: u32) -> Result<U256, ChainCommunicationError> { |
|
|
|
|
async fn threshold(&self, domain: u32) -> Result<u8, ChainCommunicationError> { |
|
|
|
|
let entry = self.threshold_cache.read().await.get(domain).cloned(); |
|
|
|
|
if let Some(threshold) = entry { |
|
|
|
|
Ok(threshold) |
|
|
|
|