mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-12-25 07:29:32 -05:00
Save Bob state during swap
This commit is contained in:
parent
7e0a1ffe84
commit
905fc6cf35
@ -1,5 +1,7 @@
|
||||
use crate::{
|
||||
bob::{event_loop::EventLoopHandle, execution::negotiate},
|
||||
state,
|
||||
state::Bob,
|
||||
storage::Database,
|
||||
SwapAmounts,
|
||||
};
|
||||
@ -17,6 +19,7 @@ use xmr_btc::{
|
||||
|
||||
// The same data structure is used for swap execution and recovery.
|
||||
// This allows for a seamless transition from a failed swap to recovery.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BobState {
|
||||
Started {
|
||||
state0: bob::State0,
|
||||
@ -53,6 +56,32 @@ impl fmt::Display for BobState {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BobState> for state::Bob {
|
||||
fn from(bob_state: BobState) -> Self {
|
||||
match bob_state {
|
||||
BobState::Started {
|
||||
state0,
|
||||
amounts,
|
||||
addr,
|
||||
} => Bob::Started {
|
||||
state0,
|
||||
amounts,
|
||||
addr,
|
||||
},
|
||||
BobState::Negotiated(state2, peer_id) => Bob::Negotiated { state2, peer_id },
|
||||
BobState::BtcLocked(state3, peer_id) => Bob::BtcLocked { state3, peer_id },
|
||||
BobState::XmrLocked(state4, peer_id) => Bob::XmrLocked { state4, peer_id },
|
||||
BobState::EncSigSent(state4, peer_id) => Bob::EncSigSent { state4, peer_id },
|
||||
BobState::BtcRedeemed(state5) => Bob::BtcRedeemed(state5),
|
||||
BobState::Cancelled(state4) => Bob::BtcCancelled(state4),
|
||||
BobState::BtcRefunded(_)
|
||||
| BobState::XmrRedeemed
|
||||
| BobState::Punished
|
||||
| BobState::SafelyAborted => Bob::SwapComplete,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn swap<R>(
|
||||
state: BobState,
|
||||
event_loop_handle: EventLoopHandle,
|
||||
@ -131,8 +160,13 @@ where
|
||||
bitcoin_wallet.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let state = BobState::Negotiated(state2, alice_peer_id);
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
.await?;
|
||||
run_until(
|
||||
BobState::Negotiated(state2, alice_peer_id),
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
@ -146,9 +180,13 @@ where
|
||||
BobState::Negotiated(state2, alice_peer_id) => {
|
||||
// Alice and Bob have exchanged info
|
||||
let state3 = state2.lock_btc(bitcoin_wallet.as_ref()).await?;
|
||||
// db.insert_latest_state(state);
|
||||
|
||||
let state = BobState::BtcLocked(state3, alice_peer_id);
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
.await?;
|
||||
run_until(
|
||||
BobState::BtcLocked(state3, alice_peer_id),
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
@ -168,8 +206,12 @@ where
|
||||
.watch_for_lock_xmr(monero_wallet.as_ref(), msg2)
|
||||
.await?;
|
||||
|
||||
let state = BobState::XmrLocked(state4, alice_peer_id);
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
.await?;
|
||||
run_until(
|
||||
BobState::XmrLocked(state4, alice_peer_id),
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
@ -192,8 +234,12 @@ where
|
||||
.send_message3(alice_peer_id.clone(), tx_redeem_encsig)
|
||||
.await?;
|
||||
|
||||
let state = BobState::EncSigSent(state, alice_peer_id);
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
.await?;
|
||||
run_until(
|
||||
BobState::EncSigSent(state, alice_peer_id),
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
@ -209,10 +255,14 @@ where
|
||||
let redeem_watcher = state.watch_for_redeem_btc(bitcoin_wallet.as_ref());
|
||||
let t1_timeout = state.wait_for_t1(bitcoin_wallet.as_ref());
|
||||
|
||||
// TODO(Franck): Check if db save and run_until can be factorized
|
||||
tokio::select! {
|
||||
val = redeem_watcher => {
|
||||
let state = BobState::BtcRedeemed(val?);
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state)).await?;
|
||||
run_until(
|
||||
BobState::BtcRedeemed(val?),
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
@ -230,15 +280,18 @@ where
|
||||
state.submit_tx_cancel(bitcoin_wallet.as_ref()).await?;
|
||||
}
|
||||
|
||||
let state = BobState::Cancelled(state);
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state)).await?;
|
||||
run_until(
|
||||
BobState::Cancelled(state),
|
||||
is_target_state,
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id
|
||||
swap_id
|
||||
)
|
||||
.await
|
||||
|
||||
@ -248,8 +301,13 @@ where
|
||||
BobState::BtcRedeemed(state) => {
|
||||
// Bob redeems XMR using revealed s_a
|
||||
state.claim_xmr(monero_wallet.as_ref()).await?;
|
||||
|
||||
let state = BobState::XmrRedeemed;
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
.await?;
|
||||
run_until(
|
||||
BobState::XmrRedeemed,
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
@ -261,37 +319,31 @@ where
|
||||
.await
|
||||
}
|
||||
BobState::Cancelled(state) => {
|
||||
// TODO
|
||||
// Bob has cancelled the swap
|
||||
match state.current_epoch(bitcoin_wallet.as_ref()).await? {
|
||||
let state = match state.current_epoch(bitcoin_wallet.as_ref()).await? {
|
||||
Epoch::T0 => panic!("Cancelled before t1??? Something is really wrong"),
|
||||
Epoch::T1 => {
|
||||
state.refund_btc(bitcoin_wallet.as_ref()).await?;
|
||||
run_until(
|
||||
BobState::BtcRefunded(state),
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
)
|
||||
.await
|
||||
BobState::BtcRefunded(state)
|
||||
}
|
||||
Epoch::T2 => {
|
||||
run_until(
|
||||
BobState::Punished,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
Epoch::T2 => BobState::Punished,
|
||||
};
|
||||
|
||||
let db_state = state.clone().into();
|
||||
db.insert_latest_state(swap_id, state::Swap::Bob(db_state))
|
||||
.await?;
|
||||
run_until(
|
||||
state,
|
||||
is_target_state,
|
||||
event_loop_handle,
|
||||
db,
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
rng,
|
||||
swap_id,
|
||||
)
|
||||
.await
|
||||
}
|
||||
BobState::BtcRefunded(state4) => Ok(BobState::BtcRefunded(state4)),
|
||||
BobState::Punished => Ok(BobState::Punished),
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ::serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
pub mod alice;
|
||||
@ -10,6 +10,7 @@ pub mod cli;
|
||||
pub mod monero;
|
||||
pub mod network;
|
||||
pub mod recover;
|
||||
pub mod serde;
|
||||
pub mod state;
|
||||
pub mod storage;
|
||||
pub mod tor;
|
||||
@ -31,7 +32,7 @@ pub enum Rsp {
|
||||
}
|
||||
|
||||
/// XMR/BTC swap amounts.
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
// TODO(Franck): review necessity of this struct
|
||||
pub struct SwapAmounts {
|
||||
/// Amount of BTC to swap.
|
||||
|
@ -24,9 +24,12 @@ use futures::{
|
||||
};
|
||||
use sha2::Sha256;
|
||||
use tracing::info;
|
||||
use xmr_btc::bitcoin::{
|
||||
poll_until_block_height_is_gte, BroadcastSignedTransaction, TransactionBlockHeight,
|
||||
WatchForRawTransaction,
|
||||
use xmr_btc::{
|
||||
bitcoin::{
|
||||
poll_until_block_height_is_gte, BroadcastSignedTransaction, TransactionBlockHeight,
|
||||
WatchForRawTransaction,
|
||||
},
|
||||
bob::{State3, State4},
|
||||
};
|
||||
|
||||
pub async fn recover(
|
||||
@ -366,18 +369,53 @@ pub async fn bob_recover(
|
||||
state: Bob,
|
||||
) -> Result<()> {
|
||||
match state {
|
||||
Bob::Handshaken(_) | Bob::SwapComplete => {
|
||||
Bob::Negotiated { .. } | Bob::SwapComplete => {
|
||||
info!("Nothing to do");
|
||||
}
|
||||
Bob::BtcLocked(state) | Bob::XmrLocked(state) | Bob::BtcRefundable(state) => {
|
||||
Bob::BtcLocked {
|
||||
state3:
|
||||
State3 {
|
||||
A,
|
||||
b,
|
||||
s_b,
|
||||
refund_timelock,
|
||||
refund_address,
|
||||
tx_lock,
|
||||
tx_cancel_sig_a,
|
||||
tx_refund_encsig,
|
||||
..
|
||||
},
|
||||
..
|
||||
}
|
||||
| Bob::XmrLocked {
|
||||
state4:
|
||||
State4 {
|
||||
A,
|
||||
b,
|
||||
s_b,
|
||||
refund_timelock,
|
||||
refund_address,
|
||||
tx_lock,
|
||||
tx_cancel_sig_a,
|
||||
tx_refund_encsig,
|
||||
..
|
||||
},
|
||||
..
|
||||
}
|
||||
| Bob::BtcCancelled(State4 {
|
||||
A,
|
||||
b,
|
||||
s_b,
|
||||
refund_timelock,
|
||||
refund_address,
|
||||
tx_lock,
|
||||
tx_cancel_sig_a,
|
||||
tx_refund_encsig,
|
||||
..
|
||||
}) => {
|
||||
info!("Bitcoin may still be locked up, attempting to refund");
|
||||
|
||||
let tx_cancel = bitcoin::TxCancel::new(
|
||||
&state.tx_lock,
|
||||
state.refund_timelock,
|
||||
state.A,
|
||||
state.b.public(),
|
||||
);
|
||||
let tx_cancel = bitcoin::TxCancel::new(&tx_lock, refund_timelock, A, b.public());
|
||||
|
||||
info!("Checking if the Bitcoin cancel transaction has been published");
|
||||
if bitcoin_wallet
|
||||
@ -389,20 +427,17 @@ pub async fn bob_recover(
|
||||
info!("Bitcoin cancel transaction not yet published");
|
||||
|
||||
let tx_lock_height = bitcoin_wallet
|
||||
.transaction_block_height(state.tx_lock.txid())
|
||||
.transaction_block_height(tx_lock.txid())
|
||||
.await;
|
||||
poll_until_block_height_is_gte(&bitcoin_wallet, tx_lock_height + refund_timelock)
|
||||
.await;
|
||||
poll_until_block_height_is_gte(
|
||||
&bitcoin_wallet,
|
||||
tx_lock_height + state.refund_timelock,
|
||||
)
|
||||
.await;
|
||||
|
||||
let sig_a = state.tx_cancel_sig_a.clone();
|
||||
let sig_b = state.b.sign(tx_cancel.digest());
|
||||
let sig_a = tx_cancel_sig_a.clone();
|
||||
let sig_b = b.sign(tx_cancel.digest());
|
||||
|
||||
let tx_cancel = tx_cancel
|
||||
.clone()
|
||||
.add_signatures(&state.tx_lock, (state.A, sig_a), (state.b.public(), sig_b))
|
||||
.add_signatures(&tx_lock, (A, sig_a), (b.public(), sig_b))
|
||||
.expect("sig_{a,b} to be valid signatures for tx_cancel");
|
||||
|
||||
// TODO: We should not fail if the transaction is already on the blockchain
|
||||
@ -413,15 +448,15 @@ pub async fn bob_recover(
|
||||
|
||||
info!("Confirmed that Bitcoin cancel transaction is on the blockchain");
|
||||
|
||||
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &state.refund_address);
|
||||
let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &refund_address);
|
||||
let signed_tx_refund = {
|
||||
let adaptor = Adaptor::<Sha256, Deterministic<Sha256>>::default();
|
||||
let sig_a = adaptor
|
||||
.decrypt_signature(&state.s_b.into_secp256k1(), state.tx_refund_encsig.clone());
|
||||
let sig_b = state.b.sign(tx_refund.digest());
|
||||
let sig_a =
|
||||
adaptor.decrypt_signature(&s_b.into_secp256k1(), tx_refund_encsig.clone());
|
||||
let sig_b = b.sign(tx_refund.digest());
|
||||
|
||||
tx_refund
|
||||
.add_signatures(&tx_cancel, (state.A, sig_a), (state.b.public(), sig_b))
|
||||
.add_signatures(&tx_cancel, (A, sig_a), (b.public(), sig_b))
|
||||
.expect("sig_{a,b} to be valid signatures for tx_refund")
|
||||
};
|
||||
|
||||
@ -459,6 +494,8 @@ pub async fn bob_recover(
|
||||
.await?;
|
||||
info!("Successfully redeemed monero")
|
||||
}
|
||||
Bob::Started { .. } => todo!(),
|
||||
Bob::EncSigSent { .. } => todo!(),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
47
swap/src/serde.rs
Normal file
47
swap/src/serde.rs
Normal file
@ -0,0 +1,47 @@
|
||||
pub mod peer_id {
|
||||
use libp2p::PeerId;
|
||||
use serde::{de::Error, Deserialize, Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S>(peer_id: &PeerId, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let string = peer_id.to_string();
|
||||
serializer.serialize_str(&string)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<PeerId, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let string = String::deserialize(deserializer)?;
|
||||
let peer_id = string.parse().map_err(D::Error::custom)?;
|
||||
|
||||
Ok(peer_id)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use serde::Serialize;
|
||||
use spectral::prelude::*;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SerializablePeerId(#[serde(with = "super")] PeerId);
|
||||
|
||||
#[test]
|
||||
fn maker_id_serializes_as_expected() {
|
||||
let peer_id = SerializablePeerId(
|
||||
"QmfUfpC2frwFvcDzpspnfZitHt5wct6n4kpG5jzgRdsxkY"
|
||||
.parse()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let got = serde_json::to_string(&peer_id).expect("failed to serialize peer id");
|
||||
|
||||
assert_that(&got)
|
||||
.is_equal_to(r#""QmfUfpC2frwFvcDzpspnfZitHt5wct6n4kpG5jzgRdsxkY""#.to_string());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
use crate::SwapAmounts;
|
||||
use libp2p::{core::Multiaddr, PeerId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
use xmr_btc::{alice, bitcoin::EncryptedSignature, bob, monero, serde::monero_private_key};
|
||||
@ -37,11 +39,33 @@ pub enum Alice {
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub enum Bob {
|
||||
Handshaken(bob::State2),
|
||||
BtcLocked(bob::State2),
|
||||
XmrLocked(bob::State2),
|
||||
BtcRedeemed(bob::State2),
|
||||
BtcRefundable(bob::State2),
|
||||
Started {
|
||||
state0: bob::State0,
|
||||
amounts: SwapAmounts,
|
||||
addr: Multiaddr,
|
||||
},
|
||||
Negotiated {
|
||||
state2: bob::State2,
|
||||
#[serde(with = "crate::serde::peer_id")]
|
||||
peer_id: PeerId,
|
||||
},
|
||||
BtcLocked {
|
||||
state3: bob::State3,
|
||||
#[serde(with = "crate::serde::peer_id")]
|
||||
peer_id: PeerId,
|
||||
},
|
||||
XmrLocked {
|
||||
state4: bob::State4,
|
||||
#[serde(with = "crate::serde::peer_id")]
|
||||
peer_id: PeerId,
|
||||
},
|
||||
EncSigSent {
|
||||
state4: bob::State4,
|
||||
#[serde(with = "crate::serde::peer_id")]
|
||||
peer_id: PeerId,
|
||||
},
|
||||
BtcRedeemed(bob::State5),
|
||||
BtcCancelled(bob::State4),
|
||||
SwapComplete,
|
||||
}
|
||||
|
||||
@ -85,12 +109,14 @@ impl Display for Alice {
|
||||
impl Display for Bob {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Bob::Handshaken(_) => f.write_str("Handshake complete"),
|
||||
Bob::BtcLocked(_) | Bob::XmrLocked(_) | Bob::BtcRefundable(_) => {
|
||||
Bob::Negotiated { .. } => f.write_str("Handshake complete"),
|
||||
Bob::BtcLocked { .. } | Bob::XmrLocked { .. } | Bob::BtcCancelled(_) => {
|
||||
f.write_str("Bitcoin refundable")
|
||||
}
|
||||
Bob::BtcRedeemed(_) => f.write_str("Monero redeemable"),
|
||||
Bob::SwapComplete => f.write_str("Swap complete"),
|
||||
Bob::Started { .. } => f.write_str("Swap started"),
|
||||
Bob::EncSigSent { .. } => f.write_str("Encrypted signature sent"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,7 +346,7 @@ impl_from_child_enum!(State3, State);
|
||||
impl_from_child_enum!(State4, State);
|
||||
impl_from_child_enum!(State5, State);
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct State0 {
|
||||
b: bitcoin::SecretKey,
|
||||
s_b: cross_curve_dleq::Scalar,
|
||||
@ -560,25 +560,25 @@ impl State2 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
pub struct State3 {
|
||||
A: bitcoin::PublicKey,
|
||||
b: bitcoin::SecretKey,
|
||||
s_b: cross_curve_dleq::Scalar,
|
||||
pub A: bitcoin::PublicKey,
|
||||
pub b: bitcoin::SecretKey,
|
||||
pub s_b: cross_curve_dleq::Scalar,
|
||||
S_a_monero: monero::PublicKey,
|
||||
S_a_bitcoin: bitcoin::PublicKey,
|
||||
v: monero::PrivateViewKey,
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
pub refund_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
pub refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
punish_address: bitcoin::Address,
|
||||
tx_lock: bitcoin::TxLock,
|
||||
tx_cancel_sig_a: Signature,
|
||||
tx_refund_encsig: EncryptedSignature,
|
||||
pub tx_lock: bitcoin::TxLock,
|
||||
pub tx_cancel_sig_a: Signature,
|
||||
pub tx_refund_encsig: EncryptedSignature,
|
||||
}
|
||||
|
||||
impl State3 {
|
||||
@ -626,11 +626,11 @@ impl State3 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
pub struct State4 {
|
||||
pub A: bitcoin::PublicKey,
|
||||
pub b: bitcoin::SecretKey,
|
||||
s_b: cross_curve_dleq::Scalar,
|
||||
pub s_b: cross_curve_dleq::Scalar,
|
||||
S_a_monero: monero::PublicKey,
|
||||
pub S_a_bitcoin: bitcoin::PublicKey,
|
||||
v: monero::PrivateViewKey,
|
||||
@ -639,12 +639,12 @@ pub struct State4 {
|
||||
xmr: monero::Amount,
|
||||
pub refund_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
pub refund_address: bitcoin::Address,
|
||||
pub redeem_address: bitcoin::Address,
|
||||
punish_address: bitcoin::Address,
|
||||
pub tx_lock: bitcoin::TxLock,
|
||||
tx_cancel_sig_a: Signature,
|
||||
tx_refund_encsig: EncryptedSignature,
|
||||
pub tx_cancel_sig_a: Signature,
|
||||
pub tx_refund_encsig: EncryptedSignature,
|
||||
}
|
||||
|
||||
impl State4 {
|
||||
@ -823,25 +823,25 @@ impl State4 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
pub struct State5 {
|
||||
A: bitcoin::PublicKey,
|
||||
b: bitcoin::SecretKey,
|
||||
pub b: bitcoin::SecretKey,
|
||||
#[serde(with = "monero_private_key")]
|
||||
s_a: monero::PrivateKey,
|
||||
s_b: cross_curve_dleq::Scalar,
|
||||
pub s_b: cross_curve_dleq::Scalar,
|
||||
S_a_monero: monero::PublicKey,
|
||||
S_a_bitcoin: bitcoin::PublicKey,
|
||||
v: monero::PrivateViewKey,
|
||||
pub S_a_bitcoin: bitcoin::PublicKey,
|
||||
pub v: monero::PrivateViewKey,
|
||||
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
|
||||
btc: bitcoin::Amount,
|
||||
xmr: monero::Amount,
|
||||
refund_timelock: u32,
|
||||
punish_timelock: u32,
|
||||
refund_address: bitcoin::Address,
|
||||
redeem_address: bitcoin::Address,
|
||||
pub redeem_address: bitcoin::Address,
|
||||
punish_address: bitcoin::Address,
|
||||
tx_lock: bitcoin::TxLock,
|
||||
pub tx_lock: bitcoin::TxLock,
|
||||
tx_refund_encsig: EncryptedSignature,
|
||||
tx_cancel_sig: Signature,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user