Skip to content

Commit 1312a0b

Browse files
authored
add taproot wallet descriptors with AddressType enum (#674)
* add taproot wallet descriptors with `AddressType` enum fix doc clippy and cli defaults to P2WPKH address fix coin selection bug and use taproot change addresses * update dynamic split test * make `AddressType` required * change `swept_incoming_swapcoins` to a `HashSet`
1 parent ae9facf commit 1312a0b

26 files changed

+439
-147
lines changed

examples/taker_basic.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
3030
};
3131
use coinswap::{
3232
taker::{SwapParams, Taker},
33-
wallet::RPCConfig,
33+
wallet::{AddressType, RPCConfig},
3434
};
3535
println!("=== Coinswap Taker Basic Example ===");
3636
println!("NOTE: When prompted for encryption passphrase, press Enter for no encryption");
@@ -117,7 +117,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
117117
println!("\nFunding wallet with test coins...");
118118

119119
let wallet_mut = taker.get_wallet_mut();
120-
let funding_address = wallet_mut.get_next_external_address().unwrap();
120+
let funding_address = wallet_mut
121+
.get_next_external_address(AddressType::P2WPKH)
122+
.unwrap();
121123

122124
// Send coins from bitcoind to the taker wallet
123125
let fund_amount = Amount::from_btc(0.01).unwrap();
@@ -151,13 +153,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
151153

152154
// Generate a new receiving address
153155
let wallet_mut = taker.get_wallet_mut();
154-
let new_address = wallet_mut.get_next_external_address().unwrap();
156+
let new_address = wallet_mut
157+
.get_next_external_address(AddressType::P2WPKH)
158+
.unwrap();
155159
println!("\nGenerated new receiving address: {}", new_address);
156160

157161
// Demonstrate sending coins (send small amount to ourselves)
158162
println!("\nDemonstrating send functionality:");
159163
let send_amount = Amount::from_btc(0.001).unwrap();
160-
let internal_address = wallet_mut.get_next_internal_addresses(1).unwrap()[0].clone();
164+
let internal_address = wallet_mut
165+
.get_next_internal_addresses(1, AddressType::P2WPKH)
166+
.unwrap()[0]
167+
.clone();
161168

162169
println!(
163170
"Sending {} BTC to internal address: {}",

examples/wallet_basic.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use bitcoind::{
2323
};
2424
use coinswap::{
2525
utill::MIN_FEE_RATE,
26-
wallet::{Destination, RPCConfig, Wallet},
26+
wallet::{AddressType, Destination, RPCConfig, Wallet},
2727
};
2828

2929
fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -95,7 +95,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
9595
println!("Wallet synced with blockchain");
9696

9797
// Fund the wallet for demonstration
98-
let funding_address = wallet.get_next_external_address().unwrap();
98+
let funding_address = wallet
99+
.get_next_external_address(AddressType::P2WPKH)
100+
.unwrap();
99101
let fund_amount = Amount::from_btc(0.05).unwrap();
100102
let _txid = bitcoind
101103
.client
@@ -165,8 +167,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
165167

166168
// Generate addresses
167169
println!("\nAddress Generation:");
168-
let external_address = wallet.get_next_external_address().unwrap();
169-
let internal_addresses = wallet.get_next_internal_addresses(2).unwrap();
170+
let external_address = wallet
171+
.get_next_external_address(AddressType::P2WPKH)
172+
.unwrap();
173+
let internal_addresses = wallet
174+
.get_next_internal_addresses(2, AddressType::P2WPKH)
175+
.unwrap();
170176
println!(" External (receiving): {external_address}");
171177
println!(
172178
" Internal (change): {} {}",

src/bin/taker.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use clap::Parser;
44
use coinswap::{
55
taker::{error::TakerError, offers::MakerState, SwapParams, Taker, TaprootTaker},
66
utill::{parse_proxy_auth, setup_taker_logger, MIN_FEE_RATE, UTXO},
7-
wallet::{Destination, RPCConfig, Wallet},
7+
wallet::{AddressType, Destination, RPCConfig, Wallet},
88
};
99
use log::LevelFilter;
1010
use serde_json::{json, to_string_pretty};
@@ -284,7 +284,9 @@ fn main() -> Result<(), TakerError> {
284284
);
285285
}
286286
Commands::GetNewAddress => {
287-
let address = taker.get_wallet_mut().get_next_external_address()?;
287+
let address = taker
288+
.get_wallet_mut()
289+
.get_next_external_address(AddressType::P2WPKH)?;
288290
println!("{address:?}");
289291
}
290292
Commands::SendToAddress {
@@ -318,6 +320,7 @@ fn main() -> Result<(), TakerError> {
318320
let destination = Destination::Multi {
319321
outputs,
320322
op_return_data: None,
323+
change_address_type: AddressType::P2WPKH,
321324
};
322325

323326
let tx = taker.get_wallet_mut().spend_from_wallet(

src/maker/api2.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ use crate::{
2020
},
2121
},
2222
utill::{check_tor_status, get_maker_dir, HEART_BEAT_INTERVAL, MIN_FEE_RATE},
23-
wallet::{Destination, IncomingSwapCoinV2, OutgoingSwapCoinV2, RPCConfig, Wallet, WalletError},
23+
wallet::{
24+
AddressType, Destination, IncomingSwapCoinV2, OutgoingSwapCoinV2, RPCConfig, Wallet,
25+
WalletError,
26+
},
2427
watch_tower::{
2528
registry_storage::FileRegistry,
2629
rpc_backend::BitcoinRpc,
@@ -626,6 +629,7 @@ impl Maker {
626629
Destination::Multi {
627630
outputs: vec![(contract_address, outgoing_contract_amount)],
628631
op_return_data: None,
632+
change_address_type: AddressType::P2TR,
629633
},
630634
&selected_utxos,
631635
)?;
@@ -681,7 +685,7 @@ impl Maker {
681685
script_pubkey: self
682686
.wallet
683687
.read()?
684-
.get_next_internal_addresses(1)
688+
.get_next_internal_addresses(1, AddressType::P2TR)
685689
.map_err(MakerError::Wallet)?[0]
686690
.script_pubkey(),
687691
}],
@@ -923,11 +927,10 @@ impl Maker {
923927

924928
// Record the swept coin to track swap balance
925929
let output_scriptpubkey = spending_tx.output[0].script_pubkey.clone();
926-
// [TODO] Look into the key value pair later, it shouldn't be both sriptpubkey
927930
wallet
928931
.store
929932
.swept_incoming_swapcoins
930-
.insert(output_scriptpubkey.clone(), output_scriptpubkey);
933+
.insert(output_scriptpubkey);
931934

932935
wallet.remove_incoming_swapcoin_v2(&incoming_txid);
933936
log::info!(
@@ -976,7 +979,7 @@ impl Maker {
976979
let destination_address = {
977980
let wallet = self.wallet.read()?;
978981
wallet
979-
.get_next_internal_addresses(1)
982+
.get_next_internal_addresses(1, AddressType::P2TR)
980983
.map_err(MakerError::Wallet)?[0]
981984
.clone()
982985
};

src/maker/rpc/server.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::messages::RpcMsgReq;
1515
use crate::{
1616
maker::{config::MakerConfig, error::MakerError, rpc::messages::RpcMsgResp},
1717
utill::{get_tor_hostname, read_message, send_message, HEART_BEAT_INTERVAL, UTXO},
18-
wallet::{Destination, Wallet},
18+
wallet::{AddressType, Destination, Wallet},
1919
};
2020
use std::{path::Path, str::FromStr, sync::RwLock};
2121

@@ -78,7 +78,10 @@ fn handle_request<M: MakerRpc>(maker: &Arc<M>, socket: &mut TcpStream) -> Result
7878
RpcMsgResp::TotalBalanceResp(balances)
7979
}
8080
RpcMsgReq::NewAddress => {
81-
let new_address = maker.wallet().write()?.get_next_external_address()?;
81+
let new_address = maker
82+
.wallet()
83+
.write()?
84+
.get_next_external_address(AddressType::P2WPKH)?;
8285
RpcMsgResp::NewAddressResp(new_address.to_string())
8386
}
8487
RpcMsgReq::SendToAddress {
@@ -94,6 +97,7 @@ fn handle_request<M: MakerRpc>(maker: &Arc<M>, socket: &mut TcpStream) -> Result
9497
let destination = Destination::Multi {
9598
outputs,
9699
op_return_data: None,
100+
change_address_type: AddressType::P2WPKH,
97101
};
98102

99103
let coins_to_send = maker.wallet().read()?.coin_select(amount, feerate, None)?;

src/maker/server.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use crate::{
4343
},
4444
protocol::messages::TakerToMakerMessage,
4545
utill::{read_message, send_message, HEART_BEAT_INTERVAL, MIN_FEE_RATE},
46-
wallet::WalletError,
46+
wallet::{AddressType, WalletError},
4747
};
4848

4949
use crate::maker::error::MakerError;
@@ -84,7 +84,10 @@ fn network_bootstrap(maker: Arc<Maker>) -> Result<String, MakerError> {
8484
/// 1. Redeems all expired fidelity bonds in the maker's wallet, if any are found.
8585
/// 2. Creates a new fidelity bond if no valid bonds remain after redemption.
8686
fn manage_fidelity_bonds(maker: &Maker, maker_addr: &str) -> Result<(), MakerError> {
87-
maker.wallet.write()?.redeem_expired_fidelity_bonds()?;
87+
maker
88+
.wallet
89+
.write()?
90+
.redeem_expired_fidelity_bonds(AddressType::P2WPKH)?;
8891
let fidelity = setup_fidelity_bond(maker, maker_addr)?;
8992
broadcast_bond_on_nostr(fidelity)?;
9093
Ok(())
@@ -256,6 +259,7 @@ fn setup_fidelity_bond(maker: &Maker, maker_address: &str) -> Result<FidelityPro
256259
locktime,
257260
Some(maker_address),
258261
MIN_FEE_RATE,
262+
AddressType::P2WPKH,
259263
);
260264

261265
match fidelity_result {
@@ -269,7 +273,10 @@ fn setup_fidelity_bond(maker: &Maker, maker_address: &str) -> Result<FidelityPro
269273
{
270274
log::warn!("Insufficient fund to create fidelity bond.");
271275
let amount = required - available;
272-
let addr = maker.get_wallet().write()?.get_next_external_address()?;
276+
let addr = maker
277+
.get_wallet()
278+
.write()?
279+
.get_next_external_address(AddressType::P2WPKH)?;
273280

274281
log::info!("Send at least {:.8} BTC to {:?} | If you send extra, that will be added to your wallet balance", Amount::from_sat(amount).to_btc(), addr);
275282

@@ -316,7 +323,10 @@ fn setup_fidelity_bond(maker: &Maker, maker_address: &str) -> Result<FidelityPro
316323
fn check_swap_liquidity(maker: &Maker) -> Result<(), MakerError> {
317324
let sleep_incremental = 10;
318325
let mut sleep_duration = 0;
319-
let addr = maker.get_wallet().write()?.get_next_external_address()?;
326+
let addr = maker
327+
.get_wallet()
328+
.write()?
329+
.get_next_external_address(AddressType::P2WPKH)?;
320330
while !maker.shutdown.load(Relaxed) {
321331
maker.get_wallet().write()?.sync_and_save()?;
322332
let offer_max_size = maker.get_wallet().read()?.store.offer_maxsize;

src/maker/server2.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use crate::{
3636
get_tor_hostname, read_message, send_message, COINSWAP_KIND, HEART_BEAT_INTERVAL,
3737
MIN_FEE_RATE, NOSTR_RELAYS,
3838
},
39-
wallet::WalletError,
39+
wallet::{AddressType, WalletError},
4040
};
4141

4242
use crate::maker::error::MakerError;
@@ -73,7 +73,10 @@ fn network_bootstrap_taproot(maker: Arc<Maker>) -> Result<String, MakerError> {
7373
/// Setup's maker fidelity
7474
fn manage_fidelity_bonds_taproot(maker: &Maker, maker_addr: &str) -> Result<(), MakerError> {
7575
// Redeem expired fidelity bonds first
76-
maker.wallet().write()?.redeem_expired_fidelity_bonds()?;
76+
maker
77+
.wallet()
78+
.write()?
79+
.redeem_expired_fidelity_bonds(AddressType::P2TR)?;
7780

7881
// Create or get existing fidelity proof for taproot maker
7982
let fidelity_proof = setup_fidelity_bond_taproot(maker, maker_addr)?;
@@ -272,6 +275,7 @@ fn setup_fidelity_bond_taproot(
272275
locktime,
273276
Some(maker_address),
274277
MIN_FEE_RATE,
278+
AddressType::P2TR,
275279
);
276280

277281
match fidelity_result {
@@ -288,7 +292,10 @@ fn setup_fidelity_bond_taproot(
288292
maker.config.network_port
289293
);
290294
let amount = required - available;
291-
let addr = maker.wallet().write()?.get_next_external_address()?;
295+
let addr = maker
296+
.wallet()
297+
.write()?
298+
.get_next_external_address(AddressType::P2TR)?;
292299

293300
log::info!("[{}] Send at least {:.8} BTC to {:?} | If you send extra, that will be added to your wallet balance", maker.config.network_port, Amount::from_sat(amount).to_btc(), addr);
294301

src/taker/api2.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::{
2424
utill::{check_tor_status, get_taker_dir, read_message, send_message},
2525
wallet::{
2626
ffi::{MakerFeeInfo, SwapReport},
27-
IncomingSwapCoinV2, OutgoingSwapCoinV2, RPCConfig, Wallet, WalletError,
27+
AddressType, IncomingSwapCoinV2, OutgoingSwapCoinV2, RPCConfig, Wallet, WalletError,
2828
},
2929
watch_tower::{
3030
registry_storage::FileRegistry,
@@ -997,6 +997,7 @@ impl Taker {
997997
self.ongoing_swap_state.swap_params.send_amount,
998998
)],
999999
op_return_data: None,
1000+
change_address_type: AddressType::P2TR,
10001001
},
10011002
&selected_utxos,
10021003
)?
@@ -1369,7 +1370,7 @@ impl Taker {
13691370

13701371
let destination_address = self
13711372
.wallet
1372-
.get_next_internal_addresses(1)
1373+
.get_next_internal_addresses(1, AddressType::P2TR)
13731374
.map_err(TakerError::Wallet)?
13741375
.into_iter()
13751376
.next()
@@ -1505,7 +1506,7 @@ impl Taker {
15051506
self.wallet
15061507
.store
15071508
.swept_incoming_swapcoins
1508-
.insert(output_scriptpubkey.clone(), output_scriptpubkey);
1509+
.insert(output_scriptpubkey);
15091510
log::info!(
15101511
"Recorded swept incoming swapcoin V2: {}",
15111512
incoming_contract_txid

0 commit comments

Comments
 (0)