Faucet refactoring

This commit is contained in:
Sosthene 2024-05-22 10:18:02 +02:00
parent 083843a94a
commit de84c8a1bf

View File

@ -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<SilentPaymentWallet>,
shared_daemon: SharedDaemon,
) -> Result<Transaction> {
@ -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<SilentPaymentWallet>,
shared_daemon: SharedDaemon,
) -> Result<NewTxMessage> {
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::<FaucetMessage>(&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<u8>, daemon: Arc<Mutex<Daemon>>) -> Result<NewTxMessage> {
// 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)
{