mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
feat: Add RPC endpoint for requesting raw cancel and refund transactions
This commit is contained in:
parent
47b0fdbdee
commit
787827e50f
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -743,7 +743,7 @@ dependencies = [
|
|||||||
"nom",
|
"nom",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"serde",
|
"serde",
|
||||||
"toml 0.8.17",
|
"toml 0.8.16",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4580,7 +4580,7 @@ dependencies = [
|
|||||||
"tokio-tar",
|
"tokio-tar",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml 0.8.17",
|
"toml 0.8.16",
|
||||||
"torut",
|
"torut",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
@ -4920,9 +4920,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.8.17"
|
version = "0.8.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a44eede9b727419af8095cb2d72fab15487a541f54647ad4414b34096ee4631"
|
checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
@ -4932,18 +4932,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.8"
|
version = "0.6.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.22.18"
|
version = "0.22.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1490595c74d930da779e944f5ba2ecdf538af67df1a9848cbd156af43c1b7cf0"
|
checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.1.0",
|
||||||
"serde",
|
"serde",
|
||||||
@ -5767,9 +5767,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.6.16"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c"
|
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
@ -7,9 +7,12 @@ use crate::network::swarm;
|
|||||||
use crate::protocol::bob::{BobState, Swap};
|
use crate::protocol::bob::{BobState, Swap};
|
||||||
use crate::protocol::{bob, State};
|
use crate::protocol::{bob, State};
|
||||||
use crate::{bitcoin, cli, monero, rpc};
|
use crate::{bitcoin, cli, monero, rpc};
|
||||||
|
use crate::database::SwapStateVecExt;
|
||||||
use anyhow::{bail, Context as AnyContext, Result};
|
use anyhow::{bail, Context as AnyContext, Result};
|
||||||
|
use ::bitcoin::consensus::encode::serialize_hex;
|
||||||
use comfy_table::Table;
|
use comfy_table::Table;
|
||||||
use libp2p::core::Multiaddr;
|
use libp2p::core::Multiaddr;
|
||||||
|
use monero_rpc::wallet::BlockHeight;
|
||||||
use qrcode::render::unicode;
|
use qrcode::render::unicode;
|
||||||
use qrcode::QrCode;
|
use qrcode::QrCode;
|
||||||
use rust_decimal::prelude::FromPrimitive;
|
use rust_decimal::prelude::FromPrimitive;
|
||||||
@ -69,6 +72,9 @@ pub enum Method {
|
|||||||
swap_id: Uuid,
|
swap_id: Uuid,
|
||||||
},
|
},
|
||||||
GetRawStates,
|
GetRawStates,
|
||||||
|
GetRawTransactions {
|
||||||
|
swap_id: Uuid,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Method {
|
impl Method {
|
||||||
@ -164,6 +170,14 @@ impl Method {
|
|||||||
method_name = "WithdrawBtc",
|
method_name = "WithdrawBtc",
|
||||||
log_reference_id = field::Empty
|
log_reference_id = field::Empty
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
Method::GetRawTransactions { swap_id } => {
|
||||||
|
debug_span!(
|
||||||
|
"method",
|
||||||
|
method_name = "GetRawTransactions",
|
||||||
|
swap_id=%swap_id,
|
||||||
|
log_reference_id = field::Empty
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(log_reference_id) = log_reference_id {
|
if let Some(log_reference_id) = log_reference_id {
|
||||||
@ -660,15 +674,7 @@ impl Request {
|
|||||||
let latest_state: BobState = state.try_into()?;
|
let latest_state: BobState = state.try_into()?;
|
||||||
let all_states = context.db.get_states(swap_id).await?;
|
let all_states = context.db.get_states(swap_id).await?;
|
||||||
let state3 = all_states
|
let state3 = all_states
|
||||||
.iter()
|
.find_state3()?;
|
||||||
.find_map(|s| {
|
|
||||||
if let State::Bob(BobState::BtcLocked { state3, .. }) = s {
|
|
||||||
Some(state3)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.context("Failed to get \"BtcLocked\" state")?;
|
|
||||||
|
|
||||||
let swap_start_date = context.db.get_swap_start_date(swap_id).await?;
|
let swap_start_date = context.db.get_swap_start_date(swap_id).await?;
|
||||||
let peer_id = context.db.get_peer_id(swap_id).await?;
|
let peer_id = context.db.get_peer_id(swap_id).await?;
|
||||||
@ -915,6 +921,19 @@ impl Request {
|
|||||||
Method::GetCurrentSwap => Ok(json!({
|
Method::GetCurrentSwap => Ok(json!({
|
||||||
"swap_id": context.swap_lock.get_current_swap_id().await
|
"swap_id": context.swap_lock.get_current_swap_id().await
|
||||||
})),
|
})),
|
||||||
|
Method::GetRawTransactions { swap_id } => {
|
||||||
|
let all_states = context.db.get_states(swap_id).await?;
|
||||||
|
let state3 = all_states.find_state3()?;
|
||||||
|
|
||||||
|
let cancelledState = state3.cancel(BlockHeight { height: 0 });
|
||||||
|
let txCancel = cancelledState.construct_tx_cancel()?;
|
||||||
|
let txRefund = cancelledState.signed_refund_transaction()?;
|
||||||
|
|
||||||
|
Ok(json!({
|
||||||
|
"tx_cancel": txCancel.serialize_hex(),
|
||||||
|
"tx_refund": serialize_hex(&txRefund),
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ use std::cmp::Ordering;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use bdk::bitcoin::consensus::encode::{serialize_hex, serialize};
|
||||||
|
|
||||||
/// Represent a timelock, expressed in relative block height as defined in
|
/// Represent a timelock, expressed in relative block height as defined in
|
||||||
/// [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki).
|
/// [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki).
|
||||||
@ -161,6 +162,10 @@ impl TxCancel {
|
|||||||
self.inner.txid()
|
self.inner.txid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn serialize_hex(&self) -> String {
|
||||||
|
serialize_hex(&self.inner)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn digest(&self) -> Sighash {
|
pub fn digest(&self) -> Sighash {
|
||||||
self.digest
|
self.digest
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
pub use alice::Alice;
|
pub use alice::Alice;
|
||||||
pub use bob::Bob;
|
pub use bob::Bob;
|
||||||
|
use monero_rpc::wallet::BlockHeight;
|
||||||
pub use sqlite::SqliteDatabase;
|
pub use sqlite::SqliteDatabase;
|
||||||
|
|
||||||
use crate::fs::ensure_directory_exists;
|
use crate::fs::ensure_directory_exists;
|
||||||
|
use crate::protocol::bob::{BobState, State2, State3};
|
||||||
use crate::protocol::{Database, State};
|
use crate::protocol::{Database, State};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result, anyhow};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -105,3 +107,18 @@ pub async fn open_db(
|
|||||||
Ok(Arc::new(sqlite))
|
Ok(Arc::new(sqlite))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait SwapStateVecExt {
|
||||||
|
fn find_state3(&self) -> Result<State3>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SwapStateVecExt for Vec<State> {
|
||||||
|
fn find_state3(&self) -> Result<State3> {
|
||||||
|
self.iter()
|
||||||
|
.find_map(|state| match state {
|
||||||
|
State::Bob(BobState::BtcLocked {state3, ..}) => Some(state3.clone()),
|
||||||
|
_ => None
|
||||||
|
})
|
||||||
|
.ok_or_else(|| anyhow!("No BobState::BtcLocked found"))
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
use crate::database::Swap;
|
use crate::database::Swap;
|
||||||
use crate::monero::{Address, TransferProof};
|
use crate::monero::{Address, TransferProof};
|
||||||
|
use crate::protocol::bob::{BobState, State3};
|
||||||
use crate::protocol::{Database, State};
|
use crate::protocol::{Database, State};
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -727,11 +727,7 @@ impl State6 {
|
|||||||
&self,
|
&self,
|
||||||
bitcoin_wallet: &bitcoin::Wallet,
|
bitcoin_wallet: &bitcoin::Wallet,
|
||||||
) -> Result<(Txid, Subscription)> {
|
) -> Result<(Txid, Subscription)> {
|
||||||
let transaction = self
|
let transaction = self.signed_cancel_transaction()?;
|
||||||
.construct_tx_cancel()?
|
|
||||||
.complete_as_bob(self.A, self.b.clone(), self.tx_cancel_sig_a.clone())
|
|
||||||
.context("Failed to complete Bitcoin cancel transaction")?;
|
|
||||||
|
|
||||||
let (tx_id, subscription) = bitcoin_wallet.broadcast(transaction, "cancel").await?;
|
let (tx_id, subscription) = bitcoin_wallet.broadcast(transaction, "cancel").await?;
|
||||||
|
|
||||||
Ok((tx_id, subscription))
|
Ok((tx_id, subscription))
|
||||||
@ -760,6 +756,10 @@ impl State6 {
|
|||||||
Ok(signed_tx_refund)
|
Ok(signed_tx_refund)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn signed_cancel_transaction(&self) -> Result<Transaction> {
|
||||||
|
self.construct_tx_cancel()?.complete_as_bob(self.A, self.b.clone(), self.tx_cancel_sig_a.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tx_lock_id(&self) -> bitcoin::Txid {
|
pub fn tx_lock_id(&self) -> bitcoin::Txid {
|
||||||
self.tx_lock.txid()
|
self.tx_lock.txid()
|
||||||
}
|
}
|
||||||
|
@ -213,6 +213,22 @@ pub fn register_modules(context: Arc<Context>) -> Result<RpcModule<Arc<Context>>
|
|||||||
execute_request(params, Method::GetCurrentSwap, &context).await
|
execute_request(params, Method::GetCurrentSwap, &context).await
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
module.register_async_method("get_raw_transactions", |params_raw, context| async move {
|
||||||
|
let params: HashMap<String, serde_json::Value> = params_raw.parse()?;
|
||||||
|
|
||||||
|
let swap_id = params.get("swap_id").ok_or_else(|| {
|
||||||
|
jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let swap_id = as_uuid(swap_id).ok_or_else(|| {
|
||||||
|
jsonrpsee_core::Error::Custom("Could not parse swap_id".to_string())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
execute_request(params_raw, Method::GetRawTransactions {
|
||||||
|
swap_id
|
||||||
|
}, &context).await
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user