Skip to content

Commit

Permalink
Add a mandatory --change-address parameter to buy-xmr
Browse files Browse the repository at this point in the history
Fixes #513.
  • Loading branch information
thomaseizinger committed Jul 6, 2021
1 parent 92829eb commit 28d94fe
Show file tree
Hide file tree
Showing 13 changed files with 207 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Configuration setting for the websocket URL that the ASB connects to in order to receive price ticker updates.
Can be configured manually by editing the config.toml file directly.
It is expected that the server behind the url follows the same protocol as the [Kraken websocket api](https://docs.kraken.com/websockets/).
- A mandatory `--change-address` parameter to the CLI's `buy-xmr` command.
The provided address is used to transfer Bitcoin in case of a refund and in case the user transfers more than the specified amount into the swap.
For more information see [#513](https://github.com/comit-network/xmr-btc-swap/issues/513).

### Fixed

Expand Down
73 changes: 72 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions swap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ rust_decimal_macros = "1"
serde = { version = "1", features = [ "derive" ] }
serde_cbor = "0.11"
serde_json = "1"
serde_with = { version = "1", features = [ "macros" ] }
sha2 = "0.9"
sigma_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "ed25519", "serde" ] }
sled = "0.34"
Expand Down
4 changes: 3 additions & 1 deletion swap/src/bin/asb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ async fn main() -> Result<()> {
}
};

let psbt = bitcoin_wallet.send_to_address(address, amount).await?;
let psbt = bitcoin_wallet
.send_to_address(address, amount, None)
.await?;
let signed_tx = bitcoin_wallet.sign_and_finalize(psbt).await?;

bitcoin_wallet.broadcast(signed_tx, "withdraw").await?;
Expand Down
2 changes: 2 additions & 0 deletions swap/src/bin/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async fn main() -> Result<()> {
seller,
bitcoin_electrum_rpc_url,
bitcoin_target_block,
bitcoin_change_address,
monero_receive_address,
monero_daemon_address,
tor_socks5_port,
Expand Down Expand Up @@ -130,6 +131,7 @@ async fn main() -> Result<()> {
env_config,
event_loop_handle,
monero_receive_address,
bitcoin_change_address,
amount,
);

Expand Down
11 changes: 9 additions & 2 deletions swap/src/bitcoin/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl TxLock {
amount: Amount,
A: PublicKey,
B: PublicKey,
change: bitcoin::Address,
) -> Result<Self>
where
C: EstimateFeeRate,
Expand All @@ -34,7 +35,9 @@ impl TxLock {
.address(wallet.get_network())
.expect("can derive address from descriptor");

let psbt = wallet.send_to_address(address, amount).await?;
let psbt = wallet
.send_to_address(address, amount, Some(change))
.await?;

Ok(Self {
inner: psbt,
Expand Down Expand Up @@ -251,7 +254,11 @@ mod tests {
wallet: &Wallet<(), bdk::database::MemoryDatabase, StaticFeeRate>,
amount: Amount,
) -> PartiallySignedTransaction {
TxLock::new(&wallet, amount, A, B).await.unwrap().into()
let change = wallet.new_address().await.unwrap();
TxLock::new(&wallet, amount, A, B, change)
.await
.unwrap()
.into()
}

fn alice_and_bob() -> (PublicKey, PublicKey) {
Expand Down
45 changes: 44 additions & 1 deletion swap/src/bitcoin/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,18 @@ where
&self,
address: Address,
amount: Amount,
change_override: Option<Address>,
) -> Result<PartiallySignedTransaction> {
if self.network != address.network {
bail!("Cannot build PSBT because network of given address is {} but wallet is on network {}", address.network, self.network);
}

if let Some(change) = change_override.as_ref() {
if self.network != change.network {
bail!("Cannot build PSBT because network of given address is {} but wallet is on network {}", change.network, self.network);
}
}

let wallet = self.wallet.lock().await;
let client = self.client.lock().await;
let fee_rate = client.estimate_feerate(self.target_block)?;
Expand All @@ -340,6 +347,15 @@ where
_ => bail!("Unexpected transaction layout"),
}

if let ([_, change], [_, psbt_output], Some(change_override)) = (
&mut psbt.global.unsigned_tx.output.as_mut_slice(),
&mut psbt.outputs.as_mut_slice(),
change_override,
) {
change.script_pubkey = change_override.script_pubkey();
psbt_output.bip32_derivation.clear();
}

Ok(psbt)
}

Expand Down Expand Up @@ -1059,7 +1075,8 @@ mod tests {
// if the change output is below dust it will be dropped by the BDK
for amount in above_dust..(balance - (above_dust - 1)) {
let (A, B) = (PublicKey::random(), PublicKey::random());
let txlock = TxLock::new(&wallet, bitcoin::Amount::from_sat(amount), A, B)
let change = wallet.new_address().await.unwrap();
let txlock = TxLock::new(&wallet, bitcoin::Amount::from_sat(amount), A, B, change)
.await
.unwrap();
let txlock_output = txlock.script_pubkey();
Expand All @@ -1074,4 +1091,30 @@ mod tests {
);
}
}

#[tokio::test]
async fn can_override_change_address() {
let wallet = Wallet::new_funded_default_fees(50_000);
let custom_change = "bcrt1q08pfqpsyrt7acllzyjm8q5qsz5capvyahm49rw"
.parse::<Address>()
.unwrap();

let psbt = wallet
.send_to_address(
wallet.new_address().await.unwrap(),
Amount::from_sat(10_000),
Some(custom_change.clone()),
)
.await
.unwrap();
let transaction = wallet.sign_and_finalize(psbt).await.unwrap();

match transaction.output.as_slice() {
[first, change] => {
assert_eq!(first.value, 10_000);
assert_eq!(change.script_pubkey, custom_change.script_pubkey());
}
_ => panic!("expected exactly two outputs"),
}
}
}
Loading

0 comments on commit 28d94fe

Please sign in to comment.