Skip to content

Commit b991fb5

Browse files
EXP-83 Create basic scaffolding for bridge core impl (#230)
* feat(bridge): create basic scaffolding (WIP) * refactor: move bridge-db to db * chore(bridge): add main fn stubs * chore(bridge): add bridge binaries to project Cargo.toml * refactor: move all binaries to bin This is as per [cargo package layout](https://doc.rust-lang.org/cargo/guide/project-layout.html) * fix: correct typo * refactor: rename rpc-service to rpc-api for consistency * fix: resolve merge conflict in db crate * fix: rename bridge crates to use express * feat(bridge-rpc): create bridge rpc traits * refactor(bridge-rpc): move bridge-rpc-api inside rpc subdirectory * refactor(bridge-rpc): move deposit structs into txm and split rpc * feat(bridge-rpc): bootstrap bridge client in operator mode via stubs * refactor: remove unnecessary RPCs based on new archi * fix: remove duplicates after rebase * feat(bridge-rpc): add basic traits/types * fix(bridge-exec): move duty to bridge-state to remove cyclic deps * feat(bridge-txm): create deposit and reimbursement traits * refactor(bridge-txm): update l2 address type for multiple els * feat(bridge-exec): lay out types/traits with some basic impl * revert: move original bins back to root level Reverts 0efa8579 so as to reduce rebase hell for others. * fix: udpate struct locations after rebase * fix(primitives): convert error type for borsh * refactor(bridge): improve types/traits This is based on the discussion in PR [#230](alpenlabs/alpen#230) * refactor(bridge-rpc): rename `BridgeRpcImpl` to `BridgeRpc` * refactor(bridge-state): update and use output types for withdrawal * refactor(bridge-txm): use consistent naming The `signature_handler` is really a manager and not a handler. The crate is called `express-bridge-txm`, so the name of the directoy should be the same. * refactor(bridge): add `P2PMessage` to duties and remove `DepositRequest` * chore: reorganize workspace members list * chore(primitives): remove duplicate deps, add anyhow * refactor(primitives, state): add TweakedTrKey type for `WithdrawalOutput` * refactor(primitives): rename `TweakedTrPubkey` to `XOnlyPk` * refactor(bridge-rpc): update rpc trait * refactor(bridge-txm): add pubkeys arg to construct deposit tx * refactor(bridge-exec): remove redundant error display * refactor(bridge-exec): use AsRef<Path> instead of PathBuf * refactor(bridge-state): use XOnlyPk for dest_pk * chore: sort workspace members * refactor(bridge-client): convert `mode` to positional arg * refactor(bridge-rpc): rename method * refactor(bridge-exec): remove challenger exec * fix(bridge-exec): convert methods to pure funcs and remove relay methods * refactor(bridge-exec): remove pk path from config * refactor: implement Deref/DerefMut for BitcoinAmount * refactor: convert version to an enum * refactor(bridge-exec): use NetworkChecked addr * Revert "refactor: implement Deref/DerefMut for BitcoinAmount" This reverts commit 96aec67910f0f0f1d2f2ce5530e024c741adf2e7. * chore: cleanup unused imports * fix: resolve rebase issue * refactor(bridge-client): replace clap with argh :( * chore(bridge-rpc): add TODO to refactor RPCs * chore(withdrawal-handler): update PR reference * refactor(bridge-txm): split crate into builder and signer * refactor(bridge-exec): change signatures based on new types * docs(bridge-client): add note on using `express-tasks` * refactor(bridge-rpc): use new types * refactor(bridge-state): change type definitions for consistency * refactor(bridge-exec): use proper error messages * feat(primitives): add bridge primitives * feat(primitives): add concrete error types
1 parent 2e15bf2 commit b991fb5

File tree

67 files changed

+2180
-190
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2180
-190
lines changed

Cargo.lock

Lines changed: 79 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
[workspace]
22
members = [
3+
"crates/bridge-exec",
4+
"crates/bridge-sig-manager",
5+
"crates/bridge-tx-builder",
36
"crates/btcio",
47
"crates/chaintsn",
58
"crates/common",
@@ -19,6 +22,7 @@ members = [
1922
"crates/reth/node",
2023
"crates/reth/rpc",
2124
"crates/rpc/api",
25+
"crates/rpc/bridge-api",
2226
"crates/rpc/types",
2327
"crates/rpc/utils",
2428
"crates/state",
@@ -32,11 +36,12 @@ members = [
3236
"proofs/sp1",
3337

3438
# binaries listed separately
35-
"sequencer",
39+
"bin/bridge-client",
3640
"reth",
41+
"sequencer",
3742
]
3843

39-
default-members = ["sequencer", "reth"]
44+
default-members = ["bin/bridge-client", "reth", "sequencer"]
4045

4146
resolver = "2"
4247

@@ -56,6 +61,10 @@ alpen-express-state = { path = "crates/state" }
5661
alpen-express-status = { path = "crates/status" }
5762
alpen-test-utils = { path = "crates/test-utils" }
5863
bitcoin-blockspace = { path = "crates/prover/bitcoin-blockspace" }
64+
express-bridge-exec = { path = "crates/bridge-exec" }
65+
express-bridge-rpc-api = { path = "crates/rpc/bridge-api" }
66+
express-bridge-sig-manager = { path = "crates/bridge-sig-manager" }
67+
express-bridge-tx-builder = { path = "crates/bridge-tx-builder" }
5968
express-chaintsn = { path = "crates/chaintsn" }
6069
express-reth-db = { path = "crates/reth/db" }
6170
express-reth-exex = { path = "crates/reth/exex" }
@@ -83,6 +92,7 @@ bitcoind = { version = "0.36.0", features = ["26_0"] }
8392
bitcoind-json-rpc-types = "0.3.0"
8493
borsh = { version = "1.5.0", features = ["derive"] }
8594
bytes = { version = "1.6.0" }
95+
chrono = { version = "0.4.38" }
8696
digest = "0.10"
8797
eyre = "0.6"
8898
format_serde_error = { git = "https://github.com/AlexanderThaller/format_serde_error" }

bin/bridge-client/Cargo.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[package]
2+
edition = "2021"
3+
name = "express-bridge-client"
4+
version = "0.1.0"
5+
6+
[[bin]]
7+
name = "express-bridge-client"
8+
path = "src/main.rs"
9+
10+
[dependencies]
11+
alpen-express-common = { workspace = true }
12+
express-bridge-rpc-api = { workspace = true }
13+
14+
anyhow = { workspace = true }
15+
argh = { workspace = true }
16+
async-trait = { workspace = true }
17+
bitcoin = { workspace = true }
18+
chrono = { workspace = true }
19+
jsonrpsee = { workspace = true }
20+
thiserror = { workspace = true }
21+
tokio = { workspace = true }
22+
tracing = { workspace = true }
23+
tracing-subscriber = { workspace = true, features = ["env-filter"] }

bin/bridge-client/src/args.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//! Parses command-line arguments for the bridge-client CLI.
2+
use std::fmt::Display;
3+
4+
use argh::FromArgs;
5+
6+
use crate::errors::InitError;
7+
8+
#[derive(Debug, FromArgs)]
9+
#[argh(name = "express-bridge-client")]
10+
#[argh(description = "The bridge client for Express")]
11+
pub(crate) struct Cli {
12+
#[argh(
13+
positional,
14+
description = "what mode to run the client in, either Operator (alias: op) or Challenger (alias: ch)"
15+
)]
16+
pub mode: String,
17+
}
18+
19+
#[derive(Debug, Clone)]
20+
pub(super) enum OperationMode {
21+
/// Run client in Operator mode to handle deposits, withdrawals and challenging.
22+
Operator,
23+
24+
/// Run client in Challenger mode to verify/challenge Operator claims.
25+
Challenger,
26+
}
27+
28+
impl Display for OperationMode {
29+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30+
match self {
31+
OperationMode::Operator => write!(f, "operator"),
32+
OperationMode::Challenger => write!(f, "challenger"),
33+
}
34+
}
35+
}
36+
37+
impl TryInto<OperationMode> for String {
38+
type Error = InitError;
39+
40+
fn try_into(self) -> Result<OperationMode, Self::Error> {
41+
match self.as_ref() {
42+
"operator" | "op" => Ok(OperationMode::Operator),
43+
"challenger" | "ch" => Ok(OperationMode::Challenger),
44+
other => Err(InitError::InvalidMode(other.to_string())),
45+
}
46+
}
47+
}

bin/bridge-client/src/constants.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub(super) const RPC_PORT: usize = 4781; // first 4 digits in the sha256 of "operator"
2+
pub(super) const RPC_SERVER: &str = "127.0.0.1";

bin/bridge-client/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use thiserror::Error;
2+
3+
#[derive(Debug, Clone, Error)]
4+
pub enum InitError {
5+
#[error("Invalid operation mode, expected: operator(op) or challenger(ch), got: {0}")]
6+
InvalidMode(String),
7+
}

bin/bridge-client/src/main.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//! Bridge Operator client.
2+
//!
3+
//! Responsible for facilitating bridge-in and bridge-out operations by creating, storing and
4+
//! publishing appropriate transactions. Can also perform challenger duties.
5+
6+
mod args;
7+
pub(crate) mod constants;
8+
mod errors;
9+
mod modes;
10+
pub(crate) mod rpc_server;
11+
12+
use alpen_express_common::logging;
13+
use args::{Cli, OperationMode};
14+
use modes::{challenger, operator};
15+
use tracing::info;
16+
17+
#[tokio::main]
18+
async fn main() {
19+
logging::init();
20+
21+
let cli_args: Cli = argh::from_env();
22+
23+
let mode: OperationMode = match cli_args.mode.try_into() {
24+
Ok(mode) => mode,
25+
Err(err) => {
26+
panic!("{}", err);
27+
}
28+
};
29+
30+
info!("running bridge client in {} mode", mode);
31+
32+
match mode {
33+
OperationMode::Operator => {
34+
operator::bootstrap()
35+
.await
36+
.expect("bootstrap operator node");
37+
}
38+
OperationMode::Challenger => {
39+
challenger::bootstrap().await;
40+
}
41+
}
42+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//! Defines the main loop for the bridge-client in challenger mode.
2+
3+
pub(crate) async fn bootstrap() {
4+
unimplemented!("Challenger mode");
5+
}

bin/bridge-client/src/modes/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//! Defines the main loops for bridge-client modes namely, `operator` and `challenger`.
2+
3+
pub(crate) mod challenger;
4+
pub(crate) mod operator;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//! Defines the main loop for the bridge-client in operator mode.
2+
3+
use crate::rpc_server::{self, BridgeRpc};
4+
5+
/// Bootstraps the bridge client in Operator mode by hooking up all the required auxiliary services
6+
/// including database, rpc server, etc. Threadpool and logging need to be initialized at the call
7+
/// site (main function) itself.
8+
pub(crate) async fn bootstrap() -> anyhow::Result<()> {
9+
let rpc_impl = BridgeRpc::default();
10+
11+
rpc_server::start(&rpc_impl).await?;
12+
13+
Ok(())
14+
}

0 commit comments

Comments
 (0)