diff --git a/taptrade-cli-demo/coordinator/Cargo.lock b/taptrade-cli-demo/coordinator/Cargo.lock index 78454db..c350b4c 100644 --- a/taptrade-cli-demo/coordinator/Cargo.lock +++ b/taptrade-cli-demo/coordinator/Cargo.lock @@ -42,6 +42,12 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "async-trait" version = "0.1.80" @@ -144,6 +150,16 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes 0.14.0", +] + [[package]] name = "base64" version = "0.13.1" @@ -176,13 +192,13 @@ checksum = "2fc1fc1a92e0943bfbcd6eb7d32c1b2a79f2f1357eb1e2eee9d7f36d6d7ca44a" dependencies = [ "async-trait", "bdk-macros", - "bitcoin", + "bitcoin 0.30.2", "bitcoinconsensus", "electrum-client", "getrandom", "js-sys", "log", - "miniscript", + "miniscript 10.0.0", "rand", "serde", "serde_json", @@ -207,6 +223,12 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + [[package]] name = "bitcoin" version = "0.30.2" @@ -214,20 +236,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462" dependencies = [ "base64 0.13.1", - "bech32", + "bech32 0.9.1", "bitcoin-private", - "bitcoin_hashes", + "bitcoin_hashes 0.12.0", "hex_lit", - "secp256k1", + "secp256k1 0.27.0", "serde", ] +[[package]] +name = "bitcoin" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea507acc1cd80fc084ace38544bbcf7ced7c2aa65b653b102de0ce718df668f6" +dependencies = [ + "base58ck", + "bech32 0.11.0", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes 0.14.0", + "hex-conservative", + "hex_lit", + "secp256k1 0.29.0", +] + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" + +[[package]] +name = "bitcoin-io" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" + [[package]] name = "bitcoin-private" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals", +] + [[package]] name = "bitcoin_hashes" version = "0.12.0" @@ -238,6 +298,16 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitcoinconsensus" version = "0.19.0-3" @@ -315,9 +385,11 @@ dependencies = [ "anyhow", "axum", "bdk", + "bitcoin 0.32.2", "dotenv", "futures-util", "hex", + "miniscript 12.0.0", "rand", "reqwest", "serde", @@ -459,7 +531,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bc133f1c8d829d254f013f946653cbeb2b08674b960146361d1e9b67733ad19" dependencies = [ - "bitcoin", + "bitcoin 0.30.2", "bitcoin-private", "byteorder", "libc", @@ -750,6 +822,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex_lit" version = "0.1.1" @@ -1047,11 +1128,21 @@ version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1eb102b66b2127a872dbcc73095b7b47aeb9d92f7b03c2b2298253ffc82c7594" dependencies = [ - "bitcoin", + "bitcoin 0.30.2", "bitcoin-private", "serde", ] +[[package]] +name = "miniscript" +version = "12.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b59c67956fd276ceec0cf194fbf80754ef4d88a496d5cf5e4fdf33561466183d" +dependencies = [ + "bech32 0.11.0", + "bitcoin 0.32.2", +] + [[package]] name = "miniz_oxide" version = "0.7.4" @@ -1627,12 +1718,22 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.12.0", "rand", - "secp256k1-sys", + "secp256k1-sys 0.8.1", "serde", ] +[[package]] +name = "secp256k1" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" +dependencies = [ + "bitcoin_hashes 0.14.0", + "secp256k1-sys 0.10.0", +] + [[package]] name = "secp256k1-sys" version = "0.8.1" @@ -1642,6 +1743,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" +dependencies = [ + "cc", +] + [[package]] name = "security-framework" version = "2.11.0" diff --git a/taptrade-cli-demo/coordinator/Cargo.toml b/taptrade-cli-demo/coordinator/Cargo.toml index f9f4556..210a550 100644 --- a/taptrade-cli-demo/coordinator/Cargo.toml +++ b/taptrade-cli-demo/coordinator/Cargo.toml @@ -5,6 +5,8 @@ edition = "2021" [dependencies] anyhow = "1.0.86" +bitcoin = "0.32.2" +miniscript = "12.0.0" axum = { version = "0.7.5", features = ["tokio", "json"] } # "use-esplora-async", "async-interface", for async esplora diff --git a/taptrade-cli-demo/coordinator/src/taproot_contract/generate_descriptor.rs b/taptrade-cli-demo/coordinator/src/coordinator/create_taproot.rs similarity index 58% rename from taptrade-cli-demo/coordinator/src/taproot_contract/generate_descriptor.rs rename to taptrade-cli-demo/coordinator/src/coordinator/create_taproot.rs index d630ae1..bc2ce16 100644 --- a/taptrade-cli-demo/coordinator/src/taproot_contract/generate_descriptor.rs +++ b/taptrade-cli-demo/coordinator/src/coordinator/create_taproot.rs @@ -1,15 +1,70 @@ -use bitcoin::util::address::Address; -use bitcoin::util::psbt::{PartiallySignedTransaction, PSBTInput, PSBTOutput}; -use bitcoin::network::constants::Network; use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut}; use bitcoin::blockdata::script::Builder; use bitcoin::consensus::encode; use miniscript::{Miniscript, Descriptor, DescriptorPublicKey, policy::Concrete}; use miniscript::bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey, Message, Signature}; -use miniscript::bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey}; +// use miniscript::bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey}; use std::str::FromStr; +use bitcoin::psbt::PartiallySignedTransaction; +use bitcoin::util::taproot::{TaprootBuilder, TaprootSpendInfo}; +use bitcoin::util::schnorr::SchnorrSig; +use bitcoin::secp256k1::{Secp256k1, SecretKey}; +use bitcoin::Transaction; -async fn generate_taproot_PSBT() { + + +fn create_taproot_psbt(inputs: Vec, outputs: Vec) -> PartiallySignedTransaction { + let secp = Secp256k1::new(); + let mut psbt = PartiallySignedTransaction::new(); + + // Add inputs + for input in inputs { + psbt.inputs.push(input.to_psbt_input()); + } + + // Add outputs + for output in outputs { + psbt.outputs.push(output.to_psbt_output()); + } + + // Add Taproot data + // call create_script here, and add descriptor here + let taproot_info = TaprootSpendInfo::new(secp, root); + psbt.global.taproot_spend_info = Some(taproot_info); + + psbt +} + +impl UTXO { + fn to_psbt_input(&self) -> PsbtInput { + PsbtInput { + witness_utxo: Some(self.clone()), + ..Default::default() + } + } +} +impl Output { + fn to_psbt_output(&self) -> PsbtOutput { + PsbtOutput { + value: self.amount, + script: self.taproot_script.clone(), + ..Default::default() + } + } +} + +fn sign_psbt(psbt: &mut PartiallySignedTransaction, privkey: SecretKey) { + let secp = Secp256k1::new(); + + for (index, input) in psbt.inputs.iter_mut().enumerate() { + let sighash = psbt.sighash(index, secp); + let signature = SchnorrSig::sign(sighash, &privkey, secp); + input.taproot_key_sig = Some(signature); + } +} + + +async fn create_script(coordinator_pub_key, maker_pub_key,taker_pub_key ) { // Define the Miniscript policies let policy_a = format!("and_v(v:pk({}),and_v(v:pk({}),after(144)))", coordinator_pub_key, maker_pub_key); let policy_b = format!("and_v(v:pk({}),and_v(v:pk({}),pk({})))", maker_pub_key, taker_pub_key, coordinator_pub_key); @@ -49,57 +104,19 @@ async fn generate_taproot_PSBT() { println!("Taproot Address E: {}", address_e); println!("Taproot Address F: {}", address_f); - // Create a sample PSBT (Partially Signed Bitcoin Transaction) - let mut psbt = PartiallySignedTransaction { - global: Default::default(), - inputs: vec![], - outputs: vec![], - }; +} - // Add an example input (Replace with actual input) - psbt.inputs.push(PSBTInput { - non_witness_utxo: None, - witness_utxo: Some(TxOut { - value: 1000, - script_pubkey: address_a.script_pubkey(), - }), - ..Default::default() - }); - // Add the output addresses - psbt.outputs.push(PSBTOutput { - value: 1000, - script_pubkey: address_a.script_pubkey(), - ..Default::default() - }); +async fn procedure() { + let inputs = vec![/* ... UTXOs ... */ ]; + let outputs = vec![/* ... Outputs ... */]; - psbt.outputs.push(PSBTOutput { - value: 1000, - script_pubkey: address_b.script_pubkey(), - ..Default::default() - }); + let mut psbt = create_taproot_psbt(inputs, outputs); + let privkey = SecretKey::from_slice(&[/* private key bytes */]).unwrap(); - psbt.outputs.push(PSBTOutput { - value: 1000, - script_pubkey: address_c.script_pubkey(), - ..Default::default() - }); + sign_psbt(&mut psbt, privkey); - psbt.outputs.push(PSBTOutput { - value: 1000, - script_pubkey: address_d.script_pubkey(), - ..Default::default() - }); - - psbt.outputs.push(PSBTOutput { - value: 1000, - script_pubkey: address_e.script_pubkey(), - ..Default::default() - }); - - psbt.outputs.push(PSBTOutput { - value: 1000, - script_pubkey: address_f.script_pubkey(), - ..Default::default() - }); + // Finalize and broadcast the PSBT + let tx = psbt.finalize().unwrap(); + broadcast_transaction(tx); } \ No newline at end of file diff --git a/taptrade-cli-demo/coordinator/src/coordinator/mod.rs b/taptrade-cli-demo/coordinator/src/coordinator/mod.rs index 4d51275..3398fe2 100755 --- a/taptrade-cli-demo/coordinator/src/coordinator/mod.rs +++ b/taptrade-cli-demo/coordinator/src/coordinator/mod.rs @@ -1,3 +1,4 @@ pub mod monitoring; +pub mod create_taproot; use super::*; diff --git a/taptrade-cli-demo/trader/src/trading/utils.rs b/taptrade-cli-demo/trader/src/trading/utils.rs index eb483a3..ad92efc 100644 --- a/taptrade-cli-demo/trader/src/trading/utils.rs +++ b/taptrade-cli-demo/trader/src/trading/utils.rs @@ -16,8 +16,8 @@ impl ActiveOffer { &self, trader_config: &TraderSettings, ) -> Result<&Self> { - IsOfferReadyRequest::poll(trader_config, &self)?; - Ok(&self) + IsOfferReadyRequest::poll(trader_config, self)?; + Ok(self) } pub fn fiat_confirmation_cli_input(&self, trade_settings: &TraderSettings) -> Result {