Skip to content

Commit

Permalink
feat(bridge-exec)!: sign_[deposit|reimbursement]_tx
Browse files Browse the repository at this point in the history
  • Loading branch information
storopoli committed Sep 18, 2024
1 parent c5b5b07 commit 239473e
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 18 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions crates/bridge-exec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ rustdoc.all = "warn"
[dependencies]
alpen-express-btcio = { workspace = true }
alpen-express-primitives = { workspace = true }
alpen-express-rpc-api = { workspace = true }
express-bridge-tx-builder = { workspace = true }

async-trait = { workspace = true }
bitcoin = { workspace = true }
format_serde_error = { workspace = true }
jsonrpsee = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
toml = { workspace = true }
15 changes: 15 additions & 0 deletions crates/bridge-exec/src/deposit_handler/errors.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
//! Defines the error types associated with executing the deposit duties.

use alpen_express_btcio::rpc::error::ClientError as L1ClientError;
use express_bridge_tx_builder::errors::BridgeTxBuilderError;
use jsonrpsee::core::ClientError as L2ClientError;
use thiserror::Error;

// TODO: use concrete types instead of passing around `String`

/// Error encountered during the deposit duty execution.
#[derive(Error, Debug)]
pub enum DepositExecError {
/// Error creating the [`TxSigningData`](alpen_express_primitives::bridge::TxSigningData).
#[error("could not build deposit transaction")]
TxBuilder(#[from] BridgeTxBuilderError),

/// Error occurred while signing a transaction.
#[error("signing failed due to: {0}")]
Signing(String),
Expand All @@ -22,6 +29,14 @@ pub enum DepositExecError {
/// An unexpected error occurred during execution.
#[error("execution failed: {0}")]
Execution(String),

/// Error communicating with the Bitcoin RPC.
#[error("bitcoin RPC communication failed: {0}")]
L1Rpc(#[from] L1ClientError),

/// Error communicating with the rollup RPC.
#[error("rollup RPC communication failed: {0}")]
L2Rpc(#[from] L2ClientError),
}

/// The result of a deposit duty execution which may produce a [`DepositExecError`].
Expand Down
28 changes: 25 additions & 3 deletions crates/bridge-exec/src/deposit_handler/handler.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
//! Defines the functions that pertain to handling a deposit.

use std::sync::Arc;

use alpen_express_btcio::rpc::traits::Signer;
use alpen_express_primitives::bridge::OperatorPartialSig;
use alpen_express_rpc_api::AlpenApiClient;
use bitcoin::secp256k1::schnorr::Signature;
use express_bridge_tx_builder::deposit::DepositInfo;
use express_bridge_tx_builder::{deposit::DepositInfo, prelude::*, TxKind};

use super::errors::DepositExecResult;
use crate::deposit_handler::errors::DepositExecError;

/// Construct and sign the deposit transaction.
pub async fn sign_deposit_tx(_deposit_info: &DepositInfo) -> DepositExecResult<OperatorPartialSig> {
unimplemented!()
pub async fn sign_deposit_tx(
deposit_info: &DepositInfo,
l2_rpc_client: &Arc<impl AlpenApiClient + Sync>,
l1_rpc_client: &Arc<impl Signer>,
) -> DepositExecResult<OperatorPartialSig> {
let network = l2_rpc_client.get_l1_status().await?.network;
let operator_pubkeys = l2_rpc_client.get_active_operator_chain_pubkey_set().await?;

Check warning on line 21 in crates/bridge-exec/src/deposit_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/deposit_handler/handler.rs#L15-L21

Added lines #L15 - L21 were not covered by tests

let build_context = TxBuildContext::new(operator_pubkeys, network);
let _tx_signing_data = deposit_info.construct_signing_data(&build_context)?;

Check warning on line 24 in crates/bridge-exec/src/deposit_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/deposit_handler/handler.rs#L23-L24

Added lines #L23 - L24 were not covered by tests
// TODO: sign the transaction with MuSig2 and put inside the OperatorPartialSig
let xpriv = l1_rpc_client.get_xpriv().await?;
if let Some(_xpriv) = xpriv {
todo!()

Check warning on line 28 in crates/bridge-exec/src/deposit_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/deposit_handler/handler.rs#L26-L28

Added lines #L26 - L28 were not covered by tests
} else {
Err(DepositExecError::Signing(
"Could not get wallet's xpriv".to_string(),
))

Check warning on line 32 in crates/bridge-exec/src/deposit_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/deposit_handler/handler.rs#L30-L32

Added lines #L30 - L32 were not covered by tests
}
}

/// Add the signature to the already accumulated set of signatures for a deposit transaction and
Expand Down
18 changes: 10 additions & 8 deletions crates/bridge-exec/src/withdrawal_handler/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Defines the error types associated with executing the withdrawal duties.

use alpen_express_btcio::rpc::error::ClientError;
use alpen_express_btcio::rpc::error::ClientError as L1ClientError;
use jsonrpsee::core::ClientError as L2ClientError;
use thiserror::Error;

/// Error during execution of the withdrawal duty.
Expand All @@ -25,14 +26,15 @@ pub enum WithdrawalExecError {
/// Unexpected error during the handling of the withdrawal.
#[error("execution failed: {0}")]
Execution(String),

/// Error communicating with the Bitcoin RPC.
#[error("bitcoin RPC communication failed: {0}")]
L1Rpc(#[from] L1ClientError),

/// Error communicating with the rollup RPC.
#[error("rollup RPC communication failed: {0}")]
L2Rpc(#[from] L2ClientError),
}

/// Result of a withdrawal execution that may produce an [`WithdrawalExecError`].
pub type WithdrawalExecResult<T> = Result<T, WithdrawalExecError>;

/// Convert a [`ClientError`] into a [`WithdrawalExecError`].
impl From<ClientError> for WithdrawalExecError {
fn from(err: ClientError) -> Self {
WithdrawalExecError::Execution(err.to_string())
}
}
20 changes: 17 additions & 3 deletions crates/bridge-exec/src/withdrawal_handler/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

use std::sync::Arc;

use alpen_express_btcio::rpc::traits::Wallet;
use alpen_express_btcio::rpc::traits::{Signer, Wallet};
use alpen_express_primitives::{bridge::OperatorPartialSig, l1::BitcoinAmount};
use alpen_express_rpc_api::AlpenApiClient;
use bitcoin::{secp256k1::schnorr::Signature, Address, OutPoint};
use express_bridge_tx_builder::withdrawal::CooperativeWithdrawalInfo;
use express_bridge_tx_builder::{prelude::*, withdrawal::CooperativeWithdrawalInfo};

use crate::withdrawal_handler::errors::{WithdrawalExecError, WithdrawalExecResult};

Expand Down Expand Up @@ -45,8 +46,21 @@ pub async fn get_operator_outpoint(
/// Sign the reimbursement transaction.
pub async fn sign_reimbursement_tx(
_withdrawal_info: &CooperativeWithdrawalInfo,
l2_rpc_client: &Arc<impl AlpenApiClient + Sync>,
l1_rpc_client: &Arc<impl Signer>,

Check warning on line 50 in crates/bridge-exec/src/withdrawal_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/withdrawal_handler/handler.rs#L49-L50

Added lines #L49 - L50 were not covered by tests
) -> WithdrawalExecResult<OperatorPartialSig> {
unimplemented!()
let _network = l2_rpc_client.get_l1_status().await?.network;
let _operator_pubkeys = l2_rpc_client.get_active_operator_chain_pubkey_set().await?;

Check warning on line 53 in crates/bridge-exec/src/withdrawal_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/withdrawal_handler/handler.rs#L52-L53

Added lines #L52 - L53 were not covered by tests

// TODO: sign the transaction with MuSig2 and put inside the OperatorPartialSig
let xpriv = l1_rpc_client.get_xpriv().await?;
if let Some(_xpriv) = xpriv {
todo!()

Check warning on line 58 in crates/bridge-exec/src/withdrawal_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/withdrawal_handler/handler.rs#L56-L58

Added lines #L56 - L58 were not covered by tests
} else {
Err(WithdrawalExecError::Signing(
"Could not get wallet's xpriv".to_string(),
))

Check warning on line 62 in crates/bridge-exec/src/withdrawal_handler/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/bridge-exec/src/withdrawal_handler/handler.rs#L60-L62

Added lines #L60 - L62 were not covered by tests
}
}

/// Aggregate the received signature with the ones already accumulated.
Expand Down
6 changes: 5 additions & 1 deletion crates/rpc/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Macro trait def for the `alp_` RPC namespace using jsonrpsee.
use alpen_express_db::types::L1TxStatus;
use alpen_express_primitives::bridge::OperatorIdx;
use alpen_express_primitives::bridge::{OperatorIdx, PublickeyTable};
use alpen_express_rpc_types::{
types::{BlockHeader, ClientStatus, DepositEntry, ExecUpdate, L1Status},
HexBytes, HexBytes32, NodeSyncStatus, RawBlockWitness,
Expand Down Expand Up @@ -74,6 +74,10 @@ pub trait AlpenApi {
/// Submit raw messages
#[method(name = "submitBridgeMsg")]
async fn submit_bridge_msg(&self, raw_msg: HexBytes) -> RpcResult<()>;

/// Get the operators' public key table that is used to sign transactions.
#[method(name = "getActiveOperatorChainPubkeySet")]
async fn get_active_operator_chain_pubkey_set(&self) -> RpcResult<PublickeyTable>;
}

#[cfg_attr(not(feature = "client"), rpc(server, namespace = "alpadmin"))]
Expand Down
Empty file removed crates/rpc/api/src/types.rs
Empty file.
22 changes: 20 additions & 2 deletions crates/rpc/types/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! - crate for just data structures that represents the JSON responses from Bitcoin core RPC

use alpen_express_state::{bridge_ops::WithdrawalIntent, id::L2BlockId};
use bitcoin::Txid;
use bitcoin::{Network, Txid};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand All @@ -14,7 +14,7 @@ pub struct HexBytes(#[serde(with = "hex::serde")] pub Vec<u8>);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HexBytes32(#[serde(with = "hex::serde")] pub [u8; 32]);

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Serialize, Deserialize)]

Check warning on line 17 in crates/rpc/types/src/types.rs

View check run for this annotation

Codecov / codecov/patch

crates/rpc/types/src/types.rs#L17

Added line #L17 was not covered by tests
pub struct L1Status {
/// If the last time we tried to poll the client (as of `last_update`)
/// we were successful.
Expand All @@ -38,6 +38,24 @@ pub struct L1Status {

/// UNIX millis time of the last time we got a new update from the L1 connector.
pub last_update: u64,

/// Underlying network.
pub network: Network,
}

impl Default for L1Status {
fn default() -> Self {
Self {
bitcoin_rpc_connected: Default::default(),
last_rpc_error: Default::default(),
cur_height: Default::default(),
cur_tip_blkid: Default::default(),
last_published_txid: Default::default(),
published_inscription_count: Default::default(),
last_update: Default::default(),
network: Network::Regtest,
}
}

Check warning on line 58 in crates/rpc/types/src/types.rs

View check run for this annotation

Codecov / codecov/patch

crates/rpc/types/src/types.rs#L47-L58

Added lines #L47 - L58 were not covered by tests
}

#[derive(Clone, Debug, Deserialize, Serialize)]
Expand Down
6 changes: 5 additions & 1 deletion sequencer/src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use alpen_express_db::{
traits::{ChainstateProvider, Database, L1DataProvider, L2DataProvider},
types::{L1TxEntry, L1TxStatus},
};
use alpen_express_primitives::{buf::Buf32, hash};
use alpen_express_primitives::{bridge::PublickeyTable, buf::Buf32, hash};
use alpen_express_rpc_api::{AlpenAdminApiServer, AlpenApiServer};
use alpen_express_rpc_types::{
BlockHeader, ClientStatus, DaBlob, DepositEntry, DepositState, ExecUpdate, HexBytes,
Expand Down Expand Up @@ -568,6 +568,10 @@ impl<D: Database + Send + Sync + 'static> AlpenApiServer for AlpenRpcImpl<D> {
warn!("alp_submitBridgeMsg not implemented");
Ok(())
}

async fn get_active_operator_chain_pubkey_set(&self) -> RpcResult<PublickeyTable> {
unimplemented!()
}

Check warning on line 574 in sequencer/src/rpc_server.rs

View check run for this annotation

Codecov / codecov/patch

sequencer/src/rpc_server.rs#L572-L574

Added lines #L572 - L574 were not covered by tests
}

/// Wrapper around [``tokio::task::spawn_blocking``] that handles errors in
Expand Down

0 comments on commit 239473e

Please sign in to comment.