Faucet refactoring
This commit is contained in:
parent
083843a94a
commit
de84c8a1bf
98
src/main.rs
98
src/main.rs
@ -1,5 +1,4 @@
|
|||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
env,
|
env,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
@ -11,17 +10,12 @@ use std::{
|
|||||||
use bitcoincore_rpc::json::{self as bitcoin_json};
|
use bitcoincore_rpc::json::{self as bitcoin_json};
|
||||||
use futures_util::{future, pin_mut, stream::TryStreamExt, FutureExt, StreamExt};
|
use futures_util::{future, pin_mut, stream::TryStreamExt, FutureExt, StreamExt};
|
||||||
use log::{debug, error};
|
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::{
|
use sp_client::bitcoin::{
|
||||||
absolute::LockTime,
|
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
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
use sp_client::{
|
use sp_client::{
|
||||||
bitcoin::secp256k1::{
|
bitcoin::secp256k1::{
|
||||||
@ -99,12 +93,12 @@ fn broadcast_message(
|
|||||||
payload: String,
|
payload: String,
|
||||||
broadcast: BroadcastType,
|
broadcast: BroadcastType,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// log::debug!("Broadcasting message: {}", msg);
|
|
||||||
let ank_msg = AnkNetworkMsg {
|
let ank_msg = AnkNetworkMsg {
|
||||||
flag,
|
flag,
|
||||||
content: payload,
|
content: payload,
|
||||||
};
|
};
|
||||||
let msg = Message::Text(serde_json::to_string(&ank_msg)?);
|
let msg = Message::Text(serde_json::to_string(&ank_msg)?);
|
||||||
|
log::debug!("Broadcasting message: {}", msg);
|
||||||
match broadcast {
|
match broadcast {
|
||||||
BroadcastType::Sender(addr) => {
|
BroadcastType::Sender(addr) => {
|
||||||
peers
|
peers
|
||||||
@ -114,7 +108,7 @@ fn broadcast_message(
|
|||||||
.find(|(peer_addr, _)| peer_addr == &&addr)
|
.find(|(peer_addr, _)| peer_addr == &&addr)
|
||||||
.ok_or(Error::msg("Failed to find the sender in the peer_map"))?
|
.ok_or(Error::msg("Failed to find the sender in the peer_map"))?
|
||||||
.1
|
.1
|
||||||
.send(msg.clone())?;
|
.send(msg)?;
|
||||||
}
|
}
|
||||||
BroadcastType::ExcludeSender(addr) => {
|
BroadcastType::ExcludeSender(addr) => {
|
||||||
peers
|
peers
|
||||||
@ -173,6 +167,7 @@ fn spend_from_core(
|
|||||||
|
|
||||||
fn faucet_send(
|
fn faucet_send(
|
||||||
sp_address: SilentPaymentAddress,
|
sp_address: SilentPaymentAddress,
|
||||||
|
commitment: &str,
|
||||||
sp_wallet: Arc<SilentPaymentWallet>,
|
sp_wallet: Arc<SilentPaymentWallet>,
|
||||||
shared_daemon: SharedDaemon,
|
shared_daemon: SharedDaemon,
|
||||||
) -> Result<Transaction> {
|
) -> Result<Transaction> {
|
||||||
@ -215,26 +210,13 @@ fn faucet_send(
|
|||||||
|
|
||||||
let wallet = sp_wallet.get_wallet()?;
|
let wallet = sp_wallet.get_wallet()?;
|
||||||
|
|
||||||
let mut new_psbt =
|
let signed_psbt = create_transaction_for_address_with_shared_secret(
|
||||||
wallet
|
recipient, &wallet, Some(commitment), fee_estimate,
|
||||||
.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)?;
|
|
||||||
|
|
||||||
final_tx = signed.extract_tx()?;
|
let psbt = Psbt::from_str(&signed_psbt)?;
|
||||||
|
|
||||||
|
final_tx = psbt.extract_tx()?;
|
||||||
} else {
|
} else {
|
||||||
// let's try to spend directly from the mining address
|
// let's try to spend directly from the mining address
|
||||||
let secp = Secp256k1::signing_only();
|
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
|
// create a new transaction that spends the newly created UTXO to the sp_address
|
||||||
let mut faucet_tx = Transaction {
|
let mut faucet_tx = Transaction {
|
||||||
input: vec![TxIn {
|
input: vec![TxIn {
|
||||||
@ -290,6 +273,10 @@ fn faucet_send(
|
|||||||
let ext_spk = ScriptBuf::new_p2tr_tweaked(ext_output_key.dangerous_assume_tweaked());
|
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 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
|
// Take some margin to pay for the fees
|
||||||
if core_tx.output[0].value < FAUCET_AMT * 4 {
|
if core_tx.output[0].value < FAUCET_AMT * 4 {
|
||||||
return Err(Error::msg("Not enough funds"));
|
return Err(Error::msg("Not enough funds"));
|
||||||
@ -305,6 +292,10 @@ fn faucet_send(
|
|||||||
value: change_amt,
|
value: change_amt,
|
||||||
script_pubkey: change_spk,
|
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
|
// dummy signature only used for fee estimation
|
||||||
faucet_tx.input[0].witness.push([1; 64].to_vec());
|
faucet_tx.input[0].witness.push([1; 64].to_vec());
|
||||||
@ -344,7 +335,8 @@ fn faucet_send(
|
|||||||
if first_tx.is_some() {
|
if first_tx.is_some() {
|
||||||
daemon.broadcast(&first_tx.unwrap())?;
|
daemon.broadcast(&first_tx.unwrap())?;
|
||||||
}
|
}
|
||||||
daemon.broadcast(&final_tx)?;
|
let txid = daemon.broadcast(&final_tx)?;
|
||||||
|
debug!("Sent tx {}", txid);
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::msg("Failed to lock daemon"));
|
return Err(Error::msg("Failed to lock daemon"));
|
||||||
}
|
}
|
||||||
@ -353,14 +345,19 @@ fn faucet_send(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_faucet_request(
|
fn handle_faucet_request(
|
||||||
msg: &str,
|
msg: &FaucetMessage,
|
||||||
sp_wallet: Arc<SilentPaymentWallet>,
|
sp_wallet: Arc<SilentPaymentWallet>,
|
||||||
shared_daemon: SharedDaemon,
|
shared_daemon: SharedDaemon,
|
||||||
) -> Result<NewTxMessage> {
|
) -> 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);
|
debug!("Sending bootstrap coins to {}", sp_address);
|
||||||
// send bootstrap coins to this 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
|
// get the tweak
|
||||||
let partial_tweak = compute_partial_tweak_to_transaction(&tx, shared_daemon.clone())?;
|
let partial_tweak = compute_partial_tweak_to_transaction(&tx, shared_daemon.clone())?;
|
||||||
@ -442,24 +439,16 @@ async fn handle_connection(
|
|||||||
if let Ok(content) = serde_json::from_str::<FaucetMessage>(&ank_msg.content)
|
if let Ok(content) = serde_json::from_str::<FaucetMessage>(&ank_msg.content)
|
||||||
{
|
{
|
||||||
match handle_faucet_request(
|
match handle_faucet_request(
|
||||||
&content.sp_address,
|
&content,
|
||||||
sp_wallet.clone(),
|
sp_wallet.clone(),
|
||||||
shared_daemon.clone(),
|
shared_daemon.clone(),
|
||||||
) {
|
) {
|
||||||
Ok(new_tx_msg) => {
|
Ok(new_tx_msg) => {
|
||||||
if let Err(e) = broadcast_message(
|
debug!(
|
||||||
peers.clone(),
|
"Obtained new_tx_msg: {}",
|
||||||
AnkFlag::NewTx,
|
serde_json::to_string(&new_tx_msg).unwrap()
|
||||||
serde_json::to_string(&new_tx_msg)
|
|
||||||
.expect("This should not fail"),
|
|
||||||
BroadcastType::Sender(addr),
|
|
||||||
) {
|
|
||||||
log::error!(
|
|
||||||
"Failed to broadcast message: {}",
|
|
||||||
e.to_string()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to send faucet tx: {}", e);
|
log::error!("Failed to send faucet tx: {}", e);
|
||||||
if let Err(e) = broadcast_message(
|
if let Err(e) = broadcast_message(
|
||||||
@ -502,13 +491,12 @@ async fn handle_connection(
|
|||||||
if let Err(e) = broadcast_message(
|
if let Err(e) = broadcast_message(
|
||||||
peers.clone(),
|
peers.clone(),
|
||||||
AnkFlag::Unknown,
|
AnkFlag::Unknown,
|
||||||
serde_json::to_string(&ank_msg.content)
|
serde_json::to_string(&ank_msg.content).expect("This should not fail"),
|
||||||
.expect("This should not fail"),
|
|
||||||
BroadcastType::ExcludeSender(addr),
|
BroadcastType::ExcludeSender(addr),
|
||||||
) {
|
) {
|
||||||
log::error!("Failed to send message with error: {}", e);
|
log::error!("Failed to send message with error: {}", e);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
AnkFlag::Prd => unimplemented!(),
|
AnkFlag::Prd => unimplemented!(),
|
||||||
},
|
},
|
||||||
Err(_) => log::error!("Failed to parse network message"),
|
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> {
|
fn create_new_tx_message(transaction: Vec<u8>, daemon: Arc<Mutex<Daemon>>) -> Result<NewTxMessage> {
|
||||||
|
// debug!("Creating tx message");
|
||||||
let tx: Transaction = deserialize(&transaction)?;
|
let tx: Transaction = deserialize(&transaction)?;
|
||||||
|
|
||||||
if tx.is_coinbase() {
|
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))
|
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) {
|
match std::str::from_utf8(&topic) {
|
||||||
Ok("rawtx") => match create_new_tx_message(data.to_vec(), shared_daemon.clone()) {
|
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) => {
|
Err(e) => {
|
||||||
error!("{}", e);
|
error!("{}", e);
|
||||||
continue;
|
continue;
|
||||||
@ -628,6 +621,7 @@ async fn handle_zmq(peers: PeerMap, shared_daemon: SharedDaemon) {
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug!("Broadcasting message {}", payload);
|
||||||
if let Err(e) =
|
if let Err(e) =
|
||||||
broadcast_message(peers.clone(), AnkFlag::NewTx, payload, BroadcastType::ToAll)
|
broadcast_message(peers.clone(), AnkFlag::NewTx, payload, BroadcastType::ToAll)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user