diff --git a/taptrade-cli-demo/coordinator/src/communication/api.rs b/taptrade-cli-demo/coordinator/src/communication/api.rs index b231184..b654def 100644 --- a/taptrade-cli-demo/coordinator/src/communication/api.rs +++ b/taptrade-cli-demo/coordinator/src/communication/api.rs @@ -62,7 +62,8 @@ pub struct PublicOffers { #[derive(Serialize, Debug, Deserialize)] pub struct OfferTakenResponse { - pub trade_psbt_hex_to_sign: String, + pub escrow_output_descriptor: String, + pub escrow_tx_fee_address: String, } // request to receive the escrow psbt to sign for the specified offer to take it diff --git a/taptrade-cli-demo/coordinator/src/coordinator/mod.rs b/taptrade-cli-demo/coordinator/src/coordinator/mod.rs index 145a431..4958afe 100755 --- a/taptrade-cli-demo/coordinator/src/coordinator/mod.rs +++ b/taptrade-cli-demo/coordinator/src/coordinator/mod.rs @@ -133,11 +133,11 @@ pub async fn handle_taker_bond( } debug!("\nTaker bond validation successful"); - let escrow_psbt_data = match wallet - .assemble_escrow_psbt(database, &payload.offer.offer_id_hex) + let escrow_output_data = match wallet + .get_escrow_psbt_outputs(database, &payload.offer.offer_id_hex) .await { - Ok(escrow_psbt_data) => escrow_psbt_data, + Ok(escrow_output_data) => escrow_output_data, Err(e) => { return Err(BondError::CoordinatorError(e.to_string())); } @@ -146,10 +146,9 @@ pub async fn handle_taker_bond( if let Err(e) = database .add_taker_info_and_move_table( payload, - &escrow_psbt_data.escrow_psbt_hex_maker, - &escrow_psbt_data.escrow_psbt_hex_taker, - escrow_psbt_data.escrow_psbt_txid, - escrow_psbt_data.coordinator_escrow_pk, + &escrow_output_data.escrow_output_descriptor, + &escrow_output_data.escrow_tx_fee_address, + &escrow_output_data.coordinator_xonly_escrow_pk, ) .await { @@ -157,7 +156,8 @@ pub async fn handle_taker_bond( } Ok(OfferTakenResponse { - trade_psbt_hex_to_sign: escrow_psbt_data.escrow_psbt_hex_taker, + escrow_output_descriptor: escrow_output_data.escrow_output_descriptor, + escrow_tx_fee_address: escrow_output_data.escrow_tx_fee_address, }) } @@ -167,21 +167,22 @@ pub async fn get_offer_status_maker( ) -> Result { let database = &coordinator.coordinator_db; - let offer = match database - .fetch_taken_offer_maker(&payload.offer_id_hex, &payload.robohash_hex) + let (descriptor, fee_address) = match database + .fetch_escrow_output_information(&payload.offer_id_hex) .await { - Ok(offer) => offer, + Ok(Some(descriptor_and_fee_addr)) => (descriptor_and_fee_addr.0, descriptor_and_fee_addr.1), + Ok(None) => { + return Err(FetchOffersError::NoOffersAvailable); + } Err(e) => { return Err(FetchOffersError::Database(e.to_string())); } }; - match offer { - Some(offer) => Ok(OfferTakenResponse { - trade_psbt_hex_to_sign: offer, - }), - None => Err(FetchOffersError::NoOffersAvailable), - } + Ok(OfferTakenResponse { + escrow_output_descriptor: descriptor, + escrow_tx_fee_address: fee_address, + }) } pub async fn fetch_escrow_confirmation_status( diff --git a/taptrade-cli-demo/coordinator/src/database/mod.rs b/taptrade-cli-demo/coordinator/src/database/mod.rs index 36c5b7d..0202669 100644 --- a/taptrade-cli-demo/coordinator/src/database/mod.rs +++ b/taptrade-cli-demo/coordinator/src/database/mod.rs @@ -353,10 +353,9 @@ impl CoordinatorDB { pub async fn add_taker_info_and_move_table( &self, trade_and_taker_info: &OfferPsbtRequest, - trade_contract_psbt_maker: &str, - trade_contract_psbt_taker: &str, - trade_tx_txid: String, - escrow_taproot_pk_coordinator: String, + escrow_output_descriptor: &str, + escrow_tx_fee_address: &str, + escrow_taproot_pk_coordinator: &str, ) -> Result<()> { let public_offer = self .fetch_and_delete_offer_from_public_offers_table( @@ -368,9 +367,9 @@ impl CoordinatorDB { "INSERT OR REPLACE INTO taken_offers (offer_id, robohash_maker, robohash_taker, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address_maker, bond_address_taker, bond_amount_sat, bond_tx_hex_maker, bond_tx_hex_taker, payout_address_maker, payout_address_taker, taproot_pubkey_hex_maker, taproot_pubkey_hex_taker, musig_pub_nonce_hex_maker, musig_pubkey_hex_maker, - musig_pub_nonce_hex_taker, musig_pubkey_hex_taker, escrow_psbt_hex_maker, escrow_psbt_hex_taker, escrow_psbt_txid, escrow_psbt_is_confirmed, escrow_ongoing, + musig_pub_nonce_hex_taker, musig_pubkey_hex_taker, escrow_output_descriptor, escrow_tx_fee_address, escrow_psbt_is_confirmed, escrow_ongoing, escrow_taproot_pk_coordinator) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", ) .bind(public_offer.offer_id) .bind(public_offer.robohash_maker) @@ -392,9 +391,8 @@ impl CoordinatorDB { .bind(public_offer.musig_pubkey_hex_maker) .bind(trade_and_taker_info.trade_data.musig_pub_nonce_hex.clone()) .bind(trade_and_taker_info.trade_data.musig_pubkey_hex.clone()) - .bind(trade_contract_psbt_maker) - .bind(trade_contract_psbt_taker) - .bind(trade_tx_txid) + .bind(escrow_output_descriptor) + .bind(escrow_tx_fee_address) .bind(0) .bind(0) .bind(escrow_taproot_pk_coordinator) @@ -404,13 +402,12 @@ impl CoordinatorDB { Ok(()) } - pub async fn fetch_taken_offer_maker( + pub async fn fetch_escrow_output_information( &self, offer_id_hex: &str, - robohash_hex_maker: &str, - ) -> Result> { + ) -> Result> { let offer = sqlx::query( - "SELECT escrow_psbt_hex_maker, robohash_maker FROM taken_offers WHERE offer_id = ?", + "SELECT escrow_output_descriptor, escrow_tx_fee_address FROM taken_offers WHERE offer_id = ?", ) .bind(offer_id_hex) .fetch_optional(&*self.db_pool) @@ -419,16 +416,9 @@ impl CoordinatorDB { Some(offer) => offer, None => return Ok(None), }; - match offer.try_get::, _>("robohash_maker") { - Ok(robohash) => { - if hex::encode(robohash) == *robohash_hex_maker { - Ok(offer.try_get("escrow_psbt_hex_maker")?) - } else { - Ok(None) - } - } - Err(_) => Ok(None), - } + let descriptor = offer.try_get::("escrow_output_descriptor")?; + let fee_address = offer.try_get::("escrow_tx_fee_address")?; + Ok(Some((descriptor, fee_address))) } // returns a hashmap of RoboHash, MonitoringBond for the monitoring loop diff --git a/taptrade-cli-demo/coordinator/src/wallet/escrow_psbt.rs b/taptrade-cli-demo/coordinator/src/wallet/escrow_psbt.rs index 696a4dc..079cb4d 100644 --- a/taptrade-cli-demo/coordinator/src/wallet/escrow_psbt.rs +++ b/taptrade-cli-demo/coordinator/src/wallet/escrow_psbt.rs @@ -91,7 +91,17 @@ pub fn build_escrow_transaction_output_descriptor( // Create the descriptor let descriptor = Descriptor::new_tr(internal_agg_musig_key, Some(final_tap_tree)) .context("Error assembling escrow output descriptor")?; + descriptor.sanity_check()?; - debug!("Escrow descriptor: {}", descriptor.to_string()); + debug!("Escrow descriptor: {}", descriptor); Ok(descriptor.to_string()) } + +pub fn assemble_escrow_psbts( + coordinator: &Coordinator, + escrow_data: &EscrowPsbtConstructionData, + coordinator_pk: &XOnlyPublicKey, +) -> Result<()> { + panic!("Implement wallet.build_escrow_psbt()"); + Ok(()) +} diff --git a/taptrade-cli-demo/coordinator/src/wallet/mod.rs b/taptrade-cli-demo/coordinator/src/wallet/mod.rs index b5a53a3..e35d2ce 100644 --- a/taptrade-cli-demo/coordinator/src/wallet/mod.rs +++ b/taptrade-cli-demo/coordinator/src/wallet/mod.rs @@ -40,10 +40,9 @@ pub struct CoordinatorWallet { #[derive(Debug)] pub struct EscrowPsbt { - pub escrow_psbt_hex_maker: String, - pub escrow_psbt_hex_taker: String, - pub escrow_psbt_txid: String, - pub coordinator_escrow_pk: String, + pub escrow_output_descriptor: String, + pub escrow_tx_fee_address: String, + pub coordinator_xonly_escrow_pk: String, } #[derive(PartialEq, Debug, Clone)] @@ -232,23 +231,22 @@ impl CoordinatorWallet { Ok(()) } - pub async fn assemble_escrow_psbt( + pub async fn get_escrow_psbt_outputs( &self, db: &Arc, trade_id: &str, ) -> Result { let escrow_pubkeys = db.fetch_escrow_tx_payout_data(trade_id).await?; let coordinator_escrow_pk = self.get_coordinator_taproot_pk().await?; - let escrow_descriptor = + let escrow_output_descriptor = build_escrow_transaction_output_descriptor(&escrow_pubkeys, &coordinator_escrow_pk)?; + let escrow_tx_fee_address = self.get_new_address().await?; - panic!("Dummy output"); - // Ok(EscrowPsbt { - // escrow_psbt_hex_maker: String::new(), - // escrow_psbt_hex_taker: String::new(), - // escrow_psbt_txid: String::new(), - // coordinator_escrow_pk, - // }) + Ok(EscrowPsbt { + escrow_output_descriptor, + escrow_tx_fee_address, + coordinator_xonly_escrow_pk: coordinator_escrow_pk.to_string(), + }) } pub async fn get_coordinator_taproot_pk(&self) -> Result { diff --git a/taptrade-cli-demo/trader/src/communication/mod.rs b/taptrade-cli-demo/trader/src/communication/mod.rs index bf822a0..c207039 100644 --- a/taptrade-cli-demo/trader/src/communication/mod.rs +++ b/taptrade-cli-demo/trader/src/communication/mod.rs @@ -75,7 +75,7 @@ impl BondSubmissionRequest { ) -> Result { let signed_bond_hex = serialize_hex(&bond.to_owned().extract_tx()); let musig_pub_nonce_hex = hex::encode(musig_data.nonce.get_pub_for_sharing()?.serialize()); - let musig_pubkey_hex = hex::encode(musig_data.public_key.0.serialize()); + let musig_pubkey_hex = hex::encode(musig_data.public_key.to_string()); let taproot_pubkey_hex = hex::encode(taproot_pubkey.serialize()); let request = BondSubmissionRequest { diff --git a/todos.md b/todos.md index 8d606b3..43b629c 100644 --- a/todos.md +++ b/todos.md @@ -9,3 +9,4 @@ Thinks to improve when implementing the production ready library/coordinator: * use the same database as the existing (python) robosats coordinator instead of separate sqlite db? * share single db for coordinator and bdk wallet instead of sqlite + bdk k/v db? * add more test coverage +* move as much logic as possible (without safety tradeoffs) to coordinator side to make client lean