|
|
|
@ -4,16 +4,162 @@ use ethers_core::types::{Address, H256, U256}; |
|
|
|
|
use std::sync::Arc; |
|
|
|
|
|
|
|
|
|
use optics_core::{ |
|
|
|
|
traits::{ChainCommunicationError, Common, Home, State, TxOutcome}, |
|
|
|
|
Message, SignedUpdate, Update, |
|
|
|
|
traits::{ChainCommunicationError, Common, Home, Replica, State, TxOutcome}, |
|
|
|
|
Encode, Message, SignedUpdate, Update, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
abigen!( |
|
|
|
|
ReplicaContractInternal, |
|
|
|
|
"src/abis/ProcessingReplica.abi.json" |
|
|
|
|
"optics-base/src/abis/ProcessingReplica.abi.json" |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
abigen!(HomeContractInternal, "src/abis/Home.abi.json"); |
|
|
|
|
#[derive(Debug)] |
|
|
|
|
pub struct ReplicaContract<M> |
|
|
|
|
where |
|
|
|
|
M: ethers_providers::Middleware, |
|
|
|
|
{ |
|
|
|
|
contract: ReplicaContractInternal<M>, |
|
|
|
|
slip44: u32, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[async_trait] |
|
|
|
|
impl<M> Common for ReplicaContract<M> |
|
|
|
|
where |
|
|
|
|
M: ethers_providers::Middleware + 'static, |
|
|
|
|
{ |
|
|
|
|
async fn status(&self, txid: H256) -> Result<Option<TxOutcome>, ChainCommunicationError> { |
|
|
|
|
let receipt_opt = self |
|
|
|
|
.contract |
|
|
|
|
.client() |
|
|
|
|
.get_transaction_receipt(txid) |
|
|
|
|
.await |
|
|
|
|
.map_err(|e| ChainCommunicationError::CustomError(Box::new(e)))?; |
|
|
|
|
|
|
|
|
|
Ok(receipt_opt.map(Into::into)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn origin_slip44(&self) -> u32 { |
|
|
|
|
self.slip44 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn updater(&self) -> Result<H256, ChainCommunicationError> { |
|
|
|
|
Ok(self.contract.updater().call().await?.into()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn state(&self) -> Result<State, ChainCommunicationError> { |
|
|
|
|
let state = self.contract.state().call().await?; |
|
|
|
|
match state { |
|
|
|
|
0 => Ok(State::Waiting), |
|
|
|
|
1 => Ok(State::Failed), |
|
|
|
|
_ => unreachable!(), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn current_root(&self) -> Result<H256, ChainCommunicationError> { |
|
|
|
|
Ok(self.contract.current().call().await?.into()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn update(&self, update: &SignedUpdate) -> Result<TxOutcome, ChainCommunicationError> { |
|
|
|
|
Ok(self |
|
|
|
|
.contract |
|
|
|
|
.update( |
|
|
|
|
update.update.previous_root.to_fixed_bytes(), |
|
|
|
|
update.update.new_root.to_fixed_bytes(), |
|
|
|
|
update.signature.to_vec(), |
|
|
|
|
) |
|
|
|
|
.send() |
|
|
|
|
.await? |
|
|
|
|
.await? |
|
|
|
|
.into()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn double_update( |
|
|
|
|
&self, |
|
|
|
|
left: &SignedUpdate, |
|
|
|
|
right: &SignedUpdate, |
|
|
|
|
) -> Result<TxOutcome, ChainCommunicationError> { |
|
|
|
|
Ok(self |
|
|
|
|
.contract |
|
|
|
|
.double_update( |
|
|
|
|
[ |
|
|
|
|
left.update.previous_root.to_fixed_bytes(), |
|
|
|
|
right.update.previous_root.to_fixed_bytes(), |
|
|
|
|
], |
|
|
|
|
[ |
|
|
|
|
left.update.new_root.to_fixed_bytes(), |
|
|
|
|
right.update.new_root.to_fixed_bytes(), |
|
|
|
|
], |
|
|
|
|
left.signature.to_vec(), |
|
|
|
|
right.signature.to_vec(), |
|
|
|
|
) |
|
|
|
|
.send() |
|
|
|
|
.await? |
|
|
|
|
.await? |
|
|
|
|
.into()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[async_trait] |
|
|
|
|
impl<M> Replica for ReplicaContract<M> |
|
|
|
|
where |
|
|
|
|
M: ethers_providers::Middleware + 'static, |
|
|
|
|
{ |
|
|
|
|
async fn pending(&self) -> Result<Option<(H256, U256)>, ChainCommunicationError> { |
|
|
|
|
let pending = self.contract.pending(); |
|
|
|
|
let confirm_at = self.contract.confirm_at(); |
|
|
|
|
|
|
|
|
|
let (pending, confirm_at) = tokio::join!(pending.call(), confirm_at.call()); |
|
|
|
|
let pending = pending?; |
|
|
|
|
let confirm_at = confirm_at?; |
|
|
|
|
|
|
|
|
|
if confirm_at.is_zero() { |
|
|
|
|
Ok(None) |
|
|
|
|
} else { |
|
|
|
|
Ok(Some((pending.into(), confirm_at))) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn confirm(&self) -> Result<TxOutcome, ChainCommunicationError> { |
|
|
|
|
Ok(self.contract.confirm().send().await?.await?.into()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn previous_root(&self) -> Result<H256, ChainCommunicationError> { |
|
|
|
|
Ok(self.contract.previous().call().await?.into()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn prove( |
|
|
|
|
&self, |
|
|
|
|
leaf: H256, |
|
|
|
|
index: u32, |
|
|
|
|
proof: [H256; 32], |
|
|
|
|
) -> Result<TxOutcome, ChainCommunicationError> { |
|
|
|
|
let mut sol_proof: [[u8; 32]; 32] = Default::default(); |
|
|
|
|
sol_proof |
|
|
|
|
.iter_mut() |
|
|
|
|
.enumerate() |
|
|
|
|
.for_each(|(i, elem)| *elem = proof[i].to_fixed_bytes()); |
|
|
|
|
|
|
|
|
|
Ok(self |
|
|
|
|
.contract |
|
|
|
|
.prove(leaf.into(), sol_proof, index.into()) |
|
|
|
|
.send() |
|
|
|
|
.await? |
|
|
|
|
.await? |
|
|
|
|
.into()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn process(&self, message: &Message) -> Result<TxOutcome, ChainCommunicationError> { |
|
|
|
|
Ok(self |
|
|
|
|
.contract |
|
|
|
|
.process(message.to_vec()) |
|
|
|
|
.send() |
|
|
|
|
.await? |
|
|
|
|
.await? |
|
|
|
|
.into()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
abigen!(HomeContractInternal, "optics-base/src/abis/Home.abi.json"); |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
pub struct HomeContract<M> |
|
|
|
@ -131,7 +277,7 @@ where |
|
|
|
|
.query() |
|
|
|
|
.await?; |
|
|
|
|
|
|
|
|
|
Ok(filters.into_iter().next().map(|f| f.message.clone())) |
|
|
|
|
Ok(filters.into_iter().next().map(|f| f.message)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fn sequences(&self, destination: u32) -> Result<u32, ChainCommunicationError> { |
|
|
|
|