implement manual-refund -> export-monero-lock-wallet command for asb (#619)

This commit is contained in:
Raphael 2025-10-12 22:40:49 +02:00 committed by GitHub
parent 7d54a53fa5
commit 31e286f279
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 74 additions and 0 deletions

View file

@ -161,6 +161,16 @@ where
env_config: env_config(testnet), env_config: env_config(testnet),
cmd: Command::Punish { swap_id }, cmd: Command::Punish { swap_id },
}, },
RawCommand::ManualRecovery(ManualRecovery::ExportMoneroLockWallet { swap_id }) => {
Arguments {
testnet,
json,
trace,
config_path: config_path(config, testnet)?,
env_config: env_config(testnet),
cmd: Command::ExportMoneroLockWallet { swap_id },
}
}
RawCommand::ManualRecovery(ManualRecovery::SafelyAbort { swap_id }) => Arguments { RawCommand::ManualRecovery(ManualRecovery::SafelyAbort { swap_id }) => Arguments {
testnet, testnet,
json, json,
@ -252,6 +262,9 @@ pub enum Command {
}, },
ExportBitcoinWallet, ExportBitcoinWallet,
ExportMoneroWallet, ExportMoneroWallet,
ExportMoneroLockWallet {
swap_id: Uuid,
},
} }
#[derive(structopt::StructOpt, Debug)] #[derive(structopt::StructOpt, Debug)]
@ -391,6 +404,16 @@ pub enum ManualRecovery {
#[structopt(flatten)] #[structopt(flatten)]
punish_params: RecoverCommandParams, punish_params: RecoverCommandParams,
}, },
#[structopt(
about = "Get the keys to the Monero lock wallet of a specific swap (requires the taker to have refunded first)."
)]
ExportMoneroLockWallet {
#[structopt(
long = "swap-id",
help = "The swap id can be retrieved using the history subcommand"
)]
swap_id: Uuid,
},
#[structopt(about = "Safely Abort requires the swap to be in a state prior to locking XMR.")] #[structopt(about = "Safely Abort requires the swap to be in a state prior to locking XMR.")]
SafelyAbort { SafelyAbort {
#[structopt( #[structopt(

View file

@ -505,6 +505,57 @@ pub async fn main() -> Result<()> {
println!("Seed : {seed}"); println!("Seed : {seed}");
println!("Restore height: {creation_height}"); println!("Restore height: {creation_height}");
} }
Command::ExportMoneroLockWallet { swap_id } => {
let db = open_db(db_file, AccessMode::ReadWrite, None).await?;
let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config, false).await?;
let swap_states = db
.get_states(swap_id)
.await
.context(format!("Error querying database for swap {swap_id}"))?;
if swap_states.is_empty() {
tracing::error!("No state save for this swap in the database");
}
tracing::info!(?swap_states, "Found swap states");
let state3 = swap_states
.iter()
.filter_map(|state| match state {
State::Alice(AliceState::Started { state3 })
| State::Alice(AliceState::BtcLocked { state3 })
| State::Alice(AliceState::BtcLockTransactionSeen { state3 }) => {
Some(state3.clone())
}
_ => None,
})
.next()
.context("Couldn't find state Started for this swap")?;
let secret_spend_key = match state3.watch_for_btc_tx_refund(&bitcoin_wallet).await {
Ok(secret) => secret,
Err(error) => {
tracing::error!(
?error,
"Could not extract refund secret from taker's refund transaction"
);
return Ok(());
}
};
let secret_view_key = state3.v;
let primary_address = {
let public_spend_key = monero::PublicKey::from_private_key(&secret_spend_key);
let public_view_key = monero::PublicKey::from_private_key(&secret_view_key.into());
monero::Address::standard(config.monero.network, public_spend_key, public_view_key)
};
println!("Retrieved the refund secret from taker's refund transaction. Below are the keys to the Monero lock wallet:
private spend key: {secret_spend_key}
private view key: {secret_view_key}
primary address: {primary_address}");
}
} }
Ok(()) Ok(())