From f6c5318cbaae4571f93436f17e00894f23c8c2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 12:51:38 +0300 Subject: [PATCH 01/23] refactor: Uncomment new_withdrawal_sig in operator module and fix compilation errors. --- core/src/builder/script.rs | 34 ++++- core/src/operator.rs | 302 ++++++++++++++++++++----------------- 2 files changed, 197 insertions(+), 139 deletions(-) diff --git a/core/src/builder/script.rs b/core/src/builder/script.rs index 828f1b90..e4560819 100644 --- a/core/src/builder/script.rs +++ b/core/src/builder/script.rs @@ -5,8 +5,9 @@ // Currently generate_witness functions are not yet used. #![allow(dead_code)] -use crate::EVMAddress; +use crate::{utils, EVMAddress}; use bitcoin::opcodes::OP_TRUE; +use bitcoin::script::PushBytesBuf; use bitcoin::secp256k1::schnorr; use bitcoin::{ opcodes::{all::*, OP_FALSE}, @@ -234,6 +235,37 @@ impl DepositScript { } } +/// Struct for withdrawal script. +pub struct WithdrawalScript(usize); + +impl SpendableScript for WithdrawalScript { + fn as_any(&self) -> &dyn Any { + self + } + + fn to_script_buf(&self) -> ScriptBuf { + let mut push_bytes = PushBytesBuf::new(); + push_bytes + .extend_from_slice(&utils::usize_to_var_len_bytes(self.0)) + .expect("Not possible to panic while converting index to slice"); + + Builder::new() + .push_opcode(OP_RETURN) + .push_slice(push_bytes) + .into_script() + } +} + +impl WithdrawalScript { + fn generate_witness(&self, signature: schnorr::Signature) -> Witness { + Witness::from_slice(&[signature.serialize()]) + } + + pub fn new(index: usize) -> Self { + Self(index) + } +} + #[cfg(test)] fn get_script_from_arr( arr: &Vec>, diff --git a/core/src/operator.rs b/core/src/operator.rs index 59e7e848..789c3a24 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -1,11 +1,20 @@ use crate::actor::{Actor, WinternitzDerivationPath}; +use crate::builder::transaction::input::SpendableTxIn; +use crate::builder::transaction::output::UnspentTxOut; +use crate::builder::transaction::TxHandlerBuilder; use crate::config::BridgeConfig; use crate::database::Database; use crate::errors::BridgeError; use crate::extended_rpc::ExtendedRpc; use crate::musig2::AggregateFromPublicKeys; -use crate::utils::ALL_BITVM_INTERMEDIATE_VARIABLES; -use bitcoin::{Amount, OutPoint, Txid, XOnlyPublicKey}; +use crate::utils::{self, ALL_BITVM_INTERMEDIATE_VARIABLES, SECP}; +use crate::{builder, UTXO}; +use bitcoin::consensus::deserialize; +use bitcoin::hashes::Hash; +use bitcoin::script::PushBytesBuf; +use bitcoin::secp256k1::{schnorr, Message}; +use bitcoin::{Amount, OutPoint, Sequence, Transaction, TxOut, Txid, XOnlyPublicKey}; +use bitcoincore_rpc::RpcApi; use bitvm::signatures::winternitz; use jsonrpsee::core::client::ClientT; use jsonrpsee::http_client::HttpClientBuilder; @@ -17,7 +26,7 @@ pub type PublicHash = [u8; 20]; // TODO: Make sure these are 20 bytes and maybe #[derive(Debug, Clone)] pub struct Operator { - _rpc: ExtendedRpc, + rpc: ExtendedRpc, pub db: Database, pub(crate) signer: Actor, pub(crate) config: BridgeConfig, @@ -101,7 +110,7 @@ impl Operator { ); Ok(Self { - _rpc, + rpc: _rpc, db, signer, config, @@ -339,148 +348,165 @@ impl Operator { // self.db.set_funding_utxo(None, funding_utxo).await // } - // /// Checks if the withdrawal amount is within the acceptable range. - // /// - // /// # Parameters - // /// - // /// - `input_amount`: - // /// - `withdrawal_amount`: - // fn is_profitable(&self, input_amount: Amount, withdrawal_amount: Amount) -> bool { - // if withdrawal_amount - // .to_sat() - // .wrapping_sub(input_amount.to_sat()) - // > self.config.bridge_amount_sats.to_sat() - // { - // return false; - // } - - // // Calculate net profit after the withdrawal. - // let net_profit = self.config.bridge_amount_sats - withdrawal_amount; - - // // Net profit must be bigger than withdrawal fee. - // net_profit > self.config.operator_withdrawal_fee_sats.unwrap() - // } - - // /// Checks of the withdrawal has been made on Citrea, verifies a given - // /// [`bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay`] signature, - // /// checks if it is profitable and finally, funds the withdrawal. - // /// - // /// # Parameters - // /// - // /// - `withdrawal_idx`: Citrea withdrawal UTXO index - // /// - `user_sig`: User's signature that is going to be used for signing withdrawal transaction input - // /// - `input_utxo`: - // /// - `output_txout`: - // /// - // /// # Returns - // /// - // /// Withdrawal transaction's transaction id. - // #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] - // async fn new_withdrawal_sig( - // &self, - // withdrawal_idx: u32, - // user_sig: schnorr::Signature, - // input_utxo: UTXO, - // output_txout: TxOut, - // ) -> Result { - // if let Some(citrea_client) = &self.citrea_client { - // // See: https://gist.github.com/okkothejawa/a9379b02a16dada07a2b85cbbd3c1e80 - // let params = rpc_params![ - // json!({ - // "to": "0x3100000000000000000000000000000000000002", - // "data": format!("0x471ba1e300000000000000000000000000000000000000000000000000000000{}", - // hex::encode(withdrawal_idx.to_be_bytes())), - // }), - // "latest" - // ]; - // let response: String = citrea_client.request("eth_call", params).await?; - - // let txid_response = &response[2..66]; - // let txid = hex::decode(txid_response).unwrap(); - // // txid.reverse(); // TODO: we should need to reverse this, test this with declareWithdrawalFiller - - // let txid = Txid::from_slice(&txid).unwrap(); - // if txid != input_utxo.outpoint.txid || 0 != input_utxo.outpoint.vout { - // // TODO: Fix this, vout can be different from 0 as well - // return Err(BridgeError::InvalidInputUTXO( - // txid, - // input_utxo.outpoint.txid, - // )); - // } - // } - - // if !self.is_profitable(input_utxo.txout.value, output_txout.value) { - // return Err(BridgeError::NotEnoughFeeForOperator); - // } + /// Checks if the withdrawal amount is within the acceptable range. + /// + /// # Parameters + /// + /// - `input_amount`: + /// - `withdrawal_amount`: + fn is_profitable( + &self, + input_amount: Amount, + withdrawal_amount: Amount, + ) -> Result { + if withdrawal_amount + .to_sat() + .wrapping_sub(input_amount.to_sat()) + > self.config.bridge_amount_sats.to_sat() + { + return Ok(false); + } - // let user_xonly_pk = - // XOnlyPublicKey::from_slice(&input_utxo.txout.script_pubkey.as_bytes()[2..34])?; + // Calculate net profit after the withdrawal. + let net_profit = self.config.bridge_amount_sats - withdrawal_amount; + + // Net profit must be bigger than withdrawal fee. + Ok(net_profit + > self + .config + .operator_withdrawal_fee_sats + .ok_or(BridgeError::ConfigError( + "Operator withdrawal fee sats is not specified in configuration file" + .to_string(), + ))?) + } - // let tx_ins = builder::transaction::create_tx_ins(vec![input_utxo.outpoint].into()); - // let tx_outs = vec![output_txout.clone()]; - // let mut tx = builder::transaction::create_btc_tx(tx_ins, tx_outs); + /// Checks of the withdrawal has been made on Citrea, verifies a given + /// [`bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay`] signature, + /// checks if it is profitable and finally, funds the withdrawal. + /// + /// # Parameters + /// + /// - `withdrawal_idx`: Citrea withdrawal UTXO index + /// - `user_sig`: User's signature that is going to be used for signing withdrawal transaction input + /// - `input_utxo`: + /// - `output_txout`: + /// + /// # Returns + /// + /// Withdrawal transaction's transaction id. + #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] + pub async fn new_withdrawal_sig( + &self, + withdrawal_idx: u32, + user_sig: schnorr::Signature, + input_utxo: UTXO, + output_txout: TxOut, + ) -> Result { + if let Some(citrea_client) = &self.citrea_client { + // See: https://gist.github.com/okkothejawa/a9379b02a16dada07a2b85cbbd3c1e80 + let params = rpc_params![ + json!({ + "to": "0x3100000000000000000000000000000000000002", + "data": format!("0x471ba1e300000000000000000000000000000000000000000000000000000000{}", + hex::encode(withdrawal_idx.to_be_bytes())), + }), + "latest" + ]; + let response: String = citrea_client.request("eth_call", params).await?; - // let mut sighash_cache = SighashCache::new(&tx); - // let sighash = sighash_cache.taproot_key_spend_signature_hash( - // 0, - // &bitcoin::sighash::Prevouts::One(0, &input_utxo.txout), - // bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, - // )?; + let txid_response = &response[2..66]; + let txid = hex::decode(txid_response).map_err(|e| BridgeError::Error(e.to_string()))?; + // txid.reverse(); // TODO: we should need to reverse this, test this with declareWithdrawalFiller - // let user_sig_wrapped = bitcoin::taproot::Signature { - // signature: user_sig, - // sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, - // }; - // tx.input[0].witness.push(user_sig_wrapped.serialize()); + let txid = Txid::from_slice(&txid)?; + if txid != input_utxo.outpoint.txid || 0 != input_utxo.outpoint.vout { + // TODO: Fix this, vout can be different from 0 as well + return Err(BridgeError::InvalidInputUTXO( + txid, + input_utxo.outpoint.txid, + )); + } + } - // SECP.verify_schnorr( - // &user_sig, - // &Message::from_digest(*sighash.as_byte_array()), - // &user_xonly_pk, - // )?; + if !self.is_profitable(input_utxo.txout.value, output_txout.value)? { + return Err(BridgeError::NotEnoughFeeForOperator); + } - // let mut push_bytes = PushBytesBuf::new(); - // push_bytes - // .extend_from_slice(&utils::usize_to_var_len_bytes(self.idx)) - // .unwrap(); - // let op_return_txout = builder::script::op_return_txout(push_bytes); - - // tx.output.push(op_return_txout.clone()); - - // let funded_tx = self - // .rpc - // .client - // .fund_raw_transaction( - // &tx, - // Some(&bitcoincore_rpc::json::FundRawTransactionOptions { - // add_inputs: Some(true), - // change_address: None, - // change_position: Some(1), - // change_type: None, - // include_watching: None, - // lock_unspents: None, - // fee_rate: None, - // subtract_fee_from_outputs: None, - // replaceable: None, - // conf_target: None, - // estimate_mode: None, - // }), - // None, - // ) - // .await? - // .hex; + let user_xonly_pk = + XOnlyPublicKey::from_slice(&input_utxo.txout.script_pubkey.as_bytes()[2..34])?; - // let signed_tx: Transaction = deserialize( - // &self - // .rpc - // .client - // .sign_raw_transaction_with_wallet(&funded_tx, None, None) - // .await? - // .hex, - // )?; + // let user_sig_wrapped = bitcoin::taproot::Signature { + // signature: user_sig, + // sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, + // }; + // tx.input[0].witness.push(user_sig_wrapped.serialize()); - // Ok(self.rpc.client.send_raw_transaction(&signed_tx).await?) - // } + let prevout = self + .rpc + .get_txout_from_outpoint(&input_utxo.outpoint) + .await?; + let txin = SpendableTxIn::new(input_utxo.outpoint, prevout, vec![], None); + + let txout = UnspentTxOut::new(output_txout.clone(), vec![], None); + let mut push_bytes = PushBytesBuf::new(); + push_bytes + .extend_from_slice(&utils::usize_to_var_len_bytes(self.idx)) + .expect("Not possible to panic while converting index to slice"); + let op_return_txout = builder::transaction::op_return_txout(push_bytes); + let op_return_txout = UnspentTxOut::from_partial(op_return_txout); + + let tx_handler_builder = TxHandlerBuilder::new() + .add_input(txin, Sequence::from_height(0)) + .add_output(txout) + .add_output(op_return_txout) + .finalize(); + + let sighash = tx_handler_builder.calculate_pubkey_spend_sighash( + 0, + Some(bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay), + )?; + + SECP.verify_schnorr( + &user_sig, + &Message::from_digest(*sighash.as_byte_array()), + &user_xonly_pk, + )?; + + let funded_tx = self + .rpc + .client + .fund_raw_transaction( + tx_handler_builder.get_cached_tx(), + Some(&bitcoincore_rpc::json::FundRawTransactionOptions { + add_inputs: Some(true), + change_address: None, + change_position: Some(1), + change_type: None, + include_watching: None, + lock_unspents: None, + fee_rate: None, + subtract_fee_from_outputs: None, + replaceable: None, + conf_target: None, + estimate_mode: None, + }), + None, + ) + .await? + .hex; + + let signed_tx: Transaction = deserialize( + &self + .rpc + .client + .sign_raw_transaction_with_wallet(&funded_tx, None, None) + .await? + .hex, + )?; + + Ok(self.rpc.client.send_raw_transaction(&signed_tx).await?) + } /// Checks Citrea if a withdrawal is finalized. /// From 93365a83cc615efa8d1304e5e0ca519144941c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 15:55:46 +0300 Subject: [PATCH 02/23] feat: Add payout tx creator in builder. --- .../builder/transaction/operator_reimburse.rs | 34 +++++++++++++++- core/src/operator.rs | 39 +++---------------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/core/src/builder/transaction/operator_reimburse.rs b/core/src/builder/transaction/operator_reimburse.rs index 0fd6147a..f388c2d9 100644 --- a/core/src/builder/transaction/operator_reimburse.rs +++ b/core/src/builder/transaction/operator_reimburse.rs @@ -1,10 +1,11 @@ +use super::input::SpendableTxIn; use super::txhandler::DEFAULT_SEQUENCE; use crate::builder::script::{CheckSig, TimelockScript}; use crate::builder::transaction::output::UnspentTxOut; use crate::builder::transaction::txhandler::{TxHandler, TxHandlerBuilder}; use crate::constants::{BLOCKS_PER_WEEK, MIN_TAPROOT_AMOUNT}; use crate::errors::BridgeError; -use crate::{builder, utils}; +use crate::{builder, utils, UTXO}; use bitcoin::hashes::Hash; use bitcoin::script::PushBytesBuf; use bitcoin::XOnlyPublicKey; @@ -174,3 +175,34 @@ pub fn create_reimburse_txhandler( )) .finalize()) } + +/// Creates a [`TxHandler`] for the `payout_tx`. This transaction will be sent by the operator +/// for withdrawals. +pub fn create_payout_txhandler( + input_utxo: UTXO, + output_txout: TxOut, + operator_idx: usize, +) -> Result { + // let user_sig_wrapped = bitcoin::taproot::Signature { + // signature: user_sig, + // sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, + // }; + // tx.input[0].witness.push(user_sig_wrapped.serialize()); + let txin = SpendableTxIn::new(input_utxo.outpoint, input_utxo.txout, vec![], None); + + let output_txout = UnspentTxOut::new(output_txout.clone(), vec![], None); + let mut push_bytes = PushBytesBuf::new(); + push_bytes + .extend_from_slice(&utils::usize_to_var_len_bytes(operator_idx)) + .expect("Not possible to panic while converting index to slice"); + let op_return_txout = builder::transaction::op_return_txout(push_bytes); + let op_return_txout = UnspentTxOut::from_partial(op_return_txout); + + let builder = TxHandlerBuilder::new(); + + Ok(builder + .add_input(txin, Sequence::from_height(0)) + .add_output(output_txout) + .add_output(op_return_txout) + .finalize()) +} diff --git a/core/src/operator.rs b/core/src/operator.rs index 789c3a24..bfa26b83 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -1,19 +1,15 @@ use crate::actor::{Actor, WinternitzDerivationPath}; -use crate::builder::transaction::input::SpendableTxIn; -use crate::builder::transaction::output::UnspentTxOut; -use crate::builder::transaction::TxHandlerBuilder; use crate::config::BridgeConfig; use crate::database::Database; use crate::errors::BridgeError; use crate::extended_rpc::ExtendedRpc; use crate::musig2::AggregateFromPublicKeys; -use crate::utils::{self, ALL_BITVM_INTERMEDIATE_VARIABLES, SECP}; +use crate::utils::{ALL_BITVM_INTERMEDIATE_VARIABLES, SECP}; use crate::{builder, UTXO}; use bitcoin::consensus::deserialize; use bitcoin::hashes::Hash; -use bitcoin::script::PushBytesBuf; use bitcoin::secp256k1::{schnorr, Message}; -use bitcoin::{Amount, OutPoint, Sequence, Transaction, TxOut, Txid, XOnlyPublicKey}; +use bitcoin::{Amount, OutPoint, Transaction, TxOut, Txid, XOnlyPublicKey}; use bitcoincore_rpc::RpcApi; use bitvm::signatures::winternitz; use jsonrpsee::core::client::ClientT; @@ -436,33 +432,10 @@ impl Operator { let user_xonly_pk = XOnlyPublicKey::from_slice(&input_utxo.txout.script_pubkey.as_bytes()[2..34])?; - // let user_sig_wrapped = bitcoin::taproot::Signature { - // signature: user_sig, - // sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, - // }; - // tx.input[0].witness.push(user_sig_wrapped.serialize()); + let payout_txhandler = + builder::transaction::create_payout_txhandler(input_utxo, output_txout, self.idx)?; - let prevout = self - .rpc - .get_txout_from_outpoint(&input_utxo.outpoint) - .await?; - let txin = SpendableTxIn::new(input_utxo.outpoint, prevout, vec![], None); - - let txout = UnspentTxOut::new(output_txout.clone(), vec![], None); - let mut push_bytes = PushBytesBuf::new(); - push_bytes - .extend_from_slice(&utils::usize_to_var_len_bytes(self.idx)) - .expect("Not possible to panic while converting index to slice"); - let op_return_txout = builder::transaction::op_return_txout(push_bytes); - let op_return_txout = UnspentTxOut::from_partial(op_return_txout); - - let tx_handler_builder = TxHandlerBuilder::new() - .add_input(txin, Sequence::from_height(0)) - .add_output(txout) - .add_output(op_return_txout) - .finalize(); - - let sighash = tx_handler_builder.calculate_pubkey_spend_sighash( + let sighash = payout_txhandler.calculate_pubkey_spend_sighash( 0, Some(bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay), )?; @@ -477,7 +450,7 @@ impl Operator { .rpc .client .fund_raw_transaction( - tx_handler_builder.get_cached_tx(), + payout_txhandler.get_cached_tx(), Some(&bitcoincore_rpc::json::FundRawTransactionOptions { add_inputs: Some(true), change_address: None, From fef363c42fcb99231977afd0bcc60139f1e1ae93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 16:18:12 +0300 Subject: [PATCH 03/23] feat: Add witness element in create_payout_txhandler input. --- .../builder/transaction/operator_reimburse.rs | 21 ++++++++++--------- core/src/operator.rs | 8 +++++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/core/src/builder/transaction/operator_reimburse.rs b/core/src/builder/transaction/operator_reimburse.rs index f388c2d9..ebf5dd2a 100644 --- a/core/src/builder/transaction/operator_reimburse.rs +++ b/core/src/builder/transaction/operator_reimburse.rs @@ -8,8 +8,9 @@ use crate::errors::BridgeError; use crate::{builder, utils, UTXO}; use bitcoin::hashes::Hash; use bitcoin::script::PushBytesBuf; -use bitcoin::XOnlyPublicKey; +use bitcoin::secp256k1::schnorr::Signature; use bitcoin::{Network, Sequence, TxOut, Txid}; +use bitcoin::{Witness, XOnlyPublicKey}; use std::sync::Arc; /// Creates a [`TxHandler`] for the `kickoff_tx`. This transaction will be sent by the operator @@ -182,15 +183,17 @@ pub fn create_payout_txhandler( input_utxo: UTXO, output_txout: TxOut, operator_idx: usize, + user_sig: Signature, ) -> Result { - // let user_sig_wrapped = bitcoin::taproot::Signature { - // signature: user_sig, - // sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, - // }; - // tx.input[0].witness.push(user_sig_wrapped.serialize()); + let user_sig_wrapped = bitcoin::taproot::Signature { + signature: user_sig, + sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, + }; + let witness = Witness::p2tr_key_spend(&user_sig_wrapped); let txin = SpendableTxIn::new(input_utxo.outpoint, input_utxo.txout, vec![], None); let output_txout = UnspentTxOut::new(output_txout.clone(), vec![], None); + let mut push_bytes = PushBytesBuf::new(); push_bytes .extend_from_slice(&utils::usize_to_var_len_bytes(operator_idx)) @@ -198,10 +201,8 @@ pub fn create_payout_txhandler( let op_return_txout = builder::transaction::op_return_txout(push_bytes); let op_return_txout = UnspentTxOut::from_partial(op_return_txout); - let builder = TxHandlerBuilder::new(); - - Ok(builder - .add_input(txin, Sequence::from_height(0)) + Ok(TxHandlerBuilder::new() + .add_input_with_witness(txin, Sequence::from_height(0), witness) .add_output(output_txout) .add_output(op_return_txout) .finalize()) diff --git a/core/src/operator.rs b/core/src/operator.rs index bfa26b83..ccd50b74 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -432,8 +432,12 @@ impl Operator { let user_xonly_pk = XOnlyPublicKey::from_slice(&input_utxo.txout.script_pubkey.as_bytes()[2..34])?; - let payout_txhandler = - builder::transaction::create_payout_txhandler(input_utxo, output_txout, self.idx)?; + let payout_txhandler = builder::transaction::create_payout_txhandler( + input_utxo, + output_txout, + self.idx, + user_sig, + )?; let sighash = payout_txhandler.calculate_pubkey_spend_sighash( 0, From 9f8c02322956472f8583d13054b699232a271036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 16:18:12 +0300 Subject: [PATCH 04/23] feat: Add witness element in create_payout_txhandler input. --- core/src/builder/transaction/operator_reimburse.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/builder/transaction/operator_reimburse.rs b/core/src/builder/transaction/operator_reimburse.rs index ebf5dd2a..0cf8e953 100644 --- a/core/src/builder/transaction/operator_reimburse.rs +++ b/core/src/builder/transaction/operator_reimburse.rs @@ -205,5 +205,8 @@ pub fn create_payout_txhandler( .add_input_with_witness(txin, Sequence::from_height(0), witness) .add_output(output_txout) .add_output(op_return_txout) + .add_output(UnspentTxOut::from_partial( + builder::transaction::anchor_output(), + )) .finalize()) } From 9f1ed8e998ecec15901284007d84dcd402366c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 17:13:38 +0300 Subject: [PATCH 05/23] feat: Implement operator::new_withdrawal_sig call. --- core/src/operator.rs | 2 +- core/src/rpc/operator.rs | 34 ++++++++++++++++++++++++++++++--- core/src/rpc/parser/operator.rs | 32 ++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/core/src/operator.rs b/core/src/operator.rs index ccd50b74..859aeb53 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -22,7 +22,7 @@ pub type PublicHash = [u8; 20]; // TODO: Make sure these are 20 bytes and maybe #[derive(Debug, Clone)] pub struct Operator { - rpc: ExtendedRpc, + pub rpc: ExtendedRpc, pub db: Database, pub(crate) signer: Actor, pub(crate) config: BridgeConfig, diff --git a/core/src/rpc/operator.rs b/core/src/rpc/operator.rs index be35f921..465d8722 100644 --- a/core/src/rpc/operator.rs +++ b/core/src/rpc/operator.rs @@ -6,8 +6,10 @@ use super::clementine::{ use super::error::*; use crate::builder::sighash::create_operator_sighash_stream; use crate::rpc::parser; +use crate::UTXO; use crate::{errors::BridgeError, operator::Operator}; -use bitcoin::{Amount, OutPoint}; +use bitcoin::hashes::Hash; +use bitcoin::{Amount, OutPoint, TxOut}; use futures::StreamExt; use std::pin::pin; use tokio::sync::mpsc; @@ -108,9 +110,35 @@ impl ClementineOperator for Operator { #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] async fn new_withdrawal_sig( &self, - _: Request, + request: Request, ) -> Result, Status> { - todo!() + let ( + withdrawal_id, + user_sig, + users_intent_outpoint, + users_intent_script_pubkey, + users_intent_amount, + ) = parser::operator::parse_withdrawal_sig_params(request.into_inner()).await?; + + let input_prevout = self + .rpc + .get_txout_from_outpoint(&users_intent_outpoint.expect("TODO")) + .await?; + let input_utxo = UTXO { + outpoint: users_intent_outpoint.expect("TODO"), + txout: input_prevout, + }; + let output_txout = TxOut { + value: users_intent_amount, + script_pubkey: users_intent_script_pubkey, + }; + let withdrawal_txid = self + .new_withdrawal_sig(withdrawal_id, user_sig, input_utxo, output_txout) + .await?; + + Ok(Response::new(NewWithdrawalSigResponse { + txid: withdrawal_txid.as_raw_hash().to_byte_array().to_vec(), + })) } #[tracing::instrument(skip(self), err(level = tracing::Level::ERROR), ret(level = tracing::Level::TRACE))] diff --git a/core/src/rpc/parser/operator.rs b/core/src/rpc/parser/operator.rs index aa943a56..390f9cd2 100644 --- a/core/src/rpc/parser/operator.rs +++ b/core/src/rpc/parser/operator.rs @@ -4,12 +4,15 @@ use crate::{ rpc::{ clementine::{ self, operator_params, ChallengeAckDigest, DepositParams, DepositSignSession, - OperatorParams, + NewWithdrawalSigParams, OperatorParams, }, - error::expected_msg_got_none, + error::{self, expected_msg_got_none}, }, }; -use bitcoin::{hashes::Hash, Address, Txid, XOnlyPublicKey}; +use bitcoin::{ + hashes::Hash, secp256k1::schnorr::Signature, Address, Amount, OutPoint, ScriptBuf, Txid, + XOnlyPublicKey, +}; use bitvm::signatures::winternitz; use std::str::FromStr; use tonic::Status; @@ -153,3 +156,26 @@ pub async fn parse_winternitz_public_keys( Err(expected_msg_got_none("WinternitzPubkeys")()) } } + +pub async fn parse_withdrawal_sig_params( + params: NewWithdrawalSigParams, +) -> Result<(u32, Signature, Option, ScriptBuf, Amount), Status> { + let user_sig = Signature::from_slice(¶ms.user_sig) + .map_err(|e| error::invalid_argument("user_sig", "Can't convert input to Signature")(e))?; + + let users_intent_outpoint: Option = if let Some(o) = params.users_intent_outpoint { + Some(o.try_into()?) + } else { + None + }; + + let users_intent_script_pubkey = ScriptBuf::from_bytes(params.users_intent_script_pubkey); + + Ok(( + params.withdrawal_id, + user_sig, + users_intent_outpoint, + users_intent_script_pubkey, + Amount::from_sat(params.users_intent_amount), + )) +} From 11f2993b651389eb4f56bdc09d60df204cf41308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 18:57:56 +0300 Subject: [PATCH 06/23] chore: Re-enable rpc::run_single_deposit common function. --- core/src/test_utils.rs | 1 - core/tests/common/mod.rs | 313 ++++++++++++++++----------------------- 2 files changed, 124 insertions(+), 190 deletions(-) diff --git a/core/src/test_utils.rs b/core/src/test_utils.rs index 78035979..841a9d1b 100644 --- a/core/src/test_utils.rs +++ b/core/src/test_utils.rs @@ -367,7 +367,6 @@ macro_rules! get_deposit_address { $config.network, $config.user_takes_after, ) - .0 }}; } diff --git a/core/tests/common/mod.rs b/core/tests/common/mod.rs index 49bad6a9..f4d85e78 100644 --- a/core/tests/common/mod.rs +++ b/core/tests/common/mod.rs @@ -3,26 +3,28 @@ #[path = "../../src/test_utils.rs"] mod test_utils; -// use crate::{create_test_config_with_thread_name, initialize_database}; -// use bitcoin::consensus::encode::deserialize_hex; -// use bitcoin::Address; -// use bitcoin::Amount; -// use bitcoin::OutPoint; -// use bitcoin::Transaction; -// use bitcoincore_rpc::RpcApi; -// use clementine_core::actor::Actor; -// use clementine_core::config::BridgeConfig; -// use clementine_core::database::Database; -// use clementine_core::errors::BridgeError; -// use clementine_core::extended_rpc::ExtendedRpc; -// use clementine_core::musig2::MuSigPartialSignature; -// use clementine_core::user::User; -// use clementine_core::utils::initialize_logger; -// use clementine_core::EVMAddress; -// use jsonrpsee::http_client::HttpClient; -// use jsonrpsee::server::ServerHandle; -// use std::net::SocketAddr; -// use std::{env, thread}; +use crate::initialize_database; +use crate::{create_actors, get_deposit_address}; +use bitcoin::OutPoint; +use clementine_core::actor::Actor; +use clementine_core::config::BridgeConfig; +use clementine_core::database::Database; +use clementine_core::errors::BridgeError; +use clementine_core::extended_rpc::ExtendedRpc; +use clementine_core::rpc::clementine::clementine_aggregator_client::ClementineAggregatorClient; +use clementine_core::rpc::clementine::clementine_operator_client::ClementineOperatorClient; +use clementine_core::rpc::clementine::clementine_verifier_client::ClementineVerifierClient; +use clementine_core::rpc::clementine::clementine_watchtower_client::ClementineWatchtowerClient; +use clementine_core::rpc::clementine::{DepositParams, Empty}; +use clementine_core::servers::{ + create_aggregator_grpc_server, create_operator_grpc_server, create_verifier_grpc_server, + create_watchtower_grpc_server, +}; +use clementine_core::EVMAddress; +use clementine_core::{builder, musig2::AggregateFromPublicKeys}; +use futures::future::join_all; +use tonic::transport::Channel; +use tonic::Request; // pub async fn run_multiple_deposits(test_config_name: &str) { // let config = create_test_config_with_thread_name!(test_config_name, None); @@ -246,172 +248,105 @@ mod test_utils; // assert!(txs_to_be_sent_last.len() == 4); // } -// pub async fn run_single_deposit( -// test_config_name: &str, -// ) -> Result< -// ( -// Vec<(HttpClient, ServerHandle, SocketAddr)>, -// Vec<(HttpClient, ServerHandle, SocketAddr)>, -// BridgeConfig, -// OutPoint, -// ), -// BridgeError, -// > { -// let config = create_test_config_with_thread_name!(test_config_name, None); -// let rpc = ExtendedRpc::connect( -// config.bitcoin_rpc_url.clone(), -// config.bitcoin_rpc_user.clone(), -// config.bitcoin_rpc_password.clone(), -// ) -// .await; - -// let secret_key = secp256k1::SecretKey::new(&mut secp256k1::rand::thread_rng()); -// let signer_address = Actor::new(secret_key, config.winternitz_secret_key, config.network) -// .address -// .as_unchecked() -// .clone(); - -// let user = User::new(rpc.clone_inner().await.unwrap(), secret_key, config.clone()); - -// let evm_address = EVMAddress([1u8; 20]); -// let deposit_address = user.get_deposit_address(evm_address).unwrap(); This line needs to be converted into get_deposit_address! - -// let (verifiers, operators, aggregator) = -// create_verifiers_and_operators("test_config.toml").await; - -// let deposit_outpoint = rpc -// .send_to_address(&deposit_address, config.bridge_amount_sats) -// .await -// .unwrap(); -// rpc.mine_blocks(18).await.unwrap(); - -// // for every verifier, we call new_deposit -// // aggregate nonces -// let mut pub_nonces = Vec::new(); -// for (client, _, _) in verifiers.iter() { -// let musig_pub_nonces = client -// .verifier_new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) -// .await -// .unwrap(); - -// pub_nonces.push(musig_pub_nonces); -// } - -// let agg_nonces = aggregator -// .0 -// .aggregate_pub_nonces_rpc(pub_nonces) -// .await -// .unwrap(); - -// // call operators' new_deposit -// let mut kickoff_utxos = Vec::new(); -// let mut signatures = Vec::new(); -// for (client, _, _) in operators.iter() { -// // Create deposit kickoff transaction -// let (kickoff_utxo, signature) = client -// .new_deposit_rpc(deposit_outpoint, signer_address.clone(), evm_address) -// .await -// .unwrap(); - -// kickoff_utxos.push(kickoff_utxo); -// signatures.push(signature); -// } - -// // Verifiers part starts here. -// let mut slash_or_take_partial_sigs = Vec::new(); -// for (client, ..) in verifiers.iter() { -// let (partial_sigs, _) = client -// .operator_kickoffs_generated_rpc( -// deposit_outpoint, -// kickoff_utxos.clone(), -// signatures.clone(), -// agg_nonces.clone(), -// ) -// .await -// .unwrap(); - -// slash_or_take_partial_sigs.push(partial_sigs); -// } - -// let slash_or_take_sigs = aggregator -// .0 -// .aggregate_slash_or_take_sigs_rpc( -// deposit_outpoint, -// kickoff_utxos.clone(), -// agg_nonces[config.num_operators + 1..2 * config.num_operators + 1].to_vec(), -// slash_or_take_partial_sigs, -// ) -// .await -// .unwrap(); - -// // call burn_txs_signed_rpc -// let mut operator_take_partial_sigs: Vec> = Vec::new(); -// for (client, ..) in verifiers.iter() { -// let partial_sigs = client -// .burn_txs_signed_rpc(deposit_outpoint, vec![], slash_or_take_sigs.clone()) -// .await -// .unwrap(); - -// operator_take_partial_sigs.push(partial_sigs); -// } - -// let operator_take_sigs = aggregator -// .0 -// .aggregate_operator_take_sigs_rpc( -// deposit_outpoint, -// kickoff_utxos.clone(), -// agg_nonces[1..config.num_operators + 1].to_vec(), -// operator_take_partial_sigs, -// ) -// .await -// .unwrap(); - -// // Call operator_take_txs_signed_rpc -// let mut move_tx_partial_sigs = Vec::new(); -// for (client, _, _) in verifiers.iter() { -// let move_tx_partial_sig = client -// .operator_take_txs_signed_rpc(deposit_outpoint, operator_take_sigs.clone()) -// .await -// .unwrap(); - -// move_tx_partial_sigs.push(move_tx_partial_sig); -// } - -// // Aggregate move_tx_partial_sigs -// let (move_tx, _) = aggregator -// .0 -// .aggregate_move_tx_sigs_rpc( -// deposit_outpoint, -// signer_address, -// evm_address, -// agg_nonces[0], -// move_tx_partial_sigs, -// ) -// .await -// .unwrap(); - -// let move_tx: Transaction = deserialize_hex(&move_tx).unwrap(); -// println!("Move tx weight: {:?}", move_tx.weight()); - -// let move_txid = rpc.client.send_raw_transaction(&move_tx).await.unwrap(); -// println!("Move txid: {:?}", move_txid); - -// Ok((verifiers, operators, config, deposit_outpoint)) -// } - -// #[cfg(test)] -// mod tests { -// use crate::common::{run_multiple_deposits, run_single_deposit}; - -// #[ignore = "We are switching to gRPC"] -// #[tokio::test] -// async fn test_deposit() { -// run_single_deposit("test_config.toml").await.unwrap(); -// } - -// #[ignore = "We are switching to gRPC"] -// #[tokio::test] -// async fn multiple_deposits_for_operator() { -// run_multiple_deposits("test_config.toml").await; -// } -// } +pub async fn run_single_deposit( + config: BridgeConfig, +) -> Result< + ( + Vec>, + Vec>, + ClementineAggregatorClient, + Vec>, + OutPoint, + ), + BridgeError, +> { + let rpc = ExtendedRpc::connect( + config.bitcoin_rpc_url.clone(), + config.bitcoin_rpc_user.clone(), + config.bitcoin_rpc_password.clone(), + ) + .await + .unwrap(); + + let evm_address = EVMAddress([1u8; 20]); + let (deposit_address, _) = get_deposit_address!(config, evm_address).unwrap(); + + let (verifiers, operators, aggregator, watchtowers) = create_actors!(config); + let verifiers = join_all(verifiers.iter().map(|verifier| async move { + ClementineVerifierClient::connect(format!("http://{}", verifier.0)) + .await + .unwrap() + })) + .await; + let operators = join_all(operators.iter().map(|operator| async move { + ClementineOperatorClient::connect(format!("http://{}", operator.0)) + .await + .unwrap() + })) + .await; + let mut aggregator = ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) + .await + .unwrap(); + let watchtowers = join_all(watchtowers.iter().map(|watchtower| async move { + ClementineWatchtowerClient::connect(format!("http://{}", watchtower.0)) + .await + .unwrap() + })) + .await; + + aggregator.setup(Request::new(Empty {})).await.unwrap(); + + let deposit_outpoint = rpc + .send_to_address(&deposit_address, config.bridge_amount_sats) + .await + .unwrap(); + rpc.mine_blocks(18).await.unwrap(); + + let _move_tx = aggregator + .new_deposit(DepositParams { + deposit_outpoint: Some(deposit_outpoint.into()), + evm_address: evm_address.0.to_vec(), + recovery_taproot_address: + "tb1pk8vus63mx5zwlmmmglq554kwu0zm9uhswqskxg99k66h8m3arguqfrvywa".to_string(), + user_takes_after: config.user_takes_after as u32, + }) + .await + .unwrap() + .into_inner(); + + // let move_tx: Transaction = + // Transaction::consensus_decode(&mut move_tx.raw_tx.as_slice()).unwrap(); + // let move_txid = rpc.client.send_raw_transaction(&move_tx).await.unwrap(); + // println!("Move txid: {:?}", move_txid); + // println!("Move tx weight: {:?}", move_tx.weight()); + + Ok(( + verifiers, + operators, + aggregator, + watchtowers, + deposit_outpoint, + )) +} + +#[cfg(test)] +mod tests { + use crate::common::run_single_deposit; + use crate::create_test_config_with_thread_name; + use crate::initialize_database; + use clementine_core::database::Database; + use clementine_core::{config::BridgeConfig, utils::initialize_logger}; + use std::{env, thread}; + + #[tokio::test] + async fn test_deposit() { + let config = create_test_config_with_thread_name!(None); + run_single_deposit(config).await.unwrap(); + } + + // #[ignore = "We are switching to gRPC"] + // #[tokio::test] + // async fn multiple_deposits_for_operator() { + // run_multiple_deposits("test_config.toml").await; + // } +} From a3a97f1d930f991b86c7752a96cfd5761e58a279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 21:07:55 +0300 Subject: [PATCH 07/23] test: Add client creation for create_actors and return them. --- core/src/rpc/aggregator.rs | 40 +++++++++++-------------------- core/src/test_utils.rs | 41 +++++++++++++++++++++++++++----- core/src/watchtower.rs | 48 ++++---------------------------------- core/tests/common/mod.rs | 45 +++++++++++++++++------------------ 4 files changed, 75 insertions(+), 99 deletions(-) diff --git a/core/src/rpc/aggregator.rs b/core/src/rpc/aggregator.rs index af3e2328..93b4cafc 100644 --- a/core/src/rpc/aggregator.rs +++ b/core/src/rpc/aggregator.rs @@ -714,6 +714,9 @@ impl ClementineAggregator for Aggregator { #[cfg(test)] mod tests { + use crate::rpc::clementine::clementine_operator_client::ClementineOperatorClient; + use crate::rpc::clementine::clementine_verifier_client::ClementineVerifierClient; + use crate::rpc::clementine::clementine_watchtower_client::ClementineWatchtowerClient; use crate::{ config::BridgeConfig, create_test_config_with_thread_name, @@ -742,18 +745,14 @@ mod tests { async fn aggregator_double_setup_fail() { let config = create_test_config_with_thread_name!(None); - let (_, _, aggregator, _) = create_actors!(config); - let mut aggregator_client = - ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) - .await - .unwrap(); + let (_, _, mut aggregator, _) = create_actors!(config); - aggregator_client + aggregator .setup(tonic::Request::new(clementine::Empty {})) .await .unwrap(); - assert!(aggregator_client + assert!(aggregator .setup(tonic::Request::new(clementine::Empty {})) .await .is_err()); @@ -763,12 +762,9 @@ mod tests { #[serial_test::serial] async fn aggregator_setup_watchtower_winternitz_public_keys() { let mut config = create_test_config_with_thread_name!(None); - let (_verifiers, _operators, aggregator, _watchtowers) = create_actors!(config.clone()); - let mut aggregator_client = - ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) - .await - .unwrap(); - aggregator_client + let (_verifiers, _operators, mut aggregator, _watchtowers) = create_actors!(config.clone()); + + aggregator .setup(tonic::Request::new(clementine::Empty {})) .await .unwrap(); @@ -818,12 +814,8 @@ mod tests { #[serial_test::serial] async fn aggregator_setup_watchtower_challenge_addresses() { let mut config = create_test_config_with_thread_name!(None); - let (_verifiers, _operators, aggregator, _watchtowers) = create_actors!(config.clone()); - let mut aggregator_client = - ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) - .await - .unwrap(); - aggregator_client + let (_verifiers, _operators, mut aggregator, _watchtowers) = create_actors!(config.clone()); + aggregator .setup(tonic::Request::new(clementine::Empty {})) .await .unwrap(); @@ -931,18 +923,14 @@ mod tests { async fn aggregator_setup_and_deposit() { let config = create_test_config_with_thread_name!(None); - let aggregator = create_actors!(config).2; - let mut aggregator_client = - ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) - .await - .unwrap(); + let mut aggregator = create_actors!(config).2; - aggregator_client + aggregator .setup(tonic::Request::new(clementine::Empty {})) .await .unwrap(); - aggregator_client + aggregator .new_deposit(DepositParams { deposit_outpoint: Some( bitcoin::OutPoint { diff --git a/core/src/test_utils.rs b/core/src/test_utils.rs index 841a9d1b..c392491b 100644 --- a/core/src/test_utils.rs +++ b/core/src/test_utils.rs @@ -155,6 +155,10 @@ macro_rules! initialize_database { /// create_verifier_grpc_server, create_watchtower_grpc_server, /// }, /// }; +/// use crate::rpc::clementine::clementine_aggregator_client::ClementineAggregatorClient; +/// use crate::rpc::clementine::clementine_operator_client::ClementineOperatorClient; +/// use crate::rpc::clementine::clementine_verifier_client::ClementineVerifierClient; +/// use crate::rpc::clementine::clementine_watchtower_client::ClementineWatchtowerClient; /// ``` /// /// ## Integration Tests And Binaries @@ -164,6 +168,10 @@ macro_rules! initialize_database { /// create_aggregator_grpc_server, create_operator_grpc_server, create_verifier_grpc_server, /// create_watchtower_grpc_server, /// }; +/// use clementine_core::rpc::clementine::clementine_aggregator_client::ClementineAggregatorClient; +/// use clementine_core::rpc::clementine::clementine_operator_client::ClementineOperatorClient; +/// use clementine_core::rpc::clementine::clementine_verifier_client::ClementineVerifierClient; +/// use clementine_core::rpc::clementine::clementine_watchtower_client::ClementineWatchtowerClient; /// ``` #[macro_export] macro_rules! create_actors { @@ -318,12 +326,33 @@ macro_rules! create_actors { .await .unwrap(); - ( - verifier_endpoints, - operator_endpoints, - aggregator, - watchtower_endpoints, - ) + let verifiers = + futures_util::future::join_all(verifier_endpoints.iter().map(|verifier| async move { + ClementineVerifierClient::connect(format!("http://{}", verifier.0)) + .await + .unwrap() + })) + .await; + let operators = + futures_util::future::join_all(operator_endpoints.iter().map(|operator| async move { + ClementineOperatorClient::connect(format!("http://{}", operator.0)) + .await + .unwrap() + })) + .await; + let aggregator = ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) + .await + .unwrap(); + let watchtowers = futures_util::future::join_all(watchtower_endpoints.iter().map( + |watchtower| async move { + ClementineWatchtowerClient::connect(format!("http://{}", watchtower.0)) + .await + .unwrap() + }, + )) + .await; + + (verifiers, operators, aggregator, watchtowers) }}; } diff --git a/core/src/watchtower.rs b/core/src/watchtower.rs index 3061ea23..7f8dda99 100644 --- a/core/src/watchtower.rs +++ b/core/src/watchtower.rs @@ -103,62 +103,22 @@ impl Watchtower { #[cfg(test)] mod tests { + use crate::create_test_config_with_thread_name; use crate::utils::initialize_logger; use crate::watchtower::Watchtower; - use crate::{ - config::BridgeConfig, - database::Database, - errors::BridgeError, - extended_rpc::ExtendedRpc, - initialize_database, - servers::{ - create_aggregator_grpc_server, create_operator_grpc_server, - create_verifier_grpc_server, create_watchtower_grpc_server, - }, - }; - use crate::{create_actors, create_test_config_with_thread_name}; + use crate::{config::BridgeConfig, database::Database, initialize_database}; use std::{env, thread}; #[tokio::test] - #[serial_test::serial] async fn new_watchtower() { - let mut config = create_test_config_with_thread_name!(None); - let (verifiers, operators, _, _should_not_panic) = create_actors!(config.clone()); - - config.verifier_endpoints = Some( - verifiers - .iter() - .map(|v| format!("http://{}", v.0)) - .collect(), - ); - config.operator_endpoints = Some( - operators - .iter() - .map(|o| format!("http://{}", o.0)) - .collect(), - ); + let config = create_test_config_with_thread_name!(None); let _should_not_panic = Watchtower::new(config.clone()).await.unwrap(); } #[tokio::test] - #[serial_test::serial] async fn get_watchtower_winternitz_public_keys() { - let mut config = create_test_config_with_thread_name!(None); - let (verifiers, operators, _, _watchtowers) = create_actors!(config.clone()); - - config.verifier_endpoints = Some( - verifiers - .iter() - .map(|v| format!("http://{}", v.0)) - .collect(), - ); - config.operator_endpoints = Some( - operators - .iter() - .map(|o| format!("http://{}", o.0)) - .collect(), - ); + let config = create_test_config_with_thread_name!(None); let watchtower = Watchtower::new(config.clone()).await.unwrap(); let watchtower_winternitz_public_keys = watchtower diff --git a/core/tests/common/mod.rs b/core/tests/common/mod.rs index f4d85e78..7a239018 100644 --- a/core/tests/common/mod.rs +++ b/core/tests/common/mod.rs @@ -22,7 +22,6 @@ use clementine_core::servers::{ }; use clementine_core::EVMAddress; use clementine_core::{builder, musig2::AggregateFromPublicKeys}; -use futures::future::join_all; use tonic::transport::Channel; use tonic::Request; @@ -271,28 +270,28 @@ pub async fn run_single_deposit( let evm_address = EVMAddress([1u8; 20]); let (deposit_address, _) = get_deposit_address!(config, evm_address).unwrap(); - let (verifiers, operators, aggregator, watchtowers) = create_actors!(config); - let verifiers = join_all(verifiers.iter().map(|verifier| async move { - ClementineVerifierClient::connect(format!("http://{}", verifier.0)) - .await - .unwrap() - })) - .await; - let operators = join_all(operators.iter().map(|operator| async move { - ClementineOperatorClient::connect(format!("http://{}", operator.0)) - .await - .unwrap() - })) - .await; - let mut aggregator = ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) - .await - .unwrap(); - let watchtowers = join_all(watchtowers.iter().map(|watchtower| async move { - ClementineWatchtowerClient::connect(format!("http://{}", watchtower.0)) - .await - .unwrap() - })) - .await; + let (verifiers, operators, mut aggregator, watchtowers) = create_actors!(config); + // let verifiers = join_all(verifiers.iter().map(|verifier| async move { + // ClementineVerifierClient::connect(format!("http://{}", verifier.0)) + // .await + // .unwrap() + // })) + // .await; + // let operators = join_all(operators.iter().map(|operator| async move { + // ClementineOperatorClient::connect(format!("http://{}", operator.0)) + // .await + // .unwrap() + // })) + // .await; + // let mut aggregator = ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) + // .await + // .unwrap(); + // let watchtowers = join_all(watchtowers.iter().map(|watchtower| async move { + // ClementineWatchtowerClient::connect(format!("http://{}", watchtower.0)) + // .await + // .unwrap() + // })) + // .await; aggregator.setup(Request::new(Empty {})).await.unwrap(); From f4a1d89058d5875d863dd5d632b6a8cefe2355b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 21:10:51 +0300 Subject: [PATCH 08/23] test: Don't unwrap and return err in run_single_deposit. --- core/tests/common/mod.rs | 42 +++++++++------------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/core/tests/common/mod.rs b/core/tests/common/mod.rs index 7a239018..ef1d40bf 100644 --- a/core/tests/common/mod.rs +++ b/core/tests/common/mod.rs @@ -264,42 +264,19 @@ pub async fn run_single_deposit( config.bitcoin_rpc_user.clone(), config.bitcoin_rpc_password.clone(), ) - .await - .unwrap(); + .await?; let evm_address = EVMAddress([1u8; 20]); - let (deposit_address, _) = get_deposit_address!(config, evm_address).unwrap(); + let (deposit_address, _) = get_deposit_address!(config, evm_address)?; let (verifiers, operators, mut aggregator, watchtowers) = create_actors!(config); - // let verifiers = join_all(verifiers.iter().map(|verifier| async move { - // ClementineVerifierClient::connect(format!("http://{}", verifier.0)) - // .await - // .unwrap() - // })) - // .await; - // let operators = join_all(operators.iter().map(|operator| async move { - // ClementineOperatorClient::connect(format!("http://{}", operator.0)) - // .await - // .unwrap() - // })) - // .await; - // let mut aggregator = ClementineAggregatorClient::connect(format!("http://{}", aggregator.0)) - // .await - // .unwrap(); - // let watchtowers = join_all(watchtowers.iter().map(|watchtower| async move { - // ClementineWatchtowerClient::connect(format!("http://{}", watchtower.0)) - // .await - // .unwrap() - // })) - // .await; - - aggregator.setup(Request::new(Empty {})).await.unwrap(); + + aggregator.setup(Request::new(Empty {})).await?; let deposit_outpoint = rpc .send_to_address(&deposit_address, config.bridge_amount_sats) - .await - .unwrap(); - rpc.mine_blocks(18).await.unwrap(); + .await?; + rpc.mine_blocks(18).await?; let _move_tx = aggregator .new_deposit(DepositParams { @@ -309,13 +286,12 @@ pub async fn run_single_deposit( "tb1pk8vus63mx5zwlmmmglq554kwu0zm9uhswqskxg99k66h8m3arguqfrvywa".to_string(), user_takes_after: config.user_takes_after as u32, }) - .await - .unwrap() + .await? .into_inner(); // let move_tx: Transaction = - // Transaction::consensus_decode(&mut move_tx.raw_tx.as_slice()).unwrap(); - // let move_txid = rpc.client.send_raw_transaction(&move_tx).await.unwrap(); + // Transaction::consensus_decode(&mut move_tx.raw_tx.as_slice())?; + // let move_txid = rpc.client.send_raw_transaction(&move_tx).await?; // println!("Move txid: {:?}", move_txid); // println!("Move tx weight: {:?}", move_tx.weight()); From 7633d38fcb226cab8af43038337426c460818650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 22:46:09 +0300 Subject: [PATCH 09/23] test: Enable honest_operator_takes_refund test. --- .../builder/transaction/operator_reimburse.rs | 2 +- core/tests/common/mod.rs | 5 +- core/tests/rpc.rs | 170 ++++++++++-------- 3 files changed, 96 insertions(+), 81 deletions(-) diff --git a/core/src/builder/transaction/operator_reimburse.rs b/core/src/builder/transaction/operator_reimburse.rs index 0cf8e953..7269e464 100644 --- a/core/src/builder/transaction/operator_reimburse.rs +++ b/core/src/builder/transaction/operator_reimburse.rs @@ -202,7 +202,7 @@ pub fn create_payout_txhandler( let op_return_txout = UnspentTxOut::from_partial(op_return_txout); Ok(TxHandlerBuilder::new() - .add_input_with_witness(txin, Sequence::from_height(0), witness) + .add_input_with_witness(txin, DEFAULT_SEQUENCE, witness) .add_output(output_txout) .add_output(op_return_txout) .add_output(UnspentTxOut::from_partial( diff --git a/core/tests/common/mod.rs b/core/tests/common/mod.rs index ef1d40bf..5752bb1f 100644 --- a/core/tests/common/mod.rs +++ b/core/tests/common/mod.rs @@ -282,8 +282,7 @@ pub async fn run_single_deposit( .new_deposit(DepositParams { deposit_outpoint: Some(deposit_outpoint.into()), evm_address: evm_address.0.to_vec(), - recovery_taproot_address: - "tb1pk8vus63mx5zwlmmmglq554kwu0zm9uhswqskxg99k66h8m3arguqfrvywa".to_string(), + recovery_taproot_address: deposit_address.to_string(), user_takes_after: config.user_takes_after as u32, }) .await? @@ -311,9 +310,9 @@ mod tests { use crate::initialize_database; use clementine_core::database::Database; use clementine_core::{config::BridgeConfig, utils::initialize_logger}; - use std::{env, thread}; #[tokio::test] + #[serial_test::serial] async fn test_deposit() { let config = create_test_config_with_thread_name!(None); run_single_deposit(config).await.unwrap(); diff --git a/core/tests/rpc.rs b/core/tests/rpc.rs index 32adfc7e..3055de5c 100644 --- a/core/tests/rpc.rs +++ b/core/tests/rpc.rs @@ -2,85 +2,101 @@ //! //! This tests checks if typical RPC flows works or not. -mod common; - -// #[ignore = "We are switching to gRPC"] -// #[tokio::test] -// #[serial_test::serial] -// async fn honest_operator_takes_refund() { -// let (_verifiers, operators, config, deposit_outpoint) = -// run_single_deposit("test_config.toml").await.unwrap(); -// let rpc = ExtendedRpc::connect( -// config.bitcoin_rpc_url.clone(), -// config.bitcoin_rpc_user.clone(), -// config.bitcoin_rpc_password.clone(), -// ) -// .await; +use bitcoin::{secp256k1::SecretKey, Address, Amount}; +use clementine_core::rpc::clementine::{NewWithdrawalSigParams, WithdrawalFinalizedParams}; +use clementine_core::{actor::Actor, builder, UTXO}; +use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; +use clementine_core::{extended_rpc::ExtendedRpc, utils::SECP}; +use common::run_single_deposit; +use tonic::Request; -// let user_sk = SecretKey::from_slice(&[13u8; 32]).unwrap(); -// let user = User::new(rpc.clone_inner().await.unwrap(), user_sk, config.clone()); - -// let withdrawal_address = Address::p2tr( -// &SECP, -// user_sk.x_only_public_key(&SECP).0, -// None, -// config.network, -// ); - -// // We are giving enough sats to the user so that the operator can pay the -// // withdrawal and profit. -// let withdrawal_amount = Amount::from_sat( -// config.bridge_amount_sats.to_sat() -// - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), -// ); - -// let (empty_utxo, withdrawal_tx_out, user_sig) = user -// .generate_withdrawal_transaction_and_signature(withdrawal_address, withdrawal_amount) This line needs to be converted into generate_withdrawal_transaction_and_signature! -// .await -// .unwrap(); - -// let _withdrawal_provide_txid = operators[1] -// .0 -// .new_withdrawal_sig_rpc(0, user_sig, empty_utxo, withdrawal_tx_out) -// .await -// .unwrap(); - -// let txs_to_be_sent = operators[1] -// .0 -// .withdrawal_proved_on_citrea_rpc(0, deposit_outpoint) -// .await -// .unwrap(); - -// for tx in txs_to_be_sent.iter().take(txs_to_be_sent.len() - 1) { -// rpc.client.send_raw_transaction(tx.clone()).await.unwrap(); -// rpc.mine_blocks(1).await.unwrap(); -// } -// rpc.mine_blocks(1 + config.operator_takes_after as u64) -// .await -// .unwrap(); - -// // Send last transaction. -// let operator_take_txid = rpc -// .client -// .send_raw_transaction(txs_to_be_sent.last().unwrap().clone()) -// .await -// .unwrap(); -// let operator_take_tx = rpc -// .client -// .get_raw_transaction(&operator_take_txid, None) -// .await -// .unwrap(); - -// assert!(operator_take_tx.output[0].value > withdrawal_amount); +mod common; -// assert_eq!( -// operator_take_tx.output[0].script_pubkey, -// config.operator_wallet_addresses[1] -// .clone() -// .assume_checked() -// .script_pubkey() -// ); -// } +#[serial_test::serial] +#[tokio::test] +async fn honest_operator_takes_refund() { + let config = create_test_config_with_thread_name!(None); + let rpc = ExtendedRpc::connect( + config.bitcoin_rpc_url.clone(), + config.bitcoin_rpc_user.clone(), + config.bitcoin_rpc_password.clone(), + ) + .await + .unwrap(); + + let (_verifiers, mut operators, _aggregator, _watchtowers, deposit_outpoint) = + run_single_deposit(config.clone()).await.unwrap(); + + let user_sk = SecretKey::from_slice(&[13u8; 32]).unwrap(); + + let withdrawal_address = Address::p2tr( + &SECP, + user_sk.x_only_public_key(&SECP).0, + None, + config.network, + ); + + // We are giving enough sats to the user so that the operator can pay the + // withdrawal and profit. + let withdrawal_amount = Amount::from_sat( + config.bridge_amount_sats.to_sat() + - 2 * config.operator_withdrawal_fee_sats.unwrap().to_sat(), + ); + + let (empty_utxo, _withdrawal_tx_out, user_sig) = generate_withdrawal_transaction_and_signature!( + config, + rpc, + withdrawal_address, + withdrawal_amount + ); + + let request = Request::new(NewWithdrawalSigParams { + withdrawal_id: 0, + user_sig: user_sig.serialize().to_vec(), + users_intent_outpoint: Some(empty_utxo.outpoint.into()), + users_intent_script_pubkey: _withdrawal_tx_out.txout().script_pubkey.clone().into(), + users_intent_amount: withdrawal_amount.to_sat(), + output_script_pubkey: vec![], + output_amount: withdrawal_amount.to_sat(), + }); + let _withdrawal_provide_txid = operators[1].new_withdrawal_sig(request).await.unwrap(); + + let request = Request::new(WithdrawalFinalizedParams { + withdrawal_id: 0, + deposit_outpoint: Some(deposit_outpoint.into()), + }); + operators[1].withdrawal_finalized(request).await.unwrap(); + + // for tx in txs_to_be_sent.iter().take(txs_to_be_sent.len() - 1) { + // rpc.client.send_raw_transaction(tx.clone()).await.unwrap(); + // rpc.mine_blocks(1).await.unwrap(); + // } + rpc.mine_blocks(1 + config.operator_takes_after as u64) + .await + .unwrap(); + + // Send last transaction. + // let operator_take_txid = rpc + // .client + // .send_raw_transaction(txs_to_be_sent.last().unwrap().clone()) + // .await + // .unwrap(); + // let operator_take_tx = rpc + // .client + // .get_raw_transaction(&operator_take_txid, None) + // .await + // .unwrap(); + + // assert!(operator_take_tx.output[0].value > withdrawal_amount); + + // assert_eq!( + // operator_take_tx.output[0].script_pubkey, + // config.operator_wallet_addresses[1] + // .clone() + // .assume_checked() + // .script_pubkey() + // ); +} // #[ignore = "We are switching to gRPC"] // #[tokio::test] From c05c5cebf01429c50e1daa5952990d5cc253b25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 22:46:58 +0300 Subject: [PATCH 10/23] chore: Remove required std::{env, thread} use from create_test_config_with_thread_name macro. --- core/src/actor.rs | 2 -- core/src/builder/sighash.rs | 1 - core/src/database/header_chain_prover.rs | 1 - core/src/database/mod.rs | 1 - core/src/database/operator.rs | 1 - core/src/database/verifier.rs | 1 - core/src/database/watchtower.rs | 1 - core/src/database/wrapper.rs | 1 - core/src/header_chain_prover/blockgazer.rs | 1 - core/src/header_chain_prover/mod.rs | 1 - core/src/header_chain_prover/prover.rs | 1 - core/src/operator.rs | 1 - core/src/rpc/aggregator.rs | 2 +- core/src/test_utils.rs | 31 +++++++++++++--------- core/src/watchtower.rs | 1 - core/tests/musig2.rs | 1 - core/tests/taproot.rs | 1 - 17 files changed, 20 insertions(+), 29 deletions(-) diff --git a/core/src/actor.rs b/core/src/actor.rs index f3e6e46d..5fd32198 100644 --- a/core/src/actor.rs +++ b/core/src/actor.rs @@ -315,9 +315,7 @@ mod tests { treepp::script, }; use secp256k1::rand; - use std::env; use std::str::FromStr; - use std::thread; /// Returns a valid [`TxHandler`]. fn create_valid_mock_tx_handler(actor: &Actor) -> TxHandler { diff --git a/core/src/builder/sighash.rs b/core/src/builder/sighash.rs index 03de726b..50bdafb7 100644 --- a/core/src/builder/sighash.rs +++ b/core/src/builder/sighash.rs @@ -467,7 +467,6 @@ mod tests { use bitcoin::{Amount, OutPoint, ScriptBuf, TapSighash, Txid, XOnlyPublicKey}; use futures::StreamExt; use std::pin::pin; - use std::{env, thread}; #[tokio::test] async fn calculate_num_required_nofn_sigs() { diff --git a/core/src/database/header_chain_prover.rs b/core/src/database/header_chain_prover.rs index 56d790a2..1236ccf4 100644 --- a/core/src/database/header_chain_prover.rs +++ b/core/src/database/header_chain_prover.rs @@ -182,7 +182,6 @@ mod tests { use bitcoin::{BlockHash, CompactTarget, TxMerkleNode}; use borsh::BorshDeserialize; use risc0_zkvm::Receipt; - use std::{env, thread}; #[tokio::test] async fn save_get_new_block() { diff --git a/core/src/database/mod.rs b/core/src/database/mod.rs index 646e3039..6c5e1819 100644 --- a/core/src/database/mod.rs +++ b/core/src/database/mod.rs @@ -119,7 +119,6 @@ mod tests { use crate::create_test_config_with_thread_name; use crate::{config::BridgeConfig, database::Database}; use crate::{initialize_database, utils::initialize_logger}; - use std::{env, thread}; #[tokio::test] async fn valid_database_connection() { diff --git a/core/src/database/operator.rs b/core/src/database/operator.rs index b9f84e60..4a951686 100644 --- a/core/src/database/operator.rs +++ b/core/src/database/operator.rs @@ -728,7 +728,6 @@ mod tests { }; use crate::{create_test_config_with_thread_name, UTXO}; use std::str::FromStr; - use std::{env, thread}; #[tokio::test] async fn save_get_operators() { diff --git a/core/src/database/verifier.rs b/core/src/database/verifier.rs index e4f3e891..f427a109 100644 --- a/core/src/database/verifier.rs +++ b/core/src/database/verifier.rs @@ -284,7 +284,6 @@ mod tests { }; use crypto_bigint::rand_core::OsRng; use secp256k1::musig::MusigPubNonce; - use std::{env, thread}; #[tokio::test] async fn test_verifiers_kickoff_utxos_1() { diff --git a/core/src/database/watchtower.rs b/core/src/database/watchtower.rs index 5facb45e..9da62544 100644 --- a/core/src/database/watchtower.rs +++ b/core/src/database/watchtower.rs @@ -176,7 +176,6 @@ mod tests { use bitcoin::{ScriptBuf, XOnlyPublicKey}; use bitvm::signatures::winternitz::{self}; use secp256k1::rand; - use std::{env, thread}; #[tokio::test] async fn set_get_winternitz_public_key() { diff --git a/core/src/database/wrapper.rs b/core/src/database/wrapper.rs index 3faa267f..062720cc 100644 --- a/core/src/database/wrapper.rs +++ b/core/src/database/wrapper.rs @@ -284,7 +284,6 @@ mod tests { Amount, BlockHash, CompactTarget, OutPoint, ScriptBuf, TxMerkleNode, TxOut, Txid, }; use sqlx::{Executor, Type}; - use std::{env, thread}; macro_rules! test_encode_decode_invariant { ($db_type:ty, $inner:ty, $db_wrapper:expr, $table_name:expr, $column_type:expr) => { diff --git a/core/src/header_chain_prover/blockgazer.rs b/core/src/header_chain_prover/blockgazer.rs index eab29f6d..1d14ebe4 100644 --- a/core/src/header_chain_prover/blockgazer.rs +++ b/core/src/header_chain_prover/blockgazer.rs @@ -214,7 +214,6 @@ mod tests { }; use bitcoin::BlockHash; use bitcoincore_rpc::RpcApi; - use std::{env, thread}; async fn mine_and_save_blocks(prover: &HeaderChainProver, height: u64) -> Vec { let mut fork_block_hashes = Vec::new(); diff --git a/core/src/header_chain_prover/mod.rs b/core/src/header_chain_prover/mod.rs index 70d1a1c4..c3340e96 100644 --- a/core/src/header_chain_prover/mod.rs +++ b/core/src/header_chain_prover/mod.rs @@ -113,7 +113,6 @@ mod tests { use borsh::BorshDeserialize; use risc0_zkvm::Receipt; use std::time::Duration; - use std::{env, thread}; use tokio::time::sleep; #[tokio::test] diff --git a/core/src/header_chain_prover/prover.rs b/core/src/header_chain_prover/prover.rs index ade17de8..ace9712f 100644 --- a/core/src/header_chain_prover/prover.rs +++ b/core/src/header_chain_prover/prover.rs @@ -182,7 +182,6 @@ mod tests { }; use bitcoincore_rpc::RpcApi; use header_chain::header_chain::{BlockHeaderCircuitOutput, CircuitBlockHeader}; - use std::{env, thread}; async fn mine_and_get_first_n_block_headers( rpc: ExtendedRpc, diff --git a/core/src/operator.rs b/core/src/operator.rs index 859aeb53..5e09af6b 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -785,7 +785,6 @@ mod tests { use crate::{ create_test_config_with_thread_name, extended_rpc::ExtendedRpc, operator::Operator, }; - use std::{env, thread}; // #[tokio::test] // async fn set_funding_utxo() { diff --git a/core/src/rpc/aggregator.rs b/core/src/rpc/aggregator.rs index 93b4cafc..8129237d 100644 --- a/core/src/rpc/aggregator.rs +++ b/core/src/rpc/aggregator.rs @@ -738,7 +738,7 @@ mod tests { watchtower::Watchtower, }; use bitcoin::Txid; - use std::{env, str::FromStr, thread}; + use std::str::FromStr; #[tokio::test] #[serial_test::serial] diff --git a/core/src/test_utils.rs b/core/src/test_utils.rs index c392491b..55376722 100644 --- a/core/src/test_utils.rs +++ b/core/src/test_utils.rs @@ -24,21 +24,19 @@ /// use crate::{ /// config::BridgeConfig, database::Database, initialize_database, utils::initialize_logger, /// }; -/// use std::{env, thread}; /// ``` /// /// ## Integration Tests And Binaries /// /// ```rust /// use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; -/// use std::{env, thread}; /// ``` #[macro_export] macro_rules! create_test_config_with_thread_name { ($suffix:expr) => {{ let suffix = $suffix.unwrap_or(&String::default()).to_string(); - let handle = thread::current() + let handle = std::thread::current() .name() .unwrap() .split(':') @@ -53,12 +51,12 @@ macro_rules! create_test_config_with_thread_name { let mut config = BridgeConfig::default(); // Check environment for an overwrite config. TODO: Convert this to env vars. - let env_config: Option = if let Ok(config_file_path) = env::var("TEST_CONFIG") - { - Some(BridgeConfig::try_parse_file(config_file_path.into()).unwrap()) - } else { - None - }; + let env_config: Option = + if let Ok(config_file_path) = std::env::var("TEST_CONFIG") { + Some(BridgeConfig::try_parse_file(config_file_path.into()).unwrap()) + } else { + None + }; config.db_name = handle.to_string(); @@ -445,14 +443,23 @@ macro_rules! generate_withdrawal_transaction_and_signature { }, }; - let txins = builder::transaction::create_tx_ins(vec![dust_utxo.outpoint].into()); + let txin = builder::transaction::input::SpendableTxIn::new( + dust_utxo.outpoint, + dust_utxo.txout.clone(), + vec![], + None, + ); let txout = bitcoin::TxOut { value: $withdrawal_amount, script_pubkey: $withdrawal_address.script_pubkey(), }; - let txouts = vec![txout.clone()]; + let txout = builder::transaction::output::UnspentTxOut::new(txout.clone(), vec![], None); - let mut tx = builder::transaction::create_btc_tx(txins, txouts.clone()); + let tx = builder::transaction::TxHandlerBuilder::new() + .add_input(txin, builder::transaction::DEFAULT_SEQUENCE) + .add_output(txout.clone()) + .finalize(); + let mut tx = tx.get_cached_tx().clone(); let prevouts = vec![dust_utxo.txout.clone()]; let sig = signer diff --git a/core/src/watchtower.rs b/core/src/watchtower.rs index 7f8dda99..00486261 100644 --- a/core/src/watchtower.rs +++ b/core/src/watchtower.rs @@ -107,7 +107,6 @@ mod tests { use crate::utils::initialize_logger; use crate::watchtower::Watchtower; use crate::{config::BridgeConfig, database::Database, initialize_database}; - use std::{env, thread}; #[tokio::test] async fn new_watchtower() { diff --git a/core/tests/musig2.rs b/core/tests/musig2.rs index 23e6df05..0f03a29a 100644 --- a/core/tests/musig2.rs +++ b/core/tests/musig2.rs @@ -22,7 +22,6 @@ use clementine_core::{ use clementine_core::{database::Database, utils::initialize_logger}; use secp256k1::musig::{MusigAggNonce, MusigPartialSignature}; use std::sync::Arc; -use std::{env, thread}; mod common; diff --git a/core/tests/taproot.rs b/core/tests/taproot.rs index ec76bcc7..05a48ab1 100644 --- a/core/tests/taproot.rs +++ b/core/tests/taproot.rs @@ -12,7 +12,6 @@ use clementine_core::extended_rpc::ExtendedRpc; use clementine_core::utils::SECP; use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; use std::sync::Arc; -use std::{env, thread}; mod common; From 95fc4e2e22fb603cdcfa82798f6101f58c1ed70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Thu, 6 Feb 2025 22:58:06 +0300 Subject: [PATCH 11/23] chore: Remove unused code. --- core/src/builder/script.rs | 34 +--------------------------------- core/src/operator.rs | 9 +++------ core/tests/rpc.rs | 22 +++++++++++++--------- 3 files changed, 17 insertions(+), 48 deletions(-) diff --git a/core/src/builder/script.rs b/core/src/builder/script.rs index e4560819..828f1b90 100644 --- a/core/src/builder/script.rs +++ b/core/src/builder/script.rs @@ -5,9 +5,8 @@ // Currently generate_witness functions are not yet used. #![allow(dead_code)] -use crate::{utils, EVMAddress}; +use crate::EVMAddress; use bitcoin::opcodes::OP_TRUE; -use bitcoin::script::PushBytesBuf; use bitcoin::secp256k1::schnorr; use bitcoin::{ opcodes::{all::*, OP_FALSE}, @@ -235,37 +234,6 @@ impl DepositScript { } } -/// Struct for withdrawal script. -pub struct WithdrawalScript(usize); - -impl SpendableScript for WithdrawalScript { - fn as_any(&self) -> &dyn Any { - self - } - - fn to_script_buf(&self) -> ScriptBuf { - let mut push_bytes = PushBytesBuf::new(); - push_bytes - .extend_from_slice(&utils::usize_to_var_len_bytes(self.0)) - .expect("Not possible to panic while converting index to slice"); - - Builder::new() - .push_opcode(OP_RETURN) - .push_slice(push_bytes) - .into_script() - } -} - -impl WithdrawalScript { - fn generate_witness(&self, signature: schnorr::Signature) -> Witness { - Witness::from_slice(&[signature.serialize()]) - } - - pub fn new(index: usize) -> Self { - Self(index) - } -} - #[cfg(test)] fn get_script_from_arr( arr: &Vec>, diff --git a/core/src/operator.rs b/core/src/operator.rs index 5e09af6b..44441ef5 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -34,10 +34,7 @@ pub struct Operator { impl Operator { /// Creates a new `Operator`. - // #[tracing::instrument(skip_all, err(level = tracing::Level::ERROR))] - pub async fn new(config: BridgeConfig, _rpc: ExtendedRpc) -> Result { - // let num_verifiers = config.verifiers_public_keys.len(); - + pub async fn new(config: BridgeConfig, rpc: ExtendedRpc) -> Result { let signer = Actor::new( config.secret_key, config.winternitz_secret_key, @@ -82,7 +79,7 @@ impl Operator { .get_sequential_collateral_txs(Some(&mut tx), idx as i32) .await?; let collateral_funding_txid = if sequential_collateral_txs.is_empty() { - let outpoint = _rpc + let outpoint = rpc .send_to_address(&signer.address, Amount::from_sat(200_000_000)) .await?; // TODO: Is this OK to be a fixed value db.set_sequential_collateral_tx(Some(&mut tx), idx as i32, 0, outpoint.txid, 0) @@ -106,7 +103,7 @@ impl Operator { ); Ok(Self { - rpc: _rpc, + rpc, db, signer, config, diff --git a/core/tests/rpc.rs b/core/tests/rpc.rs index 3055de5c..6f899c2c 100644 --- a/core/tests/rpc.rs +++ b/core/tests/rpc.rs @@ -3,7 +3,7 @@ //! This tests checks if typical RPC flows works or not. use bitcoin::{secp256k1::SecretKey, Address, Amount}; -use clementine_core::rpc::clementine::{NewWithdrawalSigParams, WithdrawalFinalizedParams}; +use clementine_core::rpc::clementine::NewWithdrawalSigParams; use clementine_core::{actor::Actor, builder, UTXO}; use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; use clementine_core::{extended_rpc::ExtendedRpc, utils::SECP}; @@ -24,7 +24,7 @@ async fn honest_operator_takes_refund() { .await .unwrap(); - let (_verifiers, mut operators, _aggregator, _watchtowers, deposit_outpoint) = + let (_verifiers, mut operators, _aggregator, _watchtowers, _deposit_outpoint) = run_single_deposit(config.clone()).await.unwrap(); let user_sk = SecretKey::from_slice(&[13u8; 32]).unwrap(); @@ -59,13 +59,17 @@ async fn honest_operator_takes_refund() { output_script_pubkey: vec![], output_amount: withdrawal_amount.to_sat(), }); - let _withdrawal_provide_txid = operators[1].new_withdrawal_sig(request).await.unwrap(); - - let request = Request::new(WithdrawalFinalizedParams { - withdrawal_id: 0, - deposit_outpoint: Some(deposit_outpoint.into()), - }); - operators[1].withdrawal_finalized(request).await.unwrap(); + let _withdrawal_provide_txid = operators[1] + .new_withdrawal_sig(request) + .await + .unwrap() + .into_inner(); + + // let request = Request::new(WithdrawalFinalizedParams { + // withdrawal_id: 0, + // deposit_outpoint: Some(deposit_outpoint.into()), + // }); + // operators[1].withdrawal_finalized(request).await.unwrap(); // for tx in txs_to_be_sent.iter().take(txs_to_be_sent.len() - 1) { // rpc.client.send_raw_transaction(tx.clone()).await.unwrap(); From bfc207db1176c8d14f9759bc695ffd25da42d5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Fri, 7 Feb 2025 10:18:23 +0300 Subject: [PATCH 12/23] test: Disable honest_operator_takes_refund test in rpc test. --- core/tests/rpc.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/tests/rpc.rs b/core/tests/rpc.rs index 6f899c2c..2513ac2a 100644 --- a/core/tests/rpc.rs +++ b/core/tests/rpc.rs @@ -12,6 +12,7 @@ use tonic::Request; mod common; +#[ignore = "Design changes in progress"] #[serial_test::serial] #[tokio::test] async fn honest_operator_takes_refund() { @@ -75,9 +76,9 @@ async fn honest_operator_takes_refund() { // rpc.client.send_raw_transaction(tx.clone()).await.unwrap(); // rpc.mine_blocks(1).await.unwrap(); // } - rpc.mine_blocks(1 + config.operator_takes_after as u64) - .await - .unwrap(); + // rpc.mine_blocks(1 + config.operator_takes_after as u64) + // .await + // .unwrap(); // Send last transaction. // let operator_take_txid = rpc From 31bc4605d0b534bdcb030aca9bd2f19726dfc644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Fri, 7 Feb 2025 10:35:38 +0300 Subject: [PATCH 13/23] feat: Re-add WithdrawalScript to script builder. --- core/src/builder/script.rs | 34 ++++++++++++++++++- .../builder/transaction/operator_reimburse.rs | 14 ++++---- core/src/operator.rs | 1 + 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/core/src/builder/script.rs b/core/src/builder/script.rs index 828f1b90..dcf5c3f8 100644 --- a/core/src/builder/script.rs +++ b/core/src/builder/script.rs @@ -5,8 +5,9 @@ // Currently generate_witness functions are not yet used. #![allow(dead_code)] -use crate::EVMAddress; +use crate::{utils, EVMAddress}; use bitcoin::opcodes::OP_TRUE; +use bitcoin::script::PushBytesBuf; use bitcoin::secp256k1::schnorr; use bitcoin::{ opcodes::{all::*, OP_FALSE}, @@ -234,6 +235,37 @@ impl DepositScript { } } +/// Struct for withdrawal script. +pub struct WithdrawalScript(usize); + +impl SpendableScript for WithdrawalScript { + fn as_any(&self) -> &dyn Any { + self + } + + fn to_script_buf(&self) -> ScriptBuf { + let mut push_bytes = PushBytesBuf::new(); + push_bytes + .extend_from_slice(&utils::usize_to_var_len_bytes(self.0)) + .expect("Not possible to panic while adding a 4 to 8 bytes of slice"); + + Builder::new() + .push_opcode(OP_RETURN) + .push_slice(push_bytes) + .into_script() + } +} + +impl WithdrawalScript { + fn generate_witness(&self, signature: schnorr::Signature) -> Witness { + Witness::from_slice(&[signature.serialize()]) + } + + pub fn new(index: usize) -> Self { + Self(index) + } +} + #[cfg(test)] fn get_script_from_arr( arr: &Vec>, diff --git a/core/src/builder/transaction/operator_reimburse.rs b/core/src/builder/transaction/operator_reimburse.rs index 7269e464..3cf90cb7 100644 --- a/core/src/builder/transaction/operator_reimburse.rs +++ b/core/src/builder/transaction/operator_reimburse.rs @@ -1,6 +1,6 @@ use super::input::SpendableTxIn; use super::txhandler::DEFAULT_SEQUENCE; -use crate::builder::script::{CheckSig, TimelockScript}; +use crate::builder::script::{CheckSig, SpendableScript, TimelockScript, WithdrawalScript}; use crate::builder::transaction::output::UnspentTxOut; use crate::builder::transaction::txhandler::{TxHandler, TxHandlerBuilder}; use crate::constants::{BLOCKS_PER_WEEK, MIN_TAPROOT_AMOUNT}; @@ -9,7 +9,7 @@ use crate::{builder, utils, UTXO}; use bitcoin::hashes::Hash; use bitcoin::script::PushBytesBuf; use bitcoin::secp256k1::schnorr::Signature; -use bitcoin::{Network, Sequence, TxOut, Txid}; +use bitcoin::{Amount, Network, Sequence, TxOut, Txid}; use bitcoin::{Witness, XOnlyPublicKey}; use std::sync::Arc; @@ -184,6 +184,7 @@ pub fn create_payout_txhandler( output_txout: TxOut, operator_idx: usize, user_sig: Signature, + network: bitcoin::Network, ) -> Result { let user_sig_wrapped = bitcoin::taproot::Signature { signature: user_sig, @@ -194,12 +195,9 @@ pub fn create_payout_txhandler( let output_txout = UnspentTxOut::new(output_txout.clone(), vec![], None); - let mut push_bytes = PushBytesBuf::new(); - push_bytes - .extend_from_slice(&utils::usize_to_var_len_bytes(operator_idx)) - .expect("Not possible to panic while converting index to slice"); - let op_return_txout = builder::transaction::op_return_txout(push_bytes); - let op_return_txout = UnspentTxOut::from_partial(op_return_txout); + let scripts: Vec> = + vec![Arc::new(WithdrawalScript::new(operator_idx))]; + let op_return_txout = UnspentTxOut::from_scripts(Amount::from_sat(0), scripts, None, network); Ok(TxHandlerBuilder::new() .add_input_with_witness(txin, DEFAULT_SEQUENCE, witness) diff --git a/core/src/operator.rs b/core/src/operator.rs index 44441ef5..7bbbc4ac 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -434,6 +434,7 @@ impl Operator { output_txout, self.idx, user_sig, + self.config.network, )?; let sighash = payout_txhandler.calculate_pubkey_spend_sighash( From 06438366dc305319204f728cb8445bf326a63f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Fri, 7 Feb 2025 10:40:21 +0300 Subject: [PATCH 14/23] chore: Fix compilation errors caused by the merge. --- Cargo.lock | 494 ++++++++++++++++++++----------------- core/src/operator.rs | 2 +- core/src/rpc/aggregator.rs | 4 +- 3 files changed, 274 insertions(+), 226 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25f7e456..e3a61293 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -86,11 +86,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -140,7 +141,7 @@ source = "git+https://github.com/arkworks-rs/crypto-primitives/#b13983815e5b3a0f dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -210,7 +211,7 @@ version = "0.4.2" source = "git+https://github.com/chainwayxyz/algebra/?branch=new-ate-loop#ac23fde284ca4d7ede298018f7866ce8ce64467f" dependencies = [ "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -220,7 +221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -232,7 +233,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -245,7 +246,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -296,13 +297,14 @@ dependencies = [ [[package]] name = "ark-r1cs-std" version = "0.4.0" -source = "git+https://github.com/arkworks-rs/r1cs-std/#dfdad2b729ebc7e8104931b683f3799246252adc" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de1d1472e5cb020cb3405ce2567c91c8d43f21b674aef37b0202f5c3304761db" dependencies = [ "ark-ec", "ark-ff 0.4.2", "ark-relations 0.4.0", "ark-std 0.4.0", - "educe", + "derivative", "num-bigint", "num-integer", "num-traits", @@ -324,7 +326,7 @@ dependencies = [ [[package]] name = "ark-relations" version = "0.5.1" -source = "git+https://github.com/arkworks-rs/snark/#9c528529763f1a0a2e0cba83528f93d32247d621" +source = "git+https://github.com/arkworks-rs/snark/#f632770319e1aeca64524fbeb279ce6171923d9b" dependencies = [ "ark-ff 0.5.0", "ark-poly 0.5.0", @@ -366,7 +368,7 @@ source = "git+https://github.com/chainwayxyz/algebra/?branch=new-ate-loop#ac23fd dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -377,7 +379,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -445,18 +447,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] name = "async-trait" -version = "0.1.84" +version = "0.1.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" +checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -661,7 +663,7 @@ dependencies = [ "bitcoin", "clap", "console_error_panic_hook", - "getrandom", + "getrandom 0.2.15", "lazy_static", "serde", "serde-wasm-bindgen", @@ -732,9 +734,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bitvm" @@ -807,9 +809,9 @@ dependencies = [ [[package]] name = "bonsai-sdk" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce58205497760ded0e4c743bc7a7aee28da5ca29b4adb7a635bf3bee2d118ebc" +checksum = "32a6c42e9ac4df9f62aade6f4a7fab56db33d4518d1cac37434f040f610f6d40" dependencies = [ "duplicate", "maybe-async", @@ -820,9 +822,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" dependencies = [ "borsh-derive", "cfg_aliases", @@ -830,22 +832,22 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" +checksum = "f8b668d39970baad5356d7c83a86fee3a539e6f93bf6764c97368243e17a0487" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytemuck" @@ -864,7 +866,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -875,9 +877,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" dependencies = [ "serde", ] @@ -916,9 +918,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.7" +version = "1.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" +checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" dependencies = [ "shlex", ] @@ -949,9 +951,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.23" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" dependencies = [ "clap_builder", "clap_derive", @@ -959,9 +961,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" dependencies = [ "anstream", "anstyle", @@ -971,14 +973,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -1092,9 +1094,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] @@ -1245,7 +1247,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -1285,7 +1287,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -1320,7 +1322,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -1392,7 +1394,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -1477,7 +1479,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -1529,10 +1531,22 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", +] + [[package]] name = "gimli" version = "0.31.1" @@ -1551,7 +1565,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.7.0", + "indexmap 2.7.1", "slab", "tokio", "tokio-util", @@ -1570,7 +1584,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.2.0", - "indexmap 2.7.0", + "indexmap 2.7.1", "slab", "tokio", "tokio-util", @@ -1754,9 +1768,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.5" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" [[package]] name = "httpdate" @@ -1790,9 +1804,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -1833,9 +1847,9 @@ checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http 1.2.0", - "hyper 1.5.2", + "hyper 1.6.0", "hyper-util", - "rustls 0.23.20", + "rustls 0.23.22", "rustls-pki-types", "tokio", "tokio-rustls 0.26.1", @@ -1849,7 +1863,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.5.2", + "hyper 1.6.0", "hyper-util", "pin-project-lite", "tokio", @@ -1867,7 +1881,7 @@ dependencies = [ "futures-util", "http 1.2.0", "http-body 1.0.1", - "hyper 1.5.2", + "hyper 1.6.0", "pin-project-lite", "socket2", "tokio", @@ -1990,7 +2004,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -2026,9 +2040,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -2036,9 +2050,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is_terminal_polyfill" @@ -2063,9 +2077,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -2177,7 +2191,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -2207,15 +2221,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "libc", ] [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -2235,9 +2249,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "malloc_buf" @@ -2271,7 +2285,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -2308,7 +2322,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "block", "core-graphics-types", "foreign-types", @@ -2331,9 +2345,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -2346,7 +2360,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -2357,7 +2371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -2436,15 +2450,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "option-ext" @@ -2500,34 +2514,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.7.0", + "indexmap 2.7.1", ] [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2546,12 +2560,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -2589,9 +2603,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -2622,7 +2636,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.94", + "syn 2.0.98", "tempfile", ] @@ -2636,7 +2650,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -2659,9 +2673,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.20", + "rustls 0.23.22", "socket2", - "thiserror 2.0.10", + "thiserror 2.0.11", "tokio", "tracing", ] @@ -2673,14 +2687,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", - "getrandom", + "getrandom 0.2.15", "rand", "ring", "rustc-hash", - "rustls 0.23.20", + "rustls 0.23.22", "rustls-pki-types", "slab", - "thiserror 2.0.10", + "thiserror 2.0.11", "tinyvec", "tracing", "web-time", @@ -2736,7 +2750,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -2765,7 +2779,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", ] [[package]] @@ -2774,7 +2788,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror 1.0.69", ] @@ -2837,7 +2851,7 @@ dependencies = [ "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.2", + "hyper 1.6.0", "hyper-rustls 0.27.5", "hyper-util", "ipnet", @@ -2848,7 +2862,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.20", + "rustls 0.23.22", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", @@ -2877,7 +2891,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", "spin", "untrusted", @@ -2886,9 +2900,9 @@ dependencies = [ [[package]] name = "risc0-binfmt" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fb75d62d70320adc7adae2abad354a3b7565603115dfb3134465227846475" +checksum = "fac7b3a4d7f6e86b2be2daf0ec53b9b8740895ff8279011cee24e4bae72cd77e" dependencies = [ "anyhow", "borsh", @@ -2901,9 +2915,9 @@ dependencies = [ [[package]] name = "risc0-build" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f99fb40aeeaf59dddd6b6c3a177c95e8b3c7f0fb6de7d25a0687d12398323292" +checksum = "4481ff9a05c3d96c0df2278a4681172fb40291253049a3ab57ffa2c46c24a0ba" dependencies = [ "anyhow", "cargo_metadata", @@ -2918,11 +2932,27 @@ dependencies = [ "tempfile", ] +[[package]] +name = "risc0-circuit-keccak" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25beb2e593a72e4baa3ed9a18a2ee4148f629bfa9dcdac5cbe84faa12d2590d1" +dependencies = [ + "anyhow", + "bytemuck", + "paste", + "risc0-binfmt", + "risc0-circuit-recursion", + "risc0-core", + "risc0-zkp", + "tracing", +] + [[package]] name = "risc0-circuit-recursion" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b0736401dd72a60a775e675bd0adba2e0e0e2ce2b73b63fda2899d9d7889b0" +checksum = "e02357d6333355b2f9f3903149757fec59c59ef7cefd7494738446f33148cd00" dependencies = [ "anyhow", "bytemuck", @@ -2935,9 +2965,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6d7eb9ae600c2df004bf8849db2df870fd56bd5911a2ad756fb8701350b3c6" +checksum = "d062e3ee0a8a788cfeff90777e95792d58520fb71b40c28a04000277a3f0054d" dependencies = [ "anyhow", "metal", @@ -2951,9 +2981,9 @@ dependencies = [ [[package]] name = "risc0-core" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733491635d50b742d1f30a923aa3b83d62f35cef724bbf402dfc02e6f10f587a" +checksum = "da950fcd306644dc5c2c0a09ad288901450eb5f41c42f4f2120be2949f63cd2e" dependencies = [ "bytemuck", "rand_core", @@ -2961,9 +2991,9 @@ dependencies = [ [[package]] name = "risc0-groth16" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5babc69b0db6906a6ff4011641109ca2ba06636096356b32208b0dfb26b3809" +checksum = "414481d8f3f8c666a7f45b03dd9c5e32cc6dadb2abd0f55b9460386f731eeb4a" dependencies = [ "anyhow", "ark-bn254", @@ -2982,9 +3012,9 @@ dependencies = [ [[package]] name = "risc0-zkp" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21eadc5099bf0d8ecaed718810dc5deaf237ae39a2fcb66e542e8f9660132617" +checksum = "ddf3776370f26ea04e50f7e6f9d2468807aa1049063ca1b9000e1974d092ddc5" dependencies = [ "anyhow", "blake2", @@ -3006,9 +3036,9 @@ dependencies = [ [[package]] name = "risc0-zkvm" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b619085d02d57dcafc41eb74714682797ed666621ced1814c55bbe7ae7762ba" +checksum = "6700c4875b90726b7bf9e981fccbde4ea11b3593d3b2ac6fa09c96f6de166152" dependencies = [ "anyhow", "bincode", @@ -3016,12 +3046,13 @@ dependencies = [ "borsh", "bytemuck", "bytes", - "getrandom", + "getrandom 0.2.15", "hex", "lazy-regex", "prost", "risc0-binfmt", "risc0-build", + "risc0-circuit-keccak", "risc0-circuit-recursion", "risc0-circuit-rv32im", "risc0-core", @@ -3032,7 +3063,6 @@ dependencies = [ "semver", "serde", "sha2", - "sha3", "stability", "tempfile", "tracing", @@ -3040,12 +3070,13 @@ dependencies = [ [[package]] name = "risc0-zkvm-platform" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26bbcc486222a0086d36244ae1f388cac1318270bca2dd23d77af2005d679edf" +checksum = "a6b5ac61f6d36b02655a415a8a2afd021aa260402d45deff5524c80dbc521f29" dependencies = [ "bytemuck", - "getrandom", + "cfg-if", + "getrandom 0.2.15", "libm", "stability", ] @@ -3068,17 +3099,17 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", @@ -3099,9 +3130,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.20" +version = "0.23.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" dependencies = [ "log", "once_cell", @@ -3144,9 +3175,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" dependencies = [ "web-time", ] @@ -3180,15 +3211,15 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "scc" -version = "2.3.0" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28e1c91382686d21b5ac7959341fcb9780fa7c03773646995a87c950fa7be640" +checksum = "ea091f6cac2595aa38993f04f4ee692ed43757035c36e67c180b6828356385b1" dependencies = [ "sdd", ] @@ -3233,9 +3264,9 @@ dependencies = [ [[package]] name = "sdd" -version = "3.0.5" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478f121bb72bbf63c52c93011ea1791dca40140dfe13f8336c4c5ac952c33aa9" +checksum = "b07779b9b918cc05650cb30f404d4d7835d26df37c235eded8a6832e2fb82cca" [[package]] name = "secp256k1" @@ -3283,7 +3314,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "core-foundation", "core-foundation-sys", "libc", @@ -3292,9 +3323,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -3302,9 +3333,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" dependencies = [ "serde", ] @@ -3337,14 +3368,14 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -3395,7 +3426,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -3409,16 +3440,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest", - "keccak", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -3537,7 +3558,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.7.0", + "indexmap 2.7.1", "log", "memchr", "once_cell", @@ -3600,7 +3621,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.6.0", + "bitflags 2.8.0", "byteorder", "crc", "dotenvy", @@ -3637,7 +3658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -3688,9 +3709,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.94" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "987bc0be1cdea8b10216bd06e2ca407d40b9543468fafd3ddfb02f36e77f71f3" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -3714,18 +3735,18 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] name = "tempfile" -version = "3.15.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" dependencies = [ "cfg-if", "fastrand", - "getrandom", + "getrandom 0.3.1", "once_cell", "rustix", "windows-sys 0.59.0", @@ -3742,11 +3763,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ac7f54ca534db81081ef1c1e7f6ea8a3ef428d2fc069097c079443d24124d3" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.10", + "thiserror-impl 2.0.11", ] [[package]] @@ -3757,18 +3778,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] name = "thiserror-impl" -version = "2.0.10" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -3808,9 +3829,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -3826,13 +3847,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -3851,7 +3872,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.20", + "rustls 0.23.22", "tokio", ] @@ -3882,9 +3903,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", @@ -3903,11 +3924,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", @@ -3929,7 +3950,7 @@ dependencies = [ "http 1.2.0", "http-body 1.0.1", "http-body-util", - "hyper 1.5.2", + "hyper 1.6.0", "hyper-timeout", "hyper-util", "percent-encoding", @@ -3957,7 +3978,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -4038,7 +4059,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -4122,9 +4143,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unicode-normalization" @@ -4190,9 +4211,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "version_check" @@ -4215,6 +4236,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasite" version = "0.1.0" @@ -4223,34 +4253,35 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.49" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", @@ -4261,9 +4292,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4271,22 +4302,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-streams" @@ -4303,9 +4337,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -4323,9 +4357,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.7" +version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" dependencies = [ "rustls-pki-types", ] @@ -4542,13 +4576,22 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.21" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68" +checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] + [[package]] name = "write16" version = "1.0.0" @@ -4581,7 +4624,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", "synstructure", ] @@ -4603,7 +4646,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -4623,7 +4666,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", "synstructure", ] @@ -4644,7 +4687,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] [[package]] @@ -4666,10 +4709,15 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.94", + "syn 2.0.98", ] +[[patch.unused]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "git+https://github.com/arkworks-rs/r1cs-std/#c8c51a393b11dc91e47ce7a2b6b2e9e242cc3819" + [[patch.unused]] name = "ark-snark" version = "0.5.1" -source = "git+https://github.com/arkworks-rs/snark/#9c528529763f1a0a2e0cba83528f93d32247d621" +source = "git+https://github.com/arkworks-rs/snark/#f632770319e1aeca64524fbeb279ce6171923d9b" diff --git a/core/src/operator.rs b/core/src/operator.rs index cba9abfb..06fdb31e 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -4,7 +4,7 @@ use crate::database::Database; use crate::errors::BridgeError; use crate::extended_rpc::ExtendedRpc; use crate::musig2::AggregateFromPublicKeys; -use crate::utils::{ALL_BITVM_INTERMEDIATE_VARIABLES, SECP}; +use crate::utils::SECP; use crate::{builder, UTXO}; use bitcoin::consensus::deserialize; use bitcoin::hashes::Hash; diff --git a/core/src/rpc/aggregator.rs b/core/src/rpc/aggregator.rs index 8e2f9efc..5aadcd91 100644 --- a/core/src/rpc/aggregator.rs +++ b/core/src/rpc/aggregator.rs @@ -977,7 +977,7 @@ mod tests { tracing::info!("Setting up aggregator"); let start = std::time::Instant::now(); - aggregator_client + aggregator .setup(tonic::Request::new(clementine::Empty {})) .await .unwrap(); @@ -985,7 +985,7 @@ mod tests { tracing::info!("Setup completed in {:?}", start.elapsed()); tracing::info!("Depositing"); let deposit_start = std::time::Instant::now(); - aggregator_client + aggregator .new_deposit(DepositParams { deposit_outpoint: Some( bitcoin::OutPoint { From d5914f2ec4714274fead49b25b94289d6ad3c3d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Fri, 7 Feb 2025 14:37:21 +0300 Subject: [PATCH 15/23] chore: Remove unnecessary generate_witness from WithdrawalScript in builder::script. --- core/src/builder/script.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/src/builder/script.rs b/core/src/builder/script.rs index dcf5c3f8..3e0483e1 100644 --- a/core/src/builder/script.rs +++ b/core/src/builder/script.rs @@ -257,10 +257,6 @@ impl SpendableScript for WithdrawalScript { } impl WithdrawalScript { - fn generate_witness(&self, signature: schnorr::Signature) -> Witness { - Witness::from_slice(&[signature.serialize()]) - } - pub fn new(index: usize) -> Self { Self(index) } From bcc12bd379b7226615e65c219d1952be5a0e48ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Fri, 7 Feb 2025 15:14:30 +0300 Subject: [PATCH 16/23] chore: Fix compilation errors caused by the merge. --- core/src/test_utils.rs | 11 ++++++++++- core/tests/rpc.rs | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/core/src/test_utils.rs b/core/src/test_utils.rs index 55376722..b25277e5 100644 --- a/core/src/test_utils.rs +++ b/core/src/test_utils.rs @@ -413,12 +413,16 @@ macro_rules! get_deposit_address { /// /// ```rust /// use crate::{actor::Actor, builder, UTXO}; +/// use crate::builder::script::SpendPath; +/// use crate::rpc::clementine::NormalSignatureKind; /// ``` /// /// ## Integration Tests And Binaries /// /// ```rust /// use clementine_core::{actor::Actor, builder, UTXO}; +/// use clementine_core::builder::script::SpendPath; +/// use clementine_core::rpc::clementine::NormalSignatureKind; /// ``` #[macro_export] macro_rules! generate_withdrawal_transaction_and_signature { @@ -456,7 +460,12 @@ macro_rules! generate_withdrawal_transaction_and_signature { let txout = builder::transaction::output::UnspentTxOut::new(txout.clone(), vec![], None); let tx = builder::transaction::TxHandlerBuilder::new() - .add_input(txin, builder::transaction::DEFAULT_SEQUENCE) + .add_input( + NormalSignatureKind::NotStored, + txin, + SpendPath::Unknown, + builder::transaction::DEFAULT_SEQUENCE, + ) .add_output(txout.clone()) .finalize(); let mut tx = tx.get_cached_tx().clone(); diff --git a/core/tests/rpc.rs b/core/tests/rpc.rs index 2513ac2a..24abf895 100644 --- a/core/tests/rpc.rs +++ b/core/tests/rpc.rs @@ -3,7 +3,9 @@ //! This tests checks if typical RPC flows works or not. use bitcoin::{secp256k1::SecretKey, Address, Amount}; +use clementine_core::builder::script::SpendPath; use clementine_core::rpc::clementine::NewWithdrawalSigParams; +use clementine_core::rpc::clementine::NormalSignatureKind; use clementine_core::{actor::Actor, builder, UTXO}; use clementine_core::{config::BridgeConfig, database::Database, utils::initialize_logger}; use clementine_core::{extended_rpc::ExtendedRpc, utils::SECP}; @@ -13,7 +15,6 @@ use tonic::Request; mod common; #[ignore = "Design changes in progress"] -#[serial_test::serial] #[tokio::test] async fn honest_operator_takes_refund() { let config = create_test_config_with_thread_name!(None); From fee4f72b8a33d27fe63160070721109602b1e268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Fri, 7 Feb 2025 17:39:04 +0300 Subject: [PATCH 17/23] fix: Return error if operator::new_withdrawal_sig rpc call's input doesn't include users_intent_outpoint. --- core/src/rpc/operator.rs | 4 ++-- core/src/rpc/parser/operator.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/rpc/operator.rs b/core/src/rpc/operator.rs index 76f6fa46..ca972cb9 100644 --- a/core/src/rpc/operator.rs +++ b/core/src/rpc/operator.rs @@ -122,10 +122,10 @@ impl ClementineOperator for Operator { let input_prevout = self .rpc - .get_txout_from_outpoint(&users_intent_outpoint.expect("TODO")) + .get_txout_from_outpoint(&users_intent_outpoint) .await?; let input_utxo = UTXO { - outpoint: users_intent_outpoint.expect("TODO"), + outpoint: users_intent_outpoint, txout: input_prevout, }; let output_txout = TxOut { diff --git a/core/src/rpc/parser/operator.rs b/core/src/rpc/parser/operator.rs index 390f9cd2..d09fc2a5 100644 --- a/core/src/rpc/parser/operator.rs +++ b/core/src/rpc/parser/operator.rs @@ -159,14 +159,14 @@ pub async fn parse_winternitz_public_keys( pub async fn parse_withdrawal_sig_params( params: NewWithdrawalSigParams, -) -> Result<(u32, Signature, Option, ScriptBuf, Amount), Status> { +) -> Result<(u32, Signature, OutPoint, ScriptBuf, Amount), Status> { let user_sig = Signature::from_slice(¶ms.user_sig) .map_err(|e| error::invalid_argument("user_sig", "Can't convert input to Signature")(e))?; - let users_intent_outpoint: Option = if let Some(o) = params.users_intent_outpoint { - Some(o.try_into()?) + let users_intent_outpoint: OutPoint = if let Some(o) = params.users_intent_outpoint { + o.try_into()? } else { - None + return Err(error::input_ended_prematurely()); }; let users_intent_script_pubkey = ScriptBuf::from_bytes(params.users_intent_script_pubkey); From ade8477327e4e41e9bdc3f1586765ac9d62cb411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Sat, 8 Feb 2025 11:22:09 +0300 Subject: [PATCH 18/23] test: Add key-spend spend path to withdrawal tx input in generate_withdrawal_transaction_and_signature macro. --- core/src/test_utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test_utils.rs b/core/src/test_utils.rs index b25277e5..ef9052b7 100644 --- a/core/src/test_utils.rs +++ b/core/src/test_utils.rs @@ -463,7 +463,7 @@ macro_rules! generate_withdrawal_transaction_and_signature { .add_input( NormalSignatureKind::NotStored, txin, - SpendPath::Unknown, + SpendPath::KeySpend, builder::transaction::DEFAULT_SEQUENCE, ) .add_output(txout.clone()) From ff53e323b2acd3c4c408339d55c82f7b595f22fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Sat, 8 Feb 2025 11:29:54 +0300 Subject: [PATCH 19/23] chore: Convert if let else to a one liner. --- core/src/rpc/parser/operator.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/rpc/parser/operator.rs b/core/src/rpc/parser/operator.rs index d09fc2a5..db284855 100644 --- a/core/src/rpc/parser/operator.rs +++ b/core/src/rpc/parser/operator.rs @@ -163,11 +163,10 @@ pub async fn parse_withdrawal_sig_params( let user_sig = Signature::from_slice(¶ms.user_sig) .map_err(|e| error::invalid_argument("user_sig", "Can't convert input to Signature")(e))?; - let users_intent_outpoint: OutPoint = if let Some(o) = params.users_intent_outpoint { - o.try_into()? - } else { - return Err(error::input_ended_prematurely()); - }; + let users_intent_outpoint: OutPoint = params + .users_intent_outpoint + .ok_or_else(error::input_ended_prematurely)? + .try_into()?; let users_intent_script_pubkey = ScriptBuf::from_bytes(params.users_intent_script_pubkey); From df5a4be3745027a5f2de8705cdd4315b7d05dac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Sat, 8 Feb 2025 12:21:29 +0300 Subject: [PATCH 20/23] chore: Convert UnspentTxOut::new to UnspentTxOut::from_partial in create_payout_txhandler. --- core/src/builder/transaction/operator_reimburse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/builder/transaction/operator_reimburse.rs b/core/src/builder/transaction/operator_reimburse.rs index cb55c1b5..0f1e4470 100644 --- a/core/src/builder/transaction/operator_reimburse.rs +++ b/core/src/builder/transaction/operator_reimburse.rs @@ -219,9 +219,9 @@ pub fn create_payout_txhandler( sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, }; let witness = Witness::p2tr_key_spend(&user_sig_wrapped); - let txin = SpendableTxIn::new(input_utxo.outpoint, input_utxo.txout, vec![], None); + let txin = SpendableTxIn::new_partial(input_utxo.outpoint, input_utxo.txout); - let output_txout = UnspentTxOut::new(output_txout.clone(), vec![], None); + let output_txout = UnspentTxOut::from_partial(output_txout.clone()); let scripts: Vec> = vec![Arc::new(WithdrawalScript::new(operator_idx))]; From b24856d56a11ec90baeb0e3a6e9ce852b50b5e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Sat, 8 Feb 2025 15:11:39 +0300 Subject: [PATCH 21/23] fix: Make some txhandler functions available for both signed and unsigned variants. --- core/src/builder/transaction/txhandler.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/builder/transaction/txhandler.rs b/core/src/builder/transaction/txhandler.rs index 5228d9e5..3cee7923 100644 --- a/core/src/builder/transaction/txhandler.rs +++ b/core/src/builder/transaction/txhandler.rs @@ -56,9 +56,7 @@ impl TxHandler { let txin = self.txins.get(idx).ok_or(BridgeError::TxInputNotFound)?; Ok(txin.get_signature_id()) } -} -impl TxHandler { pub fn get_cached_tx(&self) -> &Transaction { &self.cached_tx } @@ -150,7 +148,9 @@ impl TxHandler { Ok(sig_hash) } +} +impl TxHandler { pub fn promote(self) -> Result, BridgeError> { if self.txins.iter().any(|s| s.get_witness().is_none()) { return Err(BridgeError::MissingWitnessData); @@ -164,9 +164,7 @@ impl TxHandler { phantom: PhantomData::, }) } -} -impl TxHandler { /// Constructs the witness for a script path spend of a transaction input. /// /// # Arguments From ccdf5f0d70d52fa1d546b07139f7bb663e76d037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Sat, 8 Feb 2025 15:12:37 +0300 Subject: [PATCH 22/23] fix: Return a signed txhandler in create_payout_txhandler and remove anchor output. --- core/src/builder/transaction/operator_reimburse.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/core/src/builder/transaction/operator_reimburse.rs b/core/src/builder/transaction/operator_reimburse.rs index 0f1e4470..62435a15 100644 --- a/core/src/builder/transaction/operator_reimburse.rs +++ b/core/src/builder/transaction/operator_reimburse.rs @@ -1,5 +1,6 @@ use super::input::SpendableTxIn; use super::txhandler::DEFAULT_SEQUENCE; +use super::Signed; use crate::builder::script::{CheckSig, SpendableScript, TimelockScript, WithdrawalScript}; use crate::builder::transaction::output::UnspentTxOut; use crate::builder::transaction::txhandler::{TxHandler, TxHandlerBuilder}; @@ -213,7 +214,7 @@ pub fn create_payout_txhandler( operator_idx: usize, user_sig: Signature, network: bitcoin::Network, -) -> Result { +) -> Result, BridgeError> { let user_sig_wrapped = bitcoin::taproot::Signature { signature: user_sig, sighash_type: bitcoin::sighash::TapSighashType::SinglePlusAnyoneCanPay, @@ -227,12 +228,9 @@ pub fn create_payout_txhandler( vec![Arc::new(WithdrawalScript::new(operator_idx))]; let op_return_txout = UnspentTxOut::from_scripts(Amount::from_sat(0), scripts, None, network); - Ok(TxHandlerBuilder::new() + TxHandlerBuilder::new() .add_input_with_witness(txin, DEFAULT_SEQUENCE, witness) .add_output(output_txout) .add_output(op_return_txout) - .add_output(UnspentTxOut::from_partial( - builder::transaction::anchor_output(), - )) - .finalize()) + .finalize_signed() } From 8a22a4b821bb34f67c7481aca4048d40e076fd01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ceyhun=20=C5=9Een?= Date: Sat, 8 Feb 2025 15:28:36 +0300 Subject: [PATCH 23/23] docs: Add comment about a Citrea request. --- core/src/operator.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/operator.rs b/core/src/operator.rs index 06fdb31e..57796d85 100644 --- a/core/src/operator.rs +++ b/core/src/operator.rs @@ -396,6 +396,7 @@ impl Operator { input_utxo: UTXO, output_txout: TxOut, ) -> Result { + // Check Citrea for the withdrawal state. if let Some(citrea_client) = &self.citrea_client { // See: https://gist.github.com/okkothejawa/a9379b02a16dada07a2b85cbbd3c1e80 let params = rpc_params![