Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(sequencer): migrate from anyhow::Result to eyre::Result #1387

Merged
merged 19 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/astria-eyre/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
eyre = "0.6"
itoa = "1.0.10"
anyhow = { version = "1.0.0", optional = true }

[dev-dependencies]
tracing = { workspace = true }
Expand Down
47 changes: 47 additions & 0 deletions crates/astria-eyre/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ use std::{
fmt::Write as _,
};

#[cfg(feature = "anyhow")]
pub use anyhow_conversion::{
anyhow_to_eyre,
eyre_to_anyhow,
};
pub use eyre;
#[doc(hidden)]
pub use eyre::Result;
Expand Down Expand Up @@ -83,3 +88,45 @@ fn write_value(err: &dyn Error, f: &mut core::fmt::Formatter<'_>) -> core::fmt::
f.write_fmt(format_args!("\"{err}\""))?;
Ok(())
}

#[cfg(feature = "anyhow")]
pub mod anyhow_conversion {
ethanoroshiba marked this conversation as resolved.
Show resolved Hide resolved
pub use anyhow;

pub fn anyhow_to_eyre(anyhow_error: anyhow::Error) -> eyre::Report {
let boxed: Box<dyn std::error::Error + Send + Sync> = anyhow_error.into();
eyre::eyre!(boxed)
}

#[must_use]
pub fn eyre_to_anyhow(eyre_error: eyre::Report) -> anyhow::Error {
let boxed: Box<dyn std::error::Error + Send + Sync> = eyre_error.into();
anyhow::anyhow!(boxed)
}

mod test {
ethanoroshiba marked this conversation as resolved.
Show resolved Hide resolved
#[test]
fn anyhow_to_eyre_preserves_source_chain() {
let mut errs = ["foo", "bar", "baz", "qux"];
let anyhow_error = anyhow::anyhow!(errs[0]).context(errs[1]).context(errs[2]);
let eyre_from_anyhow = super::anyhow_to_eyre(anyhow_error).wrap_err(errs[3]);

errs.reverse();
for (i, err) in eyre_from_anyhow.chain().enumerate() {
assert_eq!(errs[i], &err.to_string());
}
}

#[test]
fn eyre_to_anyhow_preserves_source_chain() {
let mut errs = ["foo", "bar", "baz", "qux"];
let eyre_error = eyre::eyre!(errs[0]).wrap_err(errs[1]).wrap_err(errs[2]);
let anyhow_from_eyre = super::eyre_to_anyhow(eyre_error).context(errs[3]);

errs.reverse();
for (i, err) in anyhow_from_eyre.chain().enumerate() {
assert_eq!(errs[i], &err.to_string());
}
}
}
}
8 changes: 6 additions & 2 deletions crates/astria-sequencer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@ benchmark = ["divan"]
[dependencies]
astria-core = { path = "../astria-core", features = ["server", "serde"] }
astria-build-info = { path = "../astria-build-info", features = ["runtime"] }

# The "anyhow" feature is only included because it is necessary for the implementation of
# `penumbra_ibc::component::HostInterface` in `crates/astria-sequencer/src/ibc/host_interface.rs`.
# Avoid using "anyhow" results anywhere else.
astria-eyre = { path = "../astria-eyre", features = ["anyhow"] }

config = { package = "astria-config", path = "../astria-config" }
merkle = { package = "astria-merkle", path = "../astria-merkle" }
telemetry = { package = "astria-telemetry", path = "../astria-telemetry", features = [
"display",
] }

anyhow = "1"
borsh = { version = "1", features = ["derive"] }
cnidarium = { git = "https://github.com/penumbra-zone/penumbra.git", rev = "87adc8d6b15f6081c1adf169daed4ca8873bd9f6", features = [
"metrics",
Expand Down
41 changes: 21 additions & 20 deletions crates/astria-sequencer/src/accounts/action.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use anyhow::{
ensure,
Context,
Result,
};
use astria_core::{
protocol::transaction::v1alpha1::action::TransferAction,
Protobuf as _,
};
use astria_eyre::eyre::{
ensure,
OptionExt as _,
Result,
WrapErr as _,
};
use cnidarium::{
StateRead,
StateWrite,
Expand Down Expand Up @@ -44,7 +45,7 @@ impl ActionHandler for TransferAction {
state
.get_bridge_account_rollup_id(from)
.await
.context("failed to get bridge account rollup id")?
.wrap_err("failed to get bridge account rollup id")?
.is_none(),
"cannot transfer out of bridge account; BridgeUnlock must be used",
);
Expand All @@ -60,7 +61,7 @@ pub(crate) async fn execute_transfer<S, TAddress>(
action: &TransferAction,
from: TAddress,
mut state: S,
) -> anyhow::Result<()>
) -> Result<()>
where
S: StateWrite,
TAddress: AddressBytes,
Expand All @@ -70,11 +71,11 @@ where
let fee = state
.get_transfer_base_fee()
.await
.context("failed to get transfer base fee")?;
.wrap_err("failed to get transfer base fee")?;
state
.get_and_increase_block_fees(&action.fee_asset, fee, TransferAction::full_name())
.await
.context("failed to add to block fees")?;
.wrap_err("failed to add to block fees")?;

// if fee payment asset is same asset as transfer asset, deduct fee
// from same balance as asset transferred
Expand All @@ -88,28 +89,28 @@ where
state
.decrease_balance(from, &action.asset, payment_amount)
.await
.context("failed decreasing `from` account balance")?;
.wrap_err("failed decreasing `from` account balance")?;
state
.increase_balance(action.to, &action.asset, action.amount)
.await
.context("failed increasing `to` account balance")?;
.wrap_err("failed increasing `to` account balance")?;
} else {
// otherwise, just transfer the transfer asset and deduct fee from fee asset balance
// later
state
.decrease_balance(from, &action.asset, action.amount)
.await
.context("failed decreasing `from` account balance")?;
.wrap_err("failed decreasing `from` account balance")?;
state
.increase_balance(action.to, &action.asset, action.amount)
.await
.context("failed increasing `to` account balance")?;
.wrap_err("failed increasing `to` account balance")?;

// deduct fee from fee asset balance
state
.decrease_balance(from, &action.fee_asset, fee)
.await
.context("failed decreasing `from` account balance for fee payment")?;
.wrap_err("failed decreasing `from` account balance for fee payment")?;
}
Ok(())
}
Expand All @@ -123,35 +124,35 @@ where
S: StateRead,
TAddress: AddressBytes,
{
state.ensure_base_prefix(&action.to).await.context(
state.ensure_base_prefix(&action.to).await.wrap_err(
"failed ensuring that the destination address matches the permitted base prefix",
)?;
ensure!(
state
.is_allowed_fee_asset(&action.fee_asset)
.await
.context("failed to check allowed fee assets in state")?,
.wrap_err("failed to check allowed fee assets in state")?,
"invalid fee asset",
);

let fee = state
.get_transfer_base_fee()
.await
.context("failed to get transfer base fee")?;
.wrap_err("failed to get transfer base fee")?;
let transfer_asset = action.asset.clone();

let from_fee_balance = state
.get_account_balance(&from, &action.fee_asset)
.await
.context("failed getting `from` account balance for fee payment")?;
.wrap_err("failed getting `from` account balance for fee payment")?;

// if fee asset is same as transfer asset, ensure accounts has enough funds
// to cover both the fee and the amount transferred
if action.fee_asset.to_ibc_prefixed() == transfer_asset.to_ibc_prefixed() {
let payment_amount = action
.amount
.checked_add(fee)
.context("transfer amount plus fee overflowed")?;
.ok_or_eyre("transfer amount plus fee overflowed")?;

ensure!(
from_fee_balance >= payment_amount,
Expand All @@ -168,7 +169,7 @@ where
let from_transfer_balance = state
.get_account_balance(from, transfer_asset)
.await
.context("failed to get account balance in transfer check")?;
.wrap_err("failed to get account balance in transfer check")?;
ensure!(
from_transfer_balance >= action.amount,
"insufficient funds for transfer"
Expand Down
12 changes: 6 additions & 6 deletions crates/astria-sequencer/src/accounts/component.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::sync::Arc;

use anyhow::{
Context,
use astria_core::protocol::genesis::v1alpha1::GenesisAppState;
use astria_eyre::eyre::{
Result,
WrapErr as _,
};
use astria_core::protocol::genesis::v1alpha1::GenesisAppState;
use tendermint::abci::request::{
BeginBlock,
EndBlock,
Expand Down Expand Up @@ -32,16 +32,16 @@ impl Component for AccountsComponent {
let native_asset = state
.get_native_asset()
.await
.context("failed to read native asset from state")?;
.wrap_err("failed to read native asset from state")?;
for account in app_state.accounts() {
state
.put_account_balance(account.address, &native_asset, account.balance)
.context("failed writing account balance to state")?;
.wrap_err("failed writing account balance to state")?;
}

state
.put_transfer_base_fee(app_state.fees().transfer_base_fee)
.context("failed to put transfer base fee")?;
.wrap_err("failed to put transfer base fee")?;
Ok(())
}

Expand Down
29 changes: 15 additions & 14 deletions crates/astria-sequencer/src/accounts/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use anyhow::Context as _;
use astria_core::{
primitive::v1::{
asset,
Expand All @@ -9,6 +8,11 @@ use astria_core::{
account::v1alpha1::AssetBalance,
},
};
use astria_eyre::eyre::{
OptionExt as _,
Result,
WrapErr as _,
};
use cnidarium::{
Snapshot,
StateRead,
Expand All @@ -35,19 +39,19 @@ use crate::{
async fn ibc_to_trace<S: StateRead>(
state: S,
asset: asset::IbcPrefixed,
) -> anyhow::Result<asset::TracePrefixed> {
) -> Result<asset::TracePrefixed> {
state
.map_ibc_to_trace_prefixed_asset(asset)
.await
.context("failed to get ibc asset denom")?
.context("asset not found when user has balance of it; this is a bug")
.ok_or_eyre("asset not found when user has balance of it; this is a bug")
}

#[instrument(skip_all, fields(%address))]
async fn get_trace_prefixed_account_balances<S: StateRead>(
state: &S,
address: Address,
) -> anyhow::Result<Vec<AssetBalance>> {
) -> Result<Vec<AssetBalance>> {
let stream = state
.account_asset_balances(address)
.map_ok(|asset_balance| async move {
Expand Down Expand Up @@ -150,37 +154,34 @@ pub(crate) async fn nonce_request(
}
}

async fn get_snapshot_and_height(
storage: &Storage,
height: Height,
) -> anyhow::Result<(Snapshot, Height)> {
async fn get_snapshot_and_height(storage: &Storage, height: Height) -> Result<(Snapshot, Height)> {
let snapshot = match height.value() {
0 => storage.latest_snapshot(),
other => {
let version = storage
.latest_snapshot()
.get_storage_version_by_height(other)
.await
.context("failed to get storage version from height")?;
.wrap_err("failed to get storage version from height")?;
storage
.snapshot(version)
.context("failed to get storage at version")?
.ok_or_eyre("failed to get storage at version")?
}
};
let height: Height = snapshot
.get_block_height()
.await
.context("failed to get block height from snapshot")?
.wrap_err("failed to get block height from snapshot")?
.try_into()
.context("internal u64 block height does not fit into tendermint i64 `Height`")?;
.wrap_err("internal u64 block height does not fit into tendermint i64 `Height`")?;
Ok((snapshot, height))
}

async fn preprocess_request(
storage: &Storage,
request: &request::Query,
params: &[(String, String)],
) -> anyhow::Result<(Address, Snapshot, Height), response::Query> {
) -> Result<(Address, Snapshot, Height), response::Query> {
let Some(address) = params
.iter()
.find_map(|(k, v)| (k == "account").then_some(v))
Expand All @@ -194,7 +195,7 @@ async fn preprocess_request(
};
let address = address
.parse()
.context("failed to parse argument as address")
.wrap_err("failed to parse argument as address")
.map_err(|err| response::Query {
code: Code::Err(AbciErrorCode::INVALID_PARAMETER.value()),
info: AbciErrorCode::INVALID_PARAMETER.info(),
Expand Down
Loading
Loading