Update `report_tx` to be a function instead of a macro (#456)

* Make brain hurt less by using a damn function

* rename mod to tx
pull/461/head
Mattie Conover 3 years ago committed by GitHub
parent 931c37920a
commit 2a96c607f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 17
      rust/chains/abacus-ethereum/src/inbox.rs
  2. 16
      rust/chains/abacus-ethereum/src/lib.rs
  3. 69
      rust/chains/abacus-ethereum/src/macros.rs
  4. 14
      rust/chains/abacus-ethereum/src/outbox.rs
  5. 81
      rust/chains/abacus-ethereum/src/tx.rs
  6. 11
      rust/chains/abacus-ethereum/src/validator_manager.rs

@ -1,20 +1,21 @@
#![allow(clippy::enum_variant_names)]
#![allow(missing_docs)]
use abacus_core::{accumulator::merkle::Proof, MessageStatus, *};
use abacus_core::{
AbacusCommon, AbacusCommonIndexer, AbacusMessage, ChainCommunicationError, Checkpoint,
CheckpointMeta, CheckpointWithMeta, ContractLocator, Inbox, TxOutcome,
};
use std::{error::Error as StdError, sync::Arc};
use async_trait::async_trait;
use ethers::contract::abigen;
use ethers::core::types::{H256, U256};
use eyre::Result;
use tracing::instrument;
use std::{error::Error as StdError, sync::Arc};
use abacus_core::{accumulator::merkle::Proof, MessageStatus, *};
use abacus_core::{
AbacusCommon, AbacusCommonIndexer, AbacusMessage, ChainCommunicationError, Checkpoint,
CheckpointMeta, CheckpointWithMeta, ContractLocator, Inbox, TxOutcome,
};
use crate::report_tx;
use crate::tx::report_tx;
abigen!(
EthereumInboxInternal,
@ -256,7 +257,7 @@ where
);
let gas = tx.estimate_gas().await?.saturating_add(U256::from(100000));
let gassed = tx.gas(gas);
Ok(report_tx!(gassed).into())
Ok(report_tx(gassed).await?.into())
}
#[tracing::instrument(err)]

@ -4,12 +4,20 @@
#![warn(missing_docs)]
#![warn(unused_extern_crates)]
use abacus_core::*;
use std::sync::Arc;
use ethers::providers::Middleware;
use ethers::types::{Address, BlockId, BlockNumber, NameOrAddress, H160};
use eyre::Result;
use num::Num;
use std::sync::Arc;
use abacus_core::*;
pub use retrying::{RetryingProvider, RetryingProviderError};
#[cfg(not(doctest))]
pub use crate::{inbox::*, outbox::*, validator_manager::*};
mod tx;
#[macro_use]
mod macros;
@ -28,7 +36,6 @@ mod validator_manager;
/// Retrying Provider
mod retrying;
pub use retrying::{RetryingProvider, RetryingProviderError};
/// Ethereum connection configuration
#[derive(Debug, serde::Deserialize, Clone)]
@ -54,9 +61,6 @@ impl Default for Connection {
}
}
#[cfg(not(doctest))]
pub use crate::{inbox::*, outbox::*, validator_manager::*};
#[allow(dead_code)]
/// A live connection to an ethereum-compatible chain.
pub struct Chain {

@ -1,72 +1,3 @@
/// Dispatches a transaction, logs the tx id, and returns the result
#[macro_export]
macro_rules! report_tx {
($tx:expr) => {{
// "0x..."
let data = format!("0x{}", hex::encode(&$tx.tx.data().map(|b| b.to_vec()).unwrap_or_default()));
let to = $tx.tx.to().cloned().unwrap_or_else(|| ethers::types::NameOrAddress::Address(Default::default()));
tracing::info!(
to = ?to,
data = %data,
"Dispatching transaction"
);
// We can set the gas higher here!
let dispatch_fut = $tx.send();
let dispatched = dispatch_fut.await?;
let tx_hash: ethers::core::types::H256 = *dispatched;
tracing::info!(
to = ?to,
data = %data,
tx_hash = ?tx_hash,
"Dispatched tx"
);
let wrapped_tx_submission = tokio::time::timeout(std::time::Duration::from_secs(300), dispatched);
match wrapped_tx_submission.await {
Ok(tx_submission) => {
match tx_submission {
Ok(Some(receipt)) => {
tracing::info!(
tx_hash = ?tx_hash,
"confirmed transaction"
);
receipt
}
// ethers-rs will return None if it can no longer poll for the tx in the mempool
Ok(None) => {
return Err(abacus_core::ChainCommunicationError::DroppedError(tx_hash))
}
// Pass through this error
Err(x) => {
tracing::error!(
tx_hash = ?tx_hash,
error = ?x,
"encountered error when waiting for receipt",
);
return Err(x.into())
}
}
}
Err(x) => {
tracing::error!(
tx_hash = ?tx_hash,
error = ?x,
"waiting for receipt timed out",
);
return Err(abacus_core::ChainCommunicationError::TransactionTimeout())
}
}
}};
}
macro_rules! boxed_trait {
(@finish $provider:expr, $abi:ident, $signer:ident, $($tail:tt)*) => {{
if let Some(signer) = $signer {

@ -1,16 +1,18 @@
#![allow(clippy::enum_variant_names)]
#![allow(missing_docs)]
use abacus_core::*;
use abacus_core::{ChainCommunicationError, Message, RawCommittedMessage, TxOutcome};
use std::{error::Error as StdError, sync::Arc};
use async_trait::async_trait;
use ethers::contract::abigen;
use ethers::core::types::H256;
use eyre::Result;
use std::{error::Error as StdError, sync::Arc};
use tracing::instrument;
use crate::report_tx;
use abacus_core::*;
use abacus_core::{ChainCommunicationError, Message, RawCommittedMessage, TxOutcome};
use crate::tx::report_tx;
abigen!(
EthereumOutboxInternal,
@ -257,7 +259,7 @@ where
message.body.clone().into(),
);
Ok(report_tx!(tx).into())
Ok(report_tx(tx).await?.into())
}
#[tracing::instrument(err, skip(self))]
@ -279,6 +281,6 @@ where
async fn create_checkpoint(&self) -> Result<TxOutcome, ChainCommunicationError> {
let tx = self.contract.checkpoint();
Ok(report_tx!(tx).into())
Ok(report_tx(tx).await?.into())
}
}

@ -0,0 +1,81 @@
use std::time::Duration;
use ethers::abi::Detokenize;
use ethers::prelude::*;
use ethers_contract::builders::ContractCall;
use tracing::{error, info};
use abacus_core::ChainCommunicationError;
use crate::Middleware;
/// Dispatches a transaction, logs the tx id, and returns the result
pub(crate) async fn report_tx<M, D>(
tx: ContractCall<M, D>,
) -> Result<TransactionReceipt, ChainCommunicationError>
where
M: Middleware + 'static,
D: Detokenize,
{
// "0x..."
let data = format!(
"0x{}",
hex::encode(&tx.tx.data().map(|b| b.to_vec()).unwrap_or_default())
);
let to = tx
.tx
.to()
.cloned()
.unwrap_or_else(|| NameOrAddress::Address(Default::default()));
info!(
to = ?to,
data = %data,
"Dispatching transaction"
);
// We can set the gas higher here!
let dispatch_fut = tx.send();
let dispatched = dispatch_fut.await?;
let tx_hash: H256 = *dispatched;
info!(
to = ?to,
data = %data,
tx_hash = ?tx_hash,
"Dispatched tx"
);
match tokio::time::timeout(Duration::from_secs(300), dispatched).await {
// all good
Ok(Ok(Some(receipt))) => {
info!(
tx_hash = ?tx_hash,
"confirmed transaction"
);
Ok(receipt)
}
// ethers-rs will return None if it can no longer poll for the tx in the mempool
Ok(Ok(None)) => Err(ChainCommunicationError::DroppedError(tx_hash)),
// Received error, pass it through
Ok(Err(x)) => {
error!(
tx_hash = ?tx_hash,
error = ?x,
"encountered error when waiting for receipt",
);
Err(x.into())
}
// Timed out
Err(x) => {
error!(
tx_hash = ?tx_hash,
error = ?x,
"waiting for receipt timed out",
);
Err(ChainCommunicationError::TransactionTimeout())
}
}
}

@ -1,16 +1,17 @@
#![allow(clippy::enum_variant_names)]
#![allow(missing_docs)]
use abacus_core::{ChainCommunicationError, ContractLocator, TxOutcome};
use abacus_core::{InboxValidatorManager, MultisigSignedCheckpoint};
use std::sync::Arc;
use async_trait::async_trait;
use ethers::contract::abigen;
use ethers::core::types::Address;
use eyre::Result;
use std::sync::Arc;
use abacus_core::{ChainCommunicationError, ContractLocator, TxOutcome};
use abacus_core::{InboxValidatorManager, MultisigSignedCheckpoint};
use crate::report_tx;
use crate::tx::report_tx;
abigen!(
EthereumInboxValidatorManagerInternal,
@ -91,6 +92,6 @@ where
.collect(),
);
Ok(report_tx!(tx).into())
Ok(report_tx(tx).await?.into())
}
}

Loading…
Cancel
Save