diff --git a/src/main.rs b/src/main.rs index 42dfcd0..160a5fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ use std::{ - any::Any, collections::HashMap, env, fmt::Debug, @@ -11,17 +10,12 @@ use std::{ use bitcoincore_rpc::json::{self as bitcoin_json}; use futures_util::{future, pin_mut, stream::TryStreamExt, FutureExt, StreamExt}; use log::{debug, error}; -use sdk_common::network::{AnkFlag, AnkNetworkMsg, FaucetMessage, NewTxMessage}; +use sdk_common::{ + network::{AnkFlag, AnkNetworkMsg, FaucetMessage, NewTxMessage}, + silentpayments::create_transaction_for_address_with_shared_secret, +}; use sp_client::bitcoin::{ - absolute::LockTime, - consensus::{deserialize, serialize}, - hex::{DisplayHex, FromHex}, - key::TapTweak, - sighash::{Prevouts, SighashCache}, - taproot::Signature, - transaction::Version, - Amount, OutPoint, Psbt, ScriptBuf, TapSighashType, Transaction, TxIn, TxOut, Witness, - XOnlyPublicKey, + absolute::LockTime, consensus::{deserialize, serialize}, hex::{DisplayHex, FromHex}, key::TapTweak, script::PushBytesBuf, sighash::{Prevouts, SighashCache}, taproot::Signature, transaction::Version, Amount, OutPoint, Psbt, ScriptBuf, TapSighashType, Transaction, TxIn, TxOut, Witness, XOnlyPublicKey }; use sp_client::{ bitcoin::secp256k1::{ @@ -99,12 +93,12 @@ fn broadcast_message( payload: String, broadcast: BroadcastType, ) -> Result<()> { - // log::debug!("Broadcasting message: {}", msg); let ank_msg = AnkNetworkMsg { flag, content: payload, }; let msg = Message::Text(serde_json::to_string(&ank_msg)?); + log::debug!("Broadcasting message: {}", msg); match broadcast { BroadcastType::Sender(addr) => { peers @@ -114,7 +108,7 @@ fn broadcast_message( .find(|(peer_addr, _)| peer_addr == &&addr) .ok_or(Error::msg("Failed to find the sender in the peer_map"))? .1 - .send(msg.clone())?; + .send(msg)?; } BroadcastType::ExcludeSender(addr) => { peers @@ -173,6 +167,7 @@ fn spend_from_core( fn faucet_send( sp_address: SilentPaymentAddress, + commitment: &str, sp_wallet: Arc, shared_daemon: SharedDaemon, ) -> Result { @@ -215,26 +210,13 @@ fn faucet_send( let wallet = sp_wallet.get_wallet()?; - let mut new_psbt = - wallet - .get_client() - .create_new_psbt(inputs.clone(), vec![recipient], None)?; - log::debug!("Created psbt: {}", new_psbt); - SpClient::set_fees(&mut new_psbt, fee_estimate, sp_address.into())?; - let partial_secret = wallet - .get_client() - .get_partial_secret_from_psbt(&new_psbt)?; - wallet - .get_client() - .fill_sp_outputs(&mut new_psbt, partial_secret)?; - log::debug!("Definitive psbt: {}", new_psbt); - let mut aux_rand = [0u8; 32]; - thread_rng().fill(&mut aux_rand); - let mut signed = wallet.get_client().sign_psbt(new_psbt, &aux_rand)?; - log::debug!("signed psbt: {}", signed); - SpClient::finalize_psbt(&mut signed)?; + let signed_psbt = create_transaction_for_address_with_shared_secret( + recipient, &wallet, Some(commitment), fee_estimate, + )?; - final_tx = signed.extract_tx()?; + let psbt = Psbt::from_str(&signed_psbt)?; + + final_tx = psbt.extract_tx()?; } else { // let's try to spend directly from the mining address let secp = Secp256k1::signing_only(); @@ -252,6 +234,7 @@ fn faucet_send( ) ); + // This is ugly and can be streamlined // create a new transaction that spends the newly created UTXO to the sp_address let mut faucet_tx = Transaction { input: vec![TxIn { @@ -289,6 +272,10 @@ fn faucet_send( let ext_spk = ScriptBuf::new_p2tr_tweaked(ext_output_key.dangerous_assume_tweaked()); let change_spk = ScriptBuf::new_p2tr_tweaked(change_output_key.dangerous_assume_tweaked()); + + let mut op_return = PushBytesBuf::new(); + op_return.extend_from_slice(&Vec::from_hex(commitment)?)?; + let data_spk = ScriptBuf::new_op_return(op_return); // Take some margin to pay for the fees if core_tx.output[0].value < FAUCET_AMT * 4 { @@ -305,6 +292,10 @@ fn faucet_send( value: change_amt, script_pubkey: change_spk, }); + faucet_tx.output.push(TxOut { + value: Amount::from_sat(0), + script_pubkey: data_spk, + }); // dummy signature only used for fee estimation faucet_tx.input[0].witness.push([1; 64].to_vec()); @@ -344,7 +335,8 @@ fn faucet_send( if first_tx.is_some() { daemon.broadcast(&first_tx.unwrap())?; } - daemon.broadcast(&final_tx)?; + let txid = daemon.broadcast(&final_tx)?; + debug!("Sent tx {}", txid); } else { return Err(Error::msg("Failed to lock daemon")); } @@ -353,14 +345,19 @@ fn faucet_send( } fn handle_faucet_request( - msg: &str, + msg: &FaucetMessage, sp_wallet: Arc, shared_daemon: SharedDaemon, ) -> Result { - let sp_address = SilentPaymentAddress::try_from(msg)?; + let sp_address = SilentPaymentAddress::try_from(msg.sp_address.as_str())?; debug!("Sending bootstrap coins to {}", sp_address); // send bootstrap coins to this sp_address - let tx = faucet_send(sp_address, sp_wallet.clone(), shared_daemon.clone())?; + let tx = faucet_send( + sp_address, + &msg.commitment, + sp_wallet.clone(), + shared_daemon.clone(), + )?; // get the tweak let partial_tweak = compute_partial_tweak_to_transaction(&tx, shared_daemon.clone())?; @@ -442,23 +439,15 @@ async fn handle_connection( if let Ok(content) = serde_json::from_str::(&ank_msg.content) { match handle_faucet_request( - &content.sp_address, + &content, sp_wallet.clone(), shared_daemon.clone(), ) { Ok(new_tx_msg) => { - if let Err(e) = broadcast_message( - peers.clone(), - AnkFlag::NewTx, - serde_json::to_string(&new_tx_msg) - .expect("This should not fail"), - BroadcastType::Sender(addr), - ) { - log::error!( - "Failed to broadcast message: {}", - e.to_string() - ); - } + debug!( + "Obtained new_tx_msg: {}", + serde_json::to_string(&new_tx_msg).unwrap() + ); } Err(e) => { log::error!("Failed to send faucet tx: {}", e); @@ -502,13 +491,12 @@ async fn handle_connection( if let Err(e) = broadcast_message( peers.clone(), AnkFlag::Unknown, - serde_json::to_string(&ank_msg.content) - .expect("This should not fail"), + serde_json::to_string(&ank_msg.content).expect("This should not fail"), BroadcastType::ExcludeSender(addr), ) { log::error!("Failed to send message with error: {}", e); } - }, + } AnkFlag::Prd => unimplemented!(), }, Err(_) => log::error!("Failed to parse network message"), @@ -578,6 +566,7 @@ fn compute_partial_tweak_to_transaction( } fn create_new_tx_message(transaction: Vec, daemon: Arc>) -> Result { + // debug!("Creating tx message"); let tx: Transaction = deserialize(&transaction)?; if tx.is_coinbase() { @@ -609,9 +598,13 @@ async fn handle_zmq(peers: PeerMap, shared_daemon: SharedDaemon) { let payload: String = if let (Some(topic), Some(data)) = (core_msg.get(0), core_msg.get(1)) { + // debug!("topic: {}", std::str::from_utf8(&topic).unwrap()); match std::str::from_utf8(&topic) { Ok("rawtx") => match create_new_tx_message(data.to_vec(), shared_daemon.clone()) { - Ok(m) => serde_json::to_string(&m).expect("This shouldn't fail"), + Ok(m) => { + debug!("Created message"); + serde_json::to_string(&m).expect("This shouldn't fail") + } Err(e) => { error!("{}", e); continue; @@ -628,6 +621,7 @@ async fn handle_zmq(peers: PeerMap, shared_daemon: SharedDaemon) { continue; }; + debug!("Broadcasting message {}", payload); if let Err(e) = broadcast_message(peers.clone(), AnkFlag::NewTx, payload, BroadcastType::ToAll) {