Remove vestigial agent files (#1324)

pull/1330/head
Asa Oines 2 years ago committed by GitHub
parent 12f1305817
commit 5e7ff47857
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 78
      rust/abacus-base/src/inbox.rs
  2. 169
      rust/abacus-base/src/outbox.rs
  3. 25
      rust/abacus-core/src/traits/inbox.rs
  4. 240
      rust/chains/abacus-ethereum/src/inbox.rs
  5. 323
      rust/chains/abacus-ethereum/src/outbox.rs
  6. 208
      rust/chains/abacus-ethereum/src/validator_manager.rs

@ -1,78 +0,0 @@
use std::sync::Arc;
use async_trait::async_trait;
use ethers::core::types::H256;
use eyre::Result;
use abacus_core::{
db::AbacusDB, AbacusChain, AbacusCommon, AbacusContract, Address, ChainCommunicationError,
Inbox, MessageStatus,
};
/// Caching inbox type.
#[derive(Debug, Clone)]
pub struct CachingInbox {
inbox: Arc<dyn Inbox>,
db: AbacusDB,
}
impl std::fmt::Display for CachingInbox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl CachingInbox {
/// Instantiate new CachingInbox
pub fn new(inbox: Arc<dyn Inbox>, db: AbacusDB) -> Self {
Self { inbox, db }
}
/// Return handle on inbox object
pub fn inbox(&self) -> &Arc<dyn Inbox> {
&self.inbox
}
/// Return handle on AbacusDB
pub fn db(&self) -> &AbacusDB {
&self.db
}
}
#[async_trait]
impl Inbox for CachingInbox {
fn remote_domain(&self) -> u32 {
self.inbox.remote_domain()
}
async fn message_status(&self, leaf: H256) -> Result<MessageStatus, ChainCommunicationError> {
self.inbox.message_status(leaf).await
}
fn contract_address(&self) -> Address {
self.inbox.contract_address()
}
}
impl AbacusChain for CachingInbox {
fn chain_name(&self) -> &str {
self.inbox.chain_name()
}
fn local_domain(&self) -> u32 {
self.inbox.local_domain()
}
}
impl AbacusContract for CachingInbox {
fn address(&self) -> H256 {
self.inbox.address()
}
}
#[async_trait]
impl AbacusCommon for CachingInbox {
async fn validator_manager(&self) -> Result<H256, ChainCommunicationError> {
self.inbox.validator_manager().await
}
}

@ -1,169 +0,0 @@
use std::fmt::Debug;
use std::sync::Arc;
use async_trait::async_trait;
use ethers::core::types::H256;
use eyre::Result;
use futures_util::future::select_all;
use tokio::task::JoinHandle;
use tokio::time::{sleep, Duration};
use tracing::instrument::Instrumented;
use tracing::{info_span, Instrument};
use abacus_core::db::AbacusDB;
use abacus_core::{
AbacusChain, AbacusCommon, AbacusContract, ChainCommunicationError, Checkpoint, Message,
Outbox, OutboxEvents, OutboxIndexer, OutboxState, RawCommittedMessage, TxOutcome,
};
use crate::{ContractSync, ContractSyncMetrics, IndexSettings};
/// Caching Outbox type
#[derive(Debug, Clone)]
pub struct CachingOutbox {
outbox: Arc<dyn Outbox>,
db: AbacusDB,
indexer: Arc<dyn OutboxIndexer>,
}
impl std::fmt::Display for CachingOutbox {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl CachingOutbox {
/// Instantiate new CachingOutbox
pub fn new(outbox: Arc<dyn Outbox>, db: AbacusDB, indexer: Arc<dyn OutboxIndexer>) -> Self {
Self {
outbox,
db,
indexer,
}
}
/// Return handle on outbox object
pub fn outbox(&self) -> &Arc<dyn Outbox> {
&self.outbox
}
/// Return handle on AbacusDB
pub fn db(&self) -> &AbacusDB {
&self.db
}
/// Spawn a task that syncs the CachingOutbox's db with the on-chain event
/// data
pub fn sync(
&self,
index_settings: IndexSettings,
metrics: ContractSyncMetrics,
) -> Instrumented<JoinHandle<Result<()>>> {
let span = info_span!("OutboxContractSync", self = %self);
let sync = ContractSync::new(
self.outbox.chain_name().into(),
self.db.clone(),
self.indexer.clone(),
index_settings,
metrics,
);
tokio::spawn(async move {
let tasks = vec![sync.sync_outbox_messages()];
let (_, _, remaining) = select_all(tasks).await;
for task in remaining.into_iter() {
cancel_task!(task);
}
Ok(())
})
.instrument(span)
}
}
#[async_trait]
impl Outbox for CachingOutbox {
async fn state(&self) -> Result<OutboxState, ChainCommunicationError> {
self.outbox.state().await
}
async fn count(&self) -> Result<u32, ChainCommunicationError> {
self.outbox.count().await
}
async fn dispatch(&self, message: &Message) -> Result<TxOutcome, ChainCommunicationError> {
self.outbox.dispatch(message).await
}
async fn cache_checkpoint(&self) -> Result<TxOutcome, ChainCommunicationError> {
self.outbox.cache_checkpoint().await
}
async fn latest_cached_root(&self) -> Result<H256, ChainCommunicationError> {
self.outbox.latest_cached_root().await
}
async fn latest_cached_checkpoint(&self) -> Result<Checkpoint, ChainCommunicationError> {
self.outbox.latest_cached_checkpoint().await
}
async fn latest_checkpoint(
&self,
maybe_lag: Option<u64>,
) -> Result<Checkpoint, ChainCommunicationError> {
self.outbox.latest_checkpoint(maybe_lag).await
}
}
#[async_trait]
impl OutboxEvents for CachingOutbox {
#[tracing::instrument(err, skip(self))]
async fn raw_message_by_leaf(
&self,
leaf: H256,
) -> Result<Option<RawCommittedMessage>, ChainCommunicationError> {
loop {
if let Some(message) = self.db.message_by_leaf(leaf)? {
return Ok(Some(message));
}
sleep(Duration::from_millis(500)).await;
}
}
async fn leaf_by_tree_index(
&self,
tree_index: usize,
) -> Result<Option<H256>, ChainCommunicationError> {
loop {
if let Some(leaf) = self.db.leaf_by_leaf_index(tree_index as u32)? {
return Ok(Some(leaf));
}
sleep(Duration::from_millis(500)).await;
}
}
}
impl AbacusChain for CachingOutbox {
fn chain_name(&self) -> &str {
self.outbox.chain_name()
}
fn local_domain(&self) -> u32 {
self.outbox.local_domain()
}
}
impl AbacusContract for CachingOutbox {
fn address(&self) -> H256 {
self.outbox.address()
}
}
#[async_trait]
impl AbacusCommon for CachingOutbox {
async fn validator_manager(&self) -> Result<H256, ChainCommunicationError> {
self.outbox.validator_manager().await
}
}

@ -1,25 +0,0 @@
use std::fmt::Debug;
use async_trait::async_trait;
use auto_impl::auto_impl;
use ethers::core::types::H256;
use eyre::Result;
use crate::{
traits::{AbacusCommon, ChainCommunicationError},
Address, MessageStatus,
};
/// Interface for on-chain inboxes
#[async_trait]
#[auto_impl(Box, Arc)]
pub trait Inbox: AbacusCommon + Send + Sync + Debug {
/// Return the domain of the inbox's linked outbox
fn remote_domain(&self) -> u32;
/// Fetch the status of a message
async fn message_status(&self, leaf: H256) -> Result<MessageStatus, ChainCommunicationError>;
/// The on-chain address of the inbox contract.
fn contract_address(&self) -> Address;
}

@ -1,240 +0,0 @@
#![allow(clippy::enum_variant_names)]
#![allow(missing_docs)]
use std::collections::HashMap;
use std::fmt::{self, Debug, Display};
use std::sync::Arc;
use async_trait::async_trait;
use ethers::prelude::*;
use eyre::Result;
use tracing::instrument;
use abacus_core::{
AbacusAbi, AbacusChain, AbacusCommon, AbacusContract, Address, ChainCommunicationError,
ContractLocator, Inbox, InboxIndexer, Indexer, MessageStatus,
};
use crate::contracts::inbox::{Inbox as EthereumInboxInternal, INBOX_ABI};
use crate::trait_builder::MakeableWithProvider;
impl<M> Display for EthereumInboxInternal<M>
where
M: Middleware,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
pub struct InboxBuilder {}
#[async_trait]
impl MakeableWithProvider for InboxBuilder {
type Output = Box<dyn Inbox>;
async fn make_with_provider<M: Middleware + 'static>(
&self,
provider: M,
locator: &ContractLocator,
) -> Self::Output {
Box::new(EthereumInbox::new(Arc::new(provider), locator).await)
}
}
pub struct InboxIndexerBuilder {
pub finality_blocks: u32,
}
#[async_trait]
impl MakeableWithProvider for InboxIndexerBuilder {
type Output = Box<dyn InboxIndexer>;
async fn make_with_provider<M: Middleware + 'static>(
&self,
provider: M,
locator: &ContractLocator,
) -> Self::Output {
Box::new(EthereumInboxIndexer::new(
Arc::new(provider),
locator,
self.finality_blocks,
))
}
}
#[derive(Debug)]
pub struct EthereumInboxIndexer<M>
where
M: Middleware,
{
contract: Arc<EthereumInboxInternal<M>>,
provider: Arc<M>,
finality_blocks: u32,
}
impl<M> EthereumInboxIndexer<M>
where
M: Middleware + 'static,
{
pub fn new(provider: Arc<M>, locator: &ContractLocator, finality_blocks: u32) -> Self {
let contract = Arc::new(EthereumInboxInternal::new(
&locator.address,
provider.clone(),
));
Self {
contract,
provider,
finality_blocks,
}
}
}
#[async_trait]
impl<M> Indexer for EthereumInboxIndexer<M>
where
M: Middleware + 'static,
{
async fn get_finalized_block_number(&self) -> Result<u32> {
Ok(self
.provider
.get_block_number()
.await?
.as_u32()
.saturating_sub(self.finality_blocks))
}
}
#[async_trait]
impl<M> InboxIndexer for EthereumInboxIndexer<M>
where
M: Middleware + 'static,
{
#[instrument(err, skip(self))]
async fn fetch_processed_messages(
&self,
from: u32,
to: u32,
) -> Result<Vec<(H256, abacus_core::LogMeta)>> {
Ok(self
.contract
.process_filter()
.from_block(from)
.to_block(to)
.query_with_meta()
.await?
.into_iter()
.map(|(event, meta)| (H256::from(event.message_hash), meta.into()))
.collect())
}
}
/// A struct that provides access to an Ethereum inbox contract
#[derive(Debug)]
pub struct EthereumInbox<M>
where
M: Middleware,
{
contract: Arc<EthereumInboxInternal<M>>,
remote_domain: u32,
chain_name: String,
local_domain: u32,
}
impl<M> EthereumInbox<M>
where
M: Middleware,
{
/// Create a reference to a inbox at a specific Ethereum address on some
/// chain
pub async fn new(
provider: Arc<M>,
ContractLocator {
chain_name,
domain,
address,
}: &ContractLocator,
) -> Self {
let contract = Arc::new(EthereumInboxInternal::new(address, provider));
let remote_domain = contract
.remote_domain()
.call()
.await
.expect("Failed to get inbox's local_domain");
debug_assert_eq!(
contract
.local_domain()
.call()
.await
.expect("Failed to get inbox's remote_domain"),
*domain
);
Self {
contract,
remote_domain,
local_domain: *domain,
chain_name: chain_name.to_owned(),
}
}
}
impl<M> AbacusChain for EthereumInbox<M>
where
M: Middleware + 'static,
{
fn chain_name(&self) -> &str {
&self.chain_name
}
fn local_domain(&self) -> u32 {
self.local_domain
}
}
impl<M> AbacusContract for EthereumInbox<M>
where
M: Middleware + 'static,
{
fn address(&self) -> H256 {
self.contract.address().into()
}
}
#[async_trait]
impl<M> AbacusCommon for EthereumInbox<M>
where
M: Middleware + 'static,
{
#[tracing::instrument(err)]
async fn validator_manager(&self) -> Result<H256, ChainCommunicationError> {
Ok(self.contract.validator_manager().call().await?.into())
}
}
#[async_trait]
impl<M> Inbox for EthereumInbox<M>
where
M: Middleware + 'static,
{
fn remote_domain(&self) -> u32 {
self.remote_domain
}
#[tracing::instrument(err)]
async fn message_status(&self, leaf: H256) -> Result<MessageStatus, ChainCommunicationError> {
let status = self.contract.messages(leaf.into()).call().await?;
Ok(MessageStatus::try_from(status).expect("Bad status from solidity"))
}
fn contract_address(&self) -> Address {
self.contract.address().into()
}
}
pub struct EthereumInboxAbi;
impl AbacusAbi for EthereumInboxAbi {
fn fn_map() -> HashMap<Selector, &'static str> {
super::extract_fn_map(&INBOX_ABI)
}
}

@ -1,323 +0,0 @@
#![allow(clippy::enum_variant_names)]
#![allow(missing_docs)]
use std::collections::HashMap;
use std::sync::Arc;
use async_trait::async_trait;
use ethers::prelude::*;
use eyre::Result;
use tracing::instrument;
use abacus_core::{
AbacusAbi, AbacusChain, AbacusCommon, AbacusContract, ChainCommunicationError, Checkpoint,
ContractLocator, Indexer, LogMeta, Message, Outbox, OutboxIndexer, OutboxState,
RawCommittedMessage, TxOutcome,
};
use crate::contracts::outbox::{Outbox as EthereumOutboxInternal, OUTBOX_ABI};
use crate::trait_builder::MakeableWithProvider;
use crate::tx::report_tx;
impl<M> std::fmt::Display for EthereumOutboxInternal<M>
where
M: Middleware,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub struct OutboxIndexerBuilder {
pub finality_blocks: u32,
}
#[async_trait]
impl MakeableWithProvider for OutboxIndexerBuilder {
type Output = Box<dyn OutboxIndexer>;
async fn make_with_provider<M: Middleware + 'static>(
&self,
provider: M,
locator: &ContractLocator,
) -> Self::Output {
Box::new(EthereumOutboxIndexer::new(
Arc::new(provider),
locator,
self.finality_blocks,
))
}
}
#[derive(Debug)]
/// Struct that retrieves event data for an Ethereum outbox
pub struct EthereumOutboxIndexer<M>
where
M: Middleware,
{
contract: Arc<EthereumOutboxInternal<M>>,
provider: Arc<M>,
finality_blocks: u32,
outbox_domain: u32,
}
impl<M> EthereumOutboxIndexer<M>
where
M: Middleware + 'static,
{
/// Create new EthereumOutboxIndexer
pub fn new(provider: Arc<M>, locator: &ContractLocator, finality_blocks: u32) -> Self {
let contract = Arc::new(EthereumOutboxInternal::new(
&locator.address,
provider.clone(),
));
Self {
contract,
provider,
finality_blocks,
outbox_domain: locator.domain,
}
}
}
#[async_trait]
impl<M> Indexer for EthereumOutboxIndexer<M>
where
M: Middleware + 'static,
{
#[instrument(err, skip(self))]
async fn get_finalized_block_number(&self) -> Result<u32> {
Ok(self
.provider
.get_block_number()
.await?
.as_u32()
.saturating_sub(self.finality_blocks))
}
}
#[async_trait]
impl<M> OutboxIndexer for EthereumOutboxIndexer<M>
where
M: Middleware + 'static,
{
#[instrument(err, skip(self))]
async fn fetch_sorted_messages(
&self,
from: u32,
to: u32,
) -> Result<Vec<(RawCommittedMessage, LogMeta)>> {
let mut events: Vec<(RawCommittedMessage, LogMeta)> = self
.contract
.dispatch_filter()
.from_block(from)
.to_block(to)
.query_with_meta()
.await?
.into_iter()
.map(|(event, meta)| {
(
RawCommittedMessage {
leaf_index: event.leaf_index.as_u32(),
message: event.message.to_vec(),
},
meta.into(),
)
})
.collect();
events.sort_by(|a, b| a.0.leaf_index.cmp(&b.0.leaf_index));
Ok(events)
}
#[instrument(err, skip(self))]
async fn fetch_sorted_cached_checkpoints(
&self,
from: u32,
to: u32,
) -> Result<Vec<(Checkpoint, LogMeta)>> {
let mut events: Vec<(Checkpoint, LogMeta)> = self
.contract
.checkpoint_cached_filter()
.from_block(from)
.to_block(to)
.query_with_meta()
.await?
.into_iter()
.map(|(event, meta)| {
(
Checkpoint {
outbox_domain: self.outbox_domain,
root: event.root.into(),
index: event.index.as_u32(),
},
meta.into(),
)
})
.collect();
events.sort_by(|a, b| a.1.cmp(&b.1));
Ok(events)
}
}
pub struct OutboxBuilder {}
#[async_trait]
impl MakeableWithProvider for OutboxBuilder {
type Output = Box<dyn Outbox>;
async fn make_with_provider<M: Middleware + 'static>(
&self,
provider: M,
locator: &ContractLocator,
) -> Self::Output {
Box::new(EthereumOutbox::new(Arc::new(provider), locator))
}
}
/// A reference to an Outbox contract on some Ethereum chain
#[derive(Debug)]
pub struct EthereumOutbox<M>
where
M: Middleware,
{
contract: Arc<EthereumOutboxInternal<M>>,
domain: u32,
chain_name: String,
provider: Arc<M>,
}
impl<M> EthereumOutbox<M>
where
M: Middleware + 'static,
{
/// Create a reference to a outbox at a specific Ethereum address on some
/// chain
pub fn new(provider: Arc<M>, locator: &ContractLocator) -> Self {
Self {
contract: Arc::new(EthereumOutboxInternal::new(
&locator.address,
provider.clone(),
)),
domain: locator.domain,
chain_name: locator.chain_name.to_owned(),
provider,
}
}
}
impl<M> AbacusChain for EthereumOutbox<M>
where
M: Middleware + 'static,
{
fn chain_name(&self) -> &str {
&self.chain_name
}
fn local_domain(&self) -> u32 {
self.domain
}
}
impl<M> AbacusContract for EthereumOutbox<M>
where
M: Middleware + 'static,
{
fn address(&self) -> H256 {
self.contract.address().into()
}
}
#[async_trait]
impl<M> AbacusCommon for EthereumOutbox<M>
where
M: Middleware + 'static,
{
#[tracing::instrument(err, skip(self))]
async fn validator_manager(&self) -> Result<H256, ChainCommunicationError> {
Ok(self.contract.validator_manager().call().await?.into())
}
}
#[async_trait]
impl<M> Outbox for EthereumOutbox<M>
where
M: Middleware + 'static,
{
#[tracing::instrument(err, skip(self))]
async fn dispatch(&self, message: &Message) -> Result<TxOutcome, ChainCommunicationError> {
let tx = self.contract.dispatch(
message.destination,
message.recipient.to_fixed_bytes(),
message.body.clone().into(),
);
Ok(report_tx(tx).await?.into())
}
#[tracing::instrument(err, skip(self))]
async fn state(&self) -> Result<OutboxState, ChainCommunicationError> {
let state = self.contract.state().call().await?;
Ok(OutboxState::try_from(state).expect("Invalid state received from contract"))
}
#[tracing::instrument(err, skip(self))]
async fn count(&self) -> Result<u32, ChainCommunicationError> {
Ok(self.contract.count().call().await?.as_u32())
}
#[tracing::instrument(err, skip(self))]
async fn cache_checkpoint(&self) -> Result<TxOutcome, ChainCommunicationError> {
let tx = self.contract.cache_checkpoint();
Ok(report_tx(tx).await?.into())
}
#[tracing::instrument(err, skip(self))]
async fn latest_cached_root(&self) -> Result<H256, ChainCommunicationError> {
Ok(self.contract.latest_cached_root().call().await?.into())
}
#[tracing::instrument(err, skip(self))]
async fn latest_cached_checkpoint(&self) -> Result<Checkpoint, ChainCommunicationError> {
let (root, index) = self.contract.latest_cached_checkpoint().call().await?;
Ok(Checkpoint {
outbox_domain: self.domain,
root: root.into(),
index: index.as_u32(),
})
}
#[tracing::instrument(err, skip(self))]
async fn latest_checkpoint(
&self,
maybe_lag: Option<u64>,
) -> Result<Checkpoint, ChainCommunicationError> {
let base_call = self.contract.latest_checkpoint();
let call_with_lag = match maybe_lag {
Some(lag) => {
let tip = self
.provider
.get_block_number()
.await
.map_err(|x| ChainCommunicationError::CustomError(Box::new(x)))?
.as_u64();
base_call.block(if lag > tip { 0 } else { tip - lag })
}
None => base_call,
};
let (root, index) = call_with_lag.call().await?;
Ok(Checkpoint {
outbox_domain: self.domain,
root: root.into(),
index: index.as_u32(),
})
}
}
pub struct EthereumOutboxAbi;
impl AbacusAbi for EthereumOutboxAbi {
fn fn_map() -> HashMap<Selector, &'static str> {
super::extract_fn_map(&OUTBOX_ABI)
}
}

@ -1,208 +0,0 @@
#![allow(clippy::enum_variant_names)]
#![allow(missing_docs)]
use std::fmt::Display;
use std::sync::Arc;
use abacus_core::TxCostEstimate;
use async_trait::async_trait;
use ethers::abi::AbiEncode;
use ethers::prelude::*;
use ethers_contract::builders::ContractCall;
use eyre::{eyre, Result};
use abacus_core::{
accumulator::merkle::Proof, AbacusMessage, ChainCommunicationError, ContractLocator, Encode,
InboxValidatorManager, MultisigSignedCheckpoint, TxOutcome,
};
use crate::contracts::inbox_validator_manager::{
InboxValidatorManager as EthereumInboxValidatorManagerInternal, ProcessCall,
};
use crate::trait_builder::MakeableWithProvider;
use crate::tx::report_tx;
pub use crate::contracts::inbox_validator_manager::INBOXVALIDATORMANAGER_ABI;
impl<M> Display for EthereumInboxValidatorManagerInternal<M>
where
M: Middleware,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub struct InboxValidatorManagerBuilder {
pub inbox_address: Address,
}
#[async_trait]
impl MakeableWithProvider for InboxValidatorManagerBuilder {
type Output = Box<dyn InboxValidatorManager>;
async fn make_with_provider<M: Middleware + 'static>(
&self,
provider: M,
locator: &ContractLocator,
) -> Self::Output {
Box::new(EthereumInboxValidatorManager::new(
Arc::new(provider),
locator,
self.inbox_address,
))
}
}
/// A struct that provides access to an Ethereum InboxValidatorManager contract
#[derive(Debug)]
pub struct EthereumInboxValidatorManager<M>
where
M: Middleware,
{
contract: Arc<EthereumInboxValidatorManagerInternal<M>>,
#[allow(unused)]
domain: u32,
#[allow(unused)]
chain_name: String,
#[allow(unused)]
provider: Arc<M>,
inbox_address: Address,
}
impl<M> EthereumInboxValidatorManager<M>
where
M: Middleware,
{
/// Create a reference to a inbox at a specific Ethereum address on some
/// chain
pub fn new(provider: Arc<M>, locator: &ContractLocator, inbox_address: Address) -> Self {
Self {
contract: Arc::new(EthereumInboxValidatorManagerInternal::new(
&locator.address,
provider.clone(),
)),
domain: locator.domain,
chain_name: locator.chain_name.to_owned(),
provider,
inbox_address,
}
}
}
#[async_trait]
impl<M> InboxValidatorManager for EthereumInboxValidatorManager<M>
where
M: Middleware + 'static,
{
#[tracing::instrument(skip(self))]
async fn process(
&self,
multisig_signed_checkpoint: &MultisigSignedCheckpoint,
message: &AbacusMessage,
proof: &Proof,
tx_gas_limit: Option<U256>,
) -> Result<TxOutcome, ChainCommunicationError> {
let contract_call = self
.process_contract_call(multisig_signed_checkpoint, message, proof, tx_gas_limit)
.await?;
let receipt = report_tx(contract_call).await?;
Ok(receipt.into())
}
async fn process_estimate_costs(
&self,
multisig_signed_checkpoint: &MultisigSignedCheckpoint,
message: &AbacusMessage,
proof: &Proof,
) -> Result<TxCostEstimate> {
let contract_call = self
.process_contract_call(multisig_signed_checkpoint, message, proof, None)
.await?;
let gas_limit = contract_call
.tx
.gas()
.ok_or_else(|| eyre!("Expected gas limit for process contract call"))?;
let gas_price = self.provider.get_gas_price().await?;
Ok(TxCostEstimate {
gas_limit: *gas_limit,
gas_price,
})
}
fn process_calldata(
&self,
multisig_signed_checkpoint: &MultisigSignedCheckpoint,
message: &AbacusMessage,
proof: &Proof,
) -> Vec<u8> {
let mut sol_proof: [[u8; 32]; 32] = Default::default();
sol_proof
.iter_mut()
.enumerate()
.for_each(|(i, elem)| *elem = proof.path[i].to_fixed_bytes());
let process_call = ProcessCall {
inbox: self.inbox_address,
root: multisig_signed_checkpoint.checkpoint.root.to_fixed_bytes(),
index: multisig_signed_checkpoint.checkpoint.index.into(),
signatures: multisig_signed_checkpoint
.signatures
.iter()
.map(|s| s.to_vec().into())
.collect(),
message: message.to_vec().into(),
proof: sol_proof,
leaf_index: proof.index.into(),
};
process_call.encode()
}
fn contract_address(&self) -> abacus_core::Address {
self.contract.address().into()
}
}
impl<M> EthereumInboxValidatorManager<M>
where
M: Middleware + 'static,
{
/// Returns a ContractCall that processes the provided message.
/// If the provided tx_gas_limit is None, gas estimation occurs.
async fn process_contract_call(
&self,
multisig_signed_checkpoint: &MultisigSignedCheckpoint,
message: &AbacusMessage,
proof: &Proof,
tx_gas_limit: Option<U256>,
) -> Result<ContractCall<M, ()>, ChainCommunicationError> {
let mut sol_proof: [[u8; 32]; 32] = Default::default();
sol_proof
.iter_mut()
.enumerate()
.for_each(|(i, elem)| *elem = proof.path[i].to_fixed_bytes());
let tx = self.contract.process(
self.inbox_address,
multisig_signed_checkpoint.checkpoint.root.to_fixed_bytes(),
multisig_signed_checkpoint.checkpoint.index.into(),
multisig_signed_checkpoint
.signatures
.iter()
.map(|s| s.to_vec().into())
.collect(),
message.to_vec().into(),
sol_proof,
proof.index.into(),
);
let gas_limit = if let Some(gas_limit) = tx_gas_limit {
gas_limit
} else {
tx.estimate_gas().await?.saturating_add(U256::from(100000))
};
Ok(tx.gas(gas_limit))
}
}
Loading…
Cancel
Save