-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP starting funding taproot tx impl
- Loading branch information
Showing
5 changed files
with
204 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
use bitcoin::blockdata::transaction::{OutPoint, Transaction}; | ||
use bitcoin::secp256k1::Secp256k1; | ||
use bitcoin::{Address, XOnlyPublicKey}; | ||
|
||
use crate::blockchain::Network; | ||
use crate::transaction::{Error, Fundable, Linkable}; | ||
|
||
use crate::bitcoin::taproot::Taproot; | ||
use crate::bitcoin::transaction::MetadataOutput; | ||
use crate::bitcoin::Bitcoin; | ||
use bitcoin::util::taproot::TaprootSpendInfo; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct Funding { | ||
untweaked_public_key: Option<XOnlyPublicKey>, | ||
network: Option<bitcoin::Network>, | ||
seen_tx: Option<Transaction>, | ||
} | ||
|
||
impl Linkable<MetadataOutput> for Funding { | ||
fn get_consumable_output(&self) -> Result<MetadataOutput, Error> { | ||
let secp = Secp256k1::new(); | ||
|
||
let address = Address::p2tr( | ||
&secp, | ||
self.untweaked_public_key.ok_or(Error::MissingPublicKey)?, | ||
None, | ||
self.network.ok_or(Error::MissingNetwork)?, | ||
); | ||
let script_pubkey = address.script_pubkey(); | ||
|
||
match &self.seen_tx { | ||
Some(t) => t | ||
.output | ||
.iter() | ||
.enumerate() | ||
.find(|(_, tx_out)| tx_out.script_pubkey == script_pubkey) | ||
.map(|(ix, tx_out)| MetadataOutput { | ||
out_point: OutPoint::new(t.txid(), ix as u32), | ||
tx_out: tx_out.clone(), | ||
script_pubkey: Some(script_pubkey), | ||
}) | ||
.ok_or(Error::MissingUTXO), | ||
// The transaction has not been see yet, cannot infer the UTXO | ||
None => Err(Error::MissingOnchainTransaction), | ||
} | ||
} | ||
} | ||
|
||
impl Fundable<Bitcoin<Taproot>, MetadataOutput> for Funding { | ||
fn initialize(pubkey: XOnlyPublicKey, network: Network) -> Result<Self, Error> { | ||
let network = match network { | ||
Network::Mainnet => bitcoin::Network::Bitcoin, | ||
Network::Testnet => bitcoin::Network::Testnet, | ||
Network::Local => bitcoin::Network::Regtest, | ||
}; | ||
Ok(Funding { | ||
untweaked_public_key: Some(pubkey), | ||
network: Some(network), | ||
seen_tx: None, | ||
}) | ||
} | ||
|
||
fn get_address(&self) -> Result<Address, Error> { | ||
let secp = Secp256k1::new(); | ||
let taproot_info = TaprootSpendInfo::new_key_spend( | ||
&secp, | ||
self.untweaked_public_key.ok_or(Error::MissingPublicKey)?, | ||
None, | ||
); | ||
|
||
Ok(Address::p2tr( | ||
&secp, | ||
taproot_info.internal_key(), | ||
taproot_info.merkle_root(), | ||
self.network.ok_or(Error::MissingNetwork)?, | ||
)) | ||
} | ||
|
||
fn update(&mut self, tx: Transaction) -> Result<(), Error> { | ||
self.seen_tx = Some(tx); | ||
Ok(()) | ||
} | ||
|
||
fn raw(tx: Transaction) -> Result<Self, Error> { | ||
Ok(Self { | ||
untweaked_public_key: None, | ||
network: None, | ||
seen_tx: Some(tx), | ||
}) | ||
} | ||
|
||
fn was_seen(&self) -> bool { | ||
self.seen_tx.is_some() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#![cfg(all(feature = "rpc", feature = "taproot"))] | ||
|
||
use farcaster_core::bitcoin::taproot::*; | ||
use farcaster_core::blockchain::*; | ||
use farcaster_core::transaction::*; | ||
|
||
use bitcoin::Amount; | ||
use bitcoincore_rpc::json::AddressType; | ||
use bitcoincore_rpc::RpcApi; | ||
|
||
#[macro_use] | ||
mod rpc; | ||
|
||
#[test] | ||
fn taproot_funding_tx() { | ||
let (_, xpubkey_a1, keypair_a1) = new_address!(taproot); | ||
//let (_, pubkey_a2, secret_a2) = new_address!(); | ||
|
||
let (_, xpubkey_b1, keypair_b1) = new_address!(taproot); | ||
//let (_, pubkey_b2, secret_b2) = new_address!(); | ||
|
||
let mut funding = FundingTx::initialize(xpubkey_a1, Network::Local).unwrap(); | ||
|
||
// | ||
// Create a wallet, mined funds, send to funding address with multiple UTXOs | ||
// | ||
if let Err(_) = rpc::CLIENT.create_wallet("test_wallet", Some(false), None, None, None) { | ||
let wallets = rpc::CLIENT.list_wallets().unwrap(); | ||
if wallets.len() == 0 { | ||
rpc::CLIENT.load_wallet("test_wallet").unwrap(); | ||
} | ||
if wallets.len() > 1 { | ||
panic!("More than one wallet loaded!"); | ||
} | ||
} | ||
|
||
let wallet_address = rpc::CLIENT | ||
.get_new_address(None, Some(AddressType::Bech32)) | ||
.unwrap(); | ||
rpc::CLIENT.generate_to_address(4, &wallet_address).unwrap(); | ||
mine!(100); | ||
let target_swap_amount = bitcoin::Amount::from_btc(8.0).unwrap(); | ||
|
||
let address = funding.get_address().unwrap(); | ||
println!("{:?}", address); | ||
let txid = rpc::CLIENT | ||
.send_to_address( | ||
&address, | ||
target_swap_amount, | ||
None, | ||
None, | ||
None, | ||
None, | ||
None, | ||
None, | ||
) | ||
.unwrap(); | ||
|
||
let funding_tx_seen: bitcoin::Transaction = rpc::CLIENT.get_by_id(&txid).unwrap(); | ||
// Minimum of fee of 122 sat | ||
let target_amount = Amount::from_sat(target_swap_amount.as_sat() - 122); | ||
funding.update(funding_tx_seen).unwrap(); | ||
} |