Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 11 additions & 0 deletions 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ itertools = "0.12.1"
itoa = "1.0.10"
jsonrpsee = { version = "0.20" }
once_cell = "1.17.1"
pin-project-lite = "0.2.13"
sha2 = "0.10"
serde = "1"
serde_json = "1"
Expand Down
14 changes: 14 additions & 0 deletions crates/astria-bridge-withdrawer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,32 @@ name = "astria-bridge-withdrawer"
http = "0.2.9"

axum = { workspace = true }
ed25519-consensus = { workspace = true }
futures = { workspace = true }
hex = { workspace = true }
ethers = { workspace = true, features = ["ethers-solc", "ws"] }
hyper = { workspace = true }
humantime = { workspace = true }
ibc-types = { workspace = true }
metrics = { workspace = true }
pin-project-lite = { workspace = true }
prost = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = { workspace = true }
tendermint = { workspace = true }
tracing = { workspace = true }
tryhard = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] }
tokio-util = { workspace = true }

astria-build-info = { path = "../astria-build-info", features = ["runtime"] }
astria-core = { path = "../astria-core", features = ["serde", "server"] }
astria-eyre = { path = "../astria-eyre" }
config = { package = "astria-config", path = "../astria-config" }
sequencer-client = { package = "astria-sequencer-client", path = "../astria-sequencer-client", features = [
"http",
] }
telemetry = { package = "astria-telemetry", path = "../astria-telemetry", features = [
"display",
] }
Expand Down
15 changes: 15 additions & 0 deletions crates/astria-bridge-withdrawer/local.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,23 @@ NO_COLOR=
# serves RPCs.
ASTRIA_BRIDGE_WITHDRAWER_COMETBFT_ENDPOINT="http://127.0.0.1:26657"

# Chain ID of the sequencer chain which transactions are submitted to.
ASTRIA_BRIDGE_WITHDRAWER_SEQUENCER_CHAIN_ID="astria-dev-1"

# The path to the file storing the private key for the sequencer account used for signing
# transactions. The file should contain a hex-encoded Ed25519 secret key.
ASTRIA_BRIDGE_WITHDRAWER_SEQUENCER_KEY_PATH=/path/to/priv_sequencer_key.json

# The fee asset denomination to use for the bridge account's transactions.
ASTRIA_BRIDGE_WITHDRAWER_FEE_ASSET_DENOMINATION="nria"

# The asset denomination being withdrawn from the rollup.
ASTRIA_BRIDGE_WITHDRAWER_ROLLUP_ASSET_DENOMINATION="nria",

# The address of the AstriaWithdrawer contract on the evm rollup.
ASTRIA_BRIDGE_WITHDRAWER_ETHEREUM_CONTRACT_ADDRESS="0x"

# The rpc endpoint of the evm rollup.
ASTRIA_BRIDGE_WITHDRAWER_ETHEREUM_RPC_ENDPOINT="http://127.0.0.1:8545"

# The socket address at which the bridge service will server healthz, readyz, and status calls.
Expand Down
28 changes: 14 additions & 14 deletions crates/astria-bridge-withdrawer/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,38 @@ use hyper::server::conn::AddrIncoming;
use serde::Serialize;
use tokio::sync::watch;

use crate::ethereum;
use crate::withdrawer::StateSnapshot;

pub(crate) type ApiServer = axum::Server<AddrIncoming, IntoMakeService<Router>>;

type BridgeState = watch::Receiver<ethereum::StateSnapshot>;
type WithdrawerState = watch::Receiver<StateSnapshot>;

#[derive(Clone)]
/// `AppState` is used for as an axum extractor in its method handlers.
struct AppState {
bridge_state: BridgeState,
withdrawer_state: WithdrawerState,
}

impl FromRef<AppState> for BridgeState {
impl FromRef<AppState> for WithdrawerState {
fn from_ref(app_state: &AppState) -> Self {
app_state.bridge_state.clone()
app_state.withdrawer_state.clone()
}
}

pub(crate) fn start(socket_addr: SocketAddr, bridge_state: BridgeState) -> ApiServer {
pub(crate) fn start(socket_addr: SocketAddr, withdrawer_state: WithdrawerState) -> ApiServer {
let app = Router::new()
.route("/healthz", get(get_healthz))
.route("/readyz", get(get_readyz))
.route("/status", get(get_status))
.with_state(AppState {
bridge_state,
withdrawer_state,
});
axum::Server::bind(&socket_addr).serve(app.into_make_service())
}

#[allow(clippy::unused_async)] // Permit because axum handlers must be async
async fn get_healthz(State(bridge_state): State<BridgeState>) -> Healthz {
if bridge_state.borrow().is_healthy() {
async fn get_healthz(State(withdrawer_state): State<WithdrawerState>) -> Healthz {
if withdrawer_state.borrow().is_healthy() {
Healthz::Ok
} else {
Healthz::Degraded
Expand All @@ -66,18 +66,18 @@ async fn get_healthz(State(bridge_state): State<BridgeState>) -> Healthz {
/// + there is a current sequencer height (implying a block from sequencer was received)
/// + there is a current data availability height (implying a height was received from the DA)
#[allow(clippy::unused_async)] // Permit because axum handlers must be async
async fn get_readyz(State(bridge_state): State<BridgeState>) -> Readyz {
let is_bridge_online = bridge_state.borrow().is_ready();
if is_bridge_online {
async fn get_readyz(State(withdrawer_state): State<WithdrawerState>) -> Readyz {
let is_withdrawer_online = withdrawer_state.borrow().is_ready();
if is_withdrawer_online {
Readyz::Ok
} else {
Readyz::NotReady
}
}

#[allow(clippy::unused_async)] // Permit because axum handlers must be async
async fn get_status(State(bridge_state): State<BridgeState>) -> Json<ethereum::StateSnapshot> {
Json(bridge_state.borrow().clone())
async fn get_status(State(withdrawer_state): State<WithdrawerState>) -> Json<StateSnapshot> {
Json(withdrawer_state.borrow().clone())
}

enum Healthz {
Expand Down
9 changes: 8 additions & 1 deletion crates/astria-bridge-withdrawer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,18 @@ use serde::{
pub struct Config {
// The cometbft rpc endpoint for submitting transactions to the sequencer.
pub cometbft_endpoint: String,
// The chain id of the sequencer chain.
pub sequencer_chain_id: String,
// The path to the private key used to sign transactions submitted to the sequencer.
pub sequencer_key_path: String,
// The fee asset denomination to use for the bridge account's transactions.
pub fee_asset_denomination: String,
// The asset denomination being withdrawn from the rollup.
pub rollup_asset_denomination: String,
// The address of the AstriaWithdrawer contract on the evm rollup.
pub ethereum_contract_address: String,
// The rpc endpoint of the evm rollup.
pub ethereum_rpc_endpoint: String,

// The socket address at which the bridge service will server healthz, readyz, and status
// calls.
pub api_addr: String,
Expand Down
41 changes: 0 additions & 41 deletions crates/astria-bridge-withdrawer/src/ethereum/state.rs

This file was deleted.

5 changes: 2 additions & 3 deletions crates/astria-bridge-withdrawer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
pub(crate) mod api;
pub mod bridge_service;
mod build_info;
pub(crate) mod config;
pub(crate) mod ethereum;
pub mod metrics_init;
pub mod withdrawer;

pub use bridge_service::BridgeService;
pub use build_info::BUILD_INFO;
pub use config::Config;
pub use withdrawer::WithdrawerService;
14 changes: 7 additions & 7 deletions crates/astria-bridge-withdrawer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::process::ExitCode;

use astria_bridge_withdrawer::{
metrics_init,
BridgeService,
Config,
WithdrawerService,
BUILD_INFO,
};
use astria_eyre::eyre::WrapErr as _;
Expand Down Expand Up @@ -54,10 +54,10 @@ async fn main() -> ExitCode {

let mut sigterm = signal(SignalKind::terminate())
.expect("setting a SIGTERM listener should always work on Unix");
let (bridge, shutdown_handle) = BridgeService::new(cfg)
let (withdrawer, shutdown_handle) = WithdrawerService::new(cfg)
.await
.expect("could not initialize bridge");
let bridge_handle = tokio::spawn(bridge.run());
.expect("could not initialize withdrawer");
let withdrawer_handle = tokio::spawn(withdrawer.run());

let shutdown_token = shutdown_handle.token();
tokio::select!(
Expand All @@ -72,10 +72,10 @@ async fn main() -> ExitCode {
}
);

if let Err(error) = bridge_handle.await {
error!(%error, "failed to join main bridge task");
if let Err(error) = withdrawer_handle.await {
error!(%error, "failed to join main withdrawer task");
}

info!("bridge stopped");
info!("withdrawer stopped");
ExitCode::SUCCESS
}
53 changes: 52 additions & 1 deletion crates/astria-bridge-withdrawer/src/metrics_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,56 @@
//!
//! Registers metrics & lists constants to be used as metric names throughout crate.

use metrics::{
describe_counter,
describe_gauge,
describe_histogram,
Unit,
};

/// Registers all metrics used by this crate.
pub fn register() {}
pub fn register() {
describe_counter!(
NONCE_FETCH_COUNT,
Unit::Count,
"The number of times we have attempted to fetch the nonce"
);
describe_counter!(
NONCE_FETCH_FAILURE_COUNT,
Unit::Count,
"The number of times we have failed to fetch the nonce"
);
describe_histogram!(
NONCE_FETCH_LATENCY,
Unit::Milliseconds,
"The latency of nonce fetch"
);
describe_gauge!(CURRENT_NONCE, Unit::Count, "The current nonce");
describe_histogram!(
SEQUENCER_SUBMISSION_LATENCY,
Unit::Milliseconds,
"The latency of submitting a transaction to the sequencer"
);
describe_counter!(
SEQUENCER_SUBMISSION_FAILURE_COUNT,
Unit::Count,
"The number of failed transaction submissions to the sequencer"
);
}

pub const NONCE_FETCH_COUNT: &str = concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_count");

pub const NONCE_FETCH_FAILURE_COUNT: &str =
concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_failure_count");

pub const NONCE_FETCH_LATENCY: &str = concat!(env!("CARGO_CRATE_NAME"), "_nonce_fetch_latency");

pub const CURRENT_NONCE: &str = concat!(env!("CARGO_CRATE_NAME"), "_current_nonce");

pub const SEQUENCER_SUBMISSION_FAILURE_COUNT: &str = concat!(
env!("CARGO_CRATE_NAME"),
"_sequencer_submission_failure_count"
);

pub const SEQUENCER_SUBMISSION_LATENCY: &str =
concat!(env!("CARGO_CRATE_NAME"), "_sequencer_submission_latency");
Loading