diff --git a/taptrade-cli-demo/coordinator/src/communication/mod.rs b/taptrade-cli-demo/coordinator/src/communication/mod.rs index 4011266..da72cbe 100755 --- a/taptrade-cli-demo/coordinator/src/communication/mod.rs +++ b/taptrade-cli-demo/coordinator/src/communication/mod.rs @@ -49,12 +49,12 @@ async fn submit_maker_bond( let bond_requirements = database.fetch_maker_request(&payload.robohash_hex).await?; // validate bond (check amounts, valid inputs, correct addresses, valid signature, feerate) - if !wallet - .validate_bond_tx_hex(&payload.signed_bond_hex, &bond_requirements) - .await? - { - return Ok(StatusCode::NOT_ACCEPTABLE.into_response()); - } + // if !wallet + // .validate_bond_tx_hex(&payload.signed_bond_hex) + // .await? + // { + // return Ok(StatusCode::NOT_ACCEPTABLE.into_response()); + // } let offer_id_hex = generate_random_order_id(16); // 16 bytes random offer id, maybe a different system makes more sense later on? (uuid or increasing counter...) // create address for taker bond let new_taker_bond_address = wallet.get_new_address().await?; @@ -94,18 +94,18 @@ async fn submit_taker_bond( let bond_requirements = database .fetch_taker_bond_requirements(&payload.offer.offer_id_hex) .await; - match bond_requirements { - Ok(bond_requirements) => { - if !wallet - .validate_bond_tx_hex(&payload.trade_data.signed_bond_hex, &bond_requirements) - .await? - { - dbg!("Taker Bond validation failed"); - return Ok(StatusCode::NOT_ACCEPTABLE.into_response()); - } - } - Err(_) => return Ok(StatusCode::NOT_FOUND.into_response()), - } + // match bond_requirements { + // Ok(bond_requirements) => { + // if !wallet + // .validate_bond_tx_hex(&payload.trade_data.signed_bond_hex, &bond_requirements) + // .await? + // { + // dbg!("Taker Bond validation failed"); + // return Ok(StatusCode::NOT_ACCEPTABLE.into_response()); + // } + // } + // Err(_) => return Ok(StatusCode::NOT_FOUND.into_response()), + // } let trade_contract_psbt_taker = "".to_string(); // implement psbt let trade_contract_psbt_maker = "".to_string(); // implement psbt diff --git a/taptrade-cli-demo/coordinator/src/wallet/bond.rs b/taptrade-cli-demo/coordinator/src/wallet/bond.rs new file mode 100644 index 0000000..d4e8914 --- /dev/null +++ b/taptrade-cli-demo/coordinator/src/wallet/bond.rs @@ -0,0 +1,2 @@ +use super::*; +use bdk::wallet::verify::verify_tx; diff --git a/taptrade-cli-demo/coordinator/src/wallet/escrow_psbt.rs b/taptrade-cli-demo/coordinator/src/wallet/escrow_psbt.rs new file mode 100644 index 0000000..e69de29 diff --git a/taptrade-cli-demo/coordinator/src/wallet/mod.rs b/taptrade-cli-demo/coordinator/src/wallet/mod.rs index 31092f3..f440261 100644 --- a/taptrade-cli-demo/coordinator/src/wallet/mod.rs +++ b/taptrade-cli-demo/coordinator/src/wallet/mod.rs @@ -1,3 +1,5 @@ +mod utils; + use super::*; use anyhow::Context; use bdk::{ @@ -10,6 +12,7 @@ use bdk::{ KeychainKind, SyncOptions, Wallet, }; use std::str::FromStr; +use utils::*; #[derive(Clone, Debug)] pub struct CoordinatorWallet { @@ -17,6 +20,12 @@ pub struct CoordinatorWallet { // database: Arc>, } +pub struct BondRequirements { + pub bond_address: String, + pub locking_amount_sat: u64, + pub min_input_sum_sat: u64, +} + impl CoordinatorWallet { pub fn init() -> Result { let wallet_xprv = ExtendedPrivKey::from_str( @@ -54,16 +63,30 @@ impl CoordinatorWallet { pub async fn validate_bond_tx_hex( &self, bond: &String, - requirements: &BondRequirementResponse, + requirements: BondRequirements, ) -> Result { let tx: Transaction = deserialize(&hex::decode(bond)?)?; let wallet = self.wallet.lock().await; + let blockchain = ElectrumBlockchain::from(Client::new( + &env::var("ELECTRUM_BACKEND") + .context("Parsing ELECTRUM_BACKEND from .env failed, is it set?")?, + )?); // we need to test this with signed and invalid/unsigned transactions - // let result = verify_tx(&tx, wallet.database(), blockchain); + // checks signatures and inputs + if let Err(e) = verify_tx(&tx, &*wallet.database(), &blockchain) { + dbg!(e); + return Ok(false); + } + + // check if the tx has the correct input amounts (have to be >= trading amount) + if tx.input_sum(&blockchain, &*wallet.database())? < requirements.min_input_sum_sat { + return Ok(false); + } + + // check if bond output to us is big enough // let valid = tx.verify_tx(); - panic!("Bond verification not implemented!"); Ok(true) } } diff --git a/taptrade-cli-demo/coordinator/src/wallet/utils.rs b/taptrade-cli-demo/coordinator/src/wallet/utils.rs new file mode 100644 index 0000000..f988884 --- /dev/null +++ b/taptrade-cli-demo/coordinator/src/wallet/utils.rs @@ -0,0 +1,43 @@ +use super::*; +use bdk::{blockchain::GetTx, database::Database}; + +pub trait BondTx { + fn input_sum(&self, blockchain: &B, db: &D) -> Result; + fn bond_output_sum(&self, bond_address: &str) -> Result; +} + +impl BondTx for Transaction { + fn input_sum(&self, blockchain: &B, db: &D) -> Result { + let mut input_sum = 0; + + for input in self.input.iter() { + let prev_tx = if let Some(prev_tx) = db.get_raw_tx(&input.previous_output.txid)? { + prev_tx + } else if let Some(prev_tx) = blockchain.get_tx(&input.previous_output.txid)? { + prev_tx + } else { + return Err(anyhow!(VerifyError::MissingInputTx( + input.previous_output.txid + ))); + }; + + let spent_output = prev_tx + .output + .get(input.previous_output.vout as usize) + .ok_or(VerifyError::InvalidInput(input.previous_output))?; + + input_sum += spent_output.value; + } + if input_sum == 0 { + return Err(anyhow!("Empty input sum in transaction")); + } + Ok(input_sum) + } + + fn bond_output_sum(&self, bond_address: &str) -> Result { + let bond_script = ScriptBuf; + + for output in self.output.iter() {} + Ok(0) + } +}