mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Started to extract some steps
Tealised that the whole point is for them to be idempotent to be useful
This commit is contained in:
parent
66866f8fbd
commit
437c1cbb80
@ -2,6 +2,7 @@
|
|||||||
//! Alice holds XMR and wishes receive BTC.
|
//! Alice holds XMR and wishes receive BTC.
|
||||||
use self::{amounts::*, message0::*, message1::*, message2::*, message3::*};
|
use self::{amounts::*, message0::*, message1::*, message2::*, message3::*};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
alice::execution::{lock_xmr, negotiate},
|
||||||
bitcoin,
|
bitcoin,
|
||||||
bitcoin::{EncryptedSignature, TX_LOCK_MINE_TIMEOUT},
|
bitcoin::{EncryptedSignature, TX_LOCK_MINE_TIMEOUT},
|
||||||
monero,
|
monero,
|
||||||
@ -15,7 +16,7 @@ use crate::{
|
|||||||
storage::Database,
|
storage::Database,
|
||||||
SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK,
|
SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use backoff::{backoff::Constant as ConstantBackoff, future::FutureOperation as _};
|
use backoff::{backoff::Constant as ConstantBackoff, future::FutureOperation as _};
|
||||||
@ -40,14 +41,15 @@ use xmr_btc::{
|
|||||||
alice::{self, action_generator, Action, ReceiveBitcoinRedeemEncsig, State0, State3},
|
alice::{self, action_generator, Action, ReceiveBitcoinRedeemEncsig, State0, State3},
|
||||||
bitcoin::{
|
bitcoin::{
|
||||||
poll_until_block_height_is_gte, BroadcastSignedTransaction, GetRawTransaction,
|
poll_until_block_height_is_gte, BroadcastSignedTransaction, GetRawTransaction,
|
||||||
TransactionBlockHeight, TxCancel, TxRefund, WatchForRawTransaction,
|
TransactionBlockHeight, TxCancel, TxRefund, WaitForTransactionFinality,
|
||||||
WatchForTransactionFinality,
|
WatchForRawTransaction,
|
||||||
},
|
},
|
||||||
bob, cross_curve_dleq,
|
bob, cross_curve_dleq,
|
||||||
monero::{CreateWalletForOutput, Transfer},
|
monero::{CreateWalletForOutput, Transfer},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod amounts;
|
mod amounts;
|
||||||
|
mod execution;
|
||||||
mod message0;
|
mod message0;
|
||||||
mod message1;
|
mod message1;
|
||||||
mod message2;
|
mod message2;
|
||||||
@ -67,13 +69,11 @@ pub enum AliceState {
|
|||||||
v_a: monero::PrivateViewKey,
|
v_a: monero::PrivateViewKey,
|
||||||
},
|
},
|
||||||
Negotiated {
|
Negotiated {
|
||||||
swap_id: Uuid,
|
|
||||||
channel: ResponseChannel<AliceToBob>,
|
channel: ResponseChannel<AliceToBob>,
|
||||||
amounts: SwapAmounts,
|
amounts: SwapAmounts,
|
||||||
state3: State3,
|
state3: State3,
|
||||||
},
|
},
|
||||||
BtcLocked {
|
BtcLocked {
|
||||||
swap_id: Uuid,
|
|
||||||
channel: ResponseChannel<AliceToBob>,
|
channel: ResponseChannel<AliceToBob>,
|
||||||
amounts: SwapAmounts,
|
amounts: SwapAmounts,
|
||||||
state3: State3,
|
state3: State3,
|
||||||
@ -117,7 +117,6 @@ pub enum AliceState {
|
|||||||
pub async fn simple_swap(
|
pub async fn simple_swap(
|
||||||
state: AliceState,
|
state: AliceState,
|
||||||
mut swarm: Swarm,
|
mut swarm: Swarm,
|
||||||
db: Database,
|
|
||||||
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
||||||
monero_wallet: Arc<crate::monero::Wallet>,
|
monero_wallet: Arc<crate::monero::Wallet>,
|
||||||
) -> Result<AliceState> {
|
) -> Result<AliceState> {
|
||||||
@ -128,166 +127,62 @@ pub async fn simple_swap(
|
|||||||
s_a,
|
s_a,
|
||||||
v_a,
|
v_a,
|
||||||
} => {
|
} => {
|
||||||
// Bob dials us
|
let (channel, amounts, state3) =
|
||||||
let bob_peer_id = match swarm.next().await {
|
negotiate(amounts, a, s_a, v_a, &mut swarm, bitcoin_wallet.clone()).await?;
|
||||||
OutEvent::ConnectionEstablished(bob_peer_id) => bob_peer_id,
|
|
||||||
other => bail!("Unexpected event received: {:?}", other),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Bob sends us a request
|
|
||||||
let (btc, channel) = match swarm.next().await {
|
|
||||||
OutEvent::Request(amounts::OutEvent::Btc { btc, channel }) => (btc, channel),
|
|
||||||
other => bail!("Unexpected event received: {:?}", other),
|
|
||||||
};
|
|
||||||
|
|
||||||
if btc != amounts.btc {
|
|
||||||
bail!(
|
|
||||||
"Bob proposed a different amount; got {}, expected: {}",
|
|
||||||
btc,
|
|
||||||
amounts.btc
|
|
||||||
);
|
|
||||||
}
|
|
||||||
swarm.send_amounts(channel, amounts);
|
|
||||||
|
|
||||||
let SwapAmounts { btc, xmr } = amounts;
|
|
||||||
|
|
||||||
let redeem_address = bitcoin_wallet.as_ref().new_address().await?;
|
|
||||||
let punish_address = redeem_address.clone();
|
|
||||||
|
|
||||||
let state0 = State0::new(
|
|
||||||
a,
|
|
||||||
s_a,
|
|
||||||
v_a,
|
|
||||||
btc,
|
|
||||||
xmr,
|
|
||||||
REFUND_TIMELOCK,
|
|
||||||
PUNISH_TIMELOCK,
|
|
||||||
redeem_address,
|
|
||||||
punish_address,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Bob sends us message0
|
|
||||||
let message0 = match swarm.next().await {
|
|
||||||
OutEvent::Message0(msg) => msg,
|
|
||||||
other => bail!("Unexpected event received: {:?}", other),
|
|
||||||
};
|
|
||||||
|
|
||||||
let state1 = state0.receive(message0)?;
|
|
||||||
|
|
||||||
// TODO(Franck) We should use the same channel everytime,
|
|
||||||
// Can we remove this response channel?
|
|
||||||
let (state2, channel) = match swarm.next().await {
|
|
||||||
OutEvent::Message1 { msg, channel } => {
|
|
||||||
let state2 = state1.receive(msg);
|
|
||||||
(state2, channel)
|
|
||||||
}
|
|
||||||
other => bail!("Unexpected event: {:?}", other),
|
|
||||||
};
|
|
||||||
|
|
||||||
let message1 = state2.next_message();
|
|
||||||
swarm.send_message1(channel, message1);
|
|
||||||
|
|
||||||
let (state3, channel) = match swarm.next().await {
|
|
||||||
OutEvent::Message2 { msg, channel } => {
|
|
||||||
let state3 = state2.receive(msg)?;
|
|
||||||
(state3, channel)
|
|
||||||
}
|
|
||||||
other => bail!("Unexpected event: {:?}", other),
|
|
||||||
};
|
|
||||||
|
|
||||||
let swap_id = Uuid::new_v4();
|
|
||||||
// TODO(Franck): Use the same terminology (negotiated) to describe this state.
|
|
||||||
db.insert_latest_state(swap_id, state::Alice::Handshaken(state3.clone()).into())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"State transitioned from Started to Negotiated, Bob peer id is {}",
|
|
||||||
bob_peer_id
|
|
||||||
);
|
|
||||||
|
|
||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::Negotiated {
|
AliceState::Negotiated {
|
||||||
swap_id,
|
|
||||||
state3,
|
|
||||||
channel,
|
channel,
|
||||||
amounts,
|
amounts,
|
||||||
|
state3,
|
||||||
},
|
},
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
AliceState::Negotiated {
|
AliceState::Negotiated {
|
||||||
swap_id,
|
|
||||||
state3,
|
state3,
|
||||||
channel,
|
channel,
|
||||||
amounts,
|
amounts,
|
||||||
} => {
|
} => {
|
||||||
// TODO(1): Do a future select with watch bitcoin blockchain time
|
|
||||||
// TODO(2): Implement a proper safe expiry module
|
|
||||||
timeout(
|
timeout(
|
||||||
Duration::from_secs(TX_LOCK_MINE_TIMEOUT),
|
Duration::from_secs(TX_LOCK_MINE_TIMEOUT),
|
||||||
// TODO(Franck): Need to check amount?
|
bitcoin_wallet.wait_for_transaction_finality(state3.tx_lock.txid()),
|
||||||
bitcoin_wallet.watch_for_raw_transaction(state3.tx_lock.txid()),
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("Timed out, Bob did not lock Bitcoin in time")?;
|
.context("Timed out, Bob did not lock Bitcoin in time")?;
|
||||||
|
|
||||||
db.insert_latest_state(swap_id, state::Alice::BtcLocked(state3.clone()).into())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::BtcLocked {
|
AliceState::BtcLocked {
|
||||||
swap_id,
|
|
||||||
channel,
|
channel,
|
||||||
amounts,
|
amounts,
|
||||||
state3,
|
state3,
|
||||||
},
|
},
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
AliceState::BtcLocked {
|
AliceState::BtcLocked {
|
||||||
swap_id,
|
|
||||||
channel,
|
channel,
|
||||||
amounts,
|
amounts,
|
||||||
state3,
|
state3,
|
||||||
} => {
|
} => {
|
||||||
let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey {
|
lock_xmr(
|
||||||
scalar: state3.s_a.into_ed25519(),
|
channel,
|
||||||
});
|
amounts,
|
||||||
|
state3.clone(),
|
||||||
let public_spend_key = S_a + state3.S_b_monero;
|
&mut swarm,
|
||||||
let public_view_key = state3.v.public();
|
monero_wallet.clone(),
|
||||||
|
)
|
||||||
// TODO(Franck): Probably need to wait at least 1 confirmation to be sure that
|
.await?;
|
||||||
// we don't wrongfully think this is done.
|
|
||||||
let (transfer_proof, _) = monero_wallet
|
|
||||||
.transfer(public_spend_key, public_view_key, amounts.xmr)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
swarm.send_message2(channel, alice::Message2 {
|
|
||||||
tx_lock_proof: transfer_proof,
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO(Franck): we should merge state::Alice and AliceState.
|
|
||||||
// There should be only 2 states:
|
|
||||||
// 1. the cryptographic state (State0, etc) which only aware of the crypto
|
|
||||||
// primitive to execute the protocol 2. the more general/business
|
|
||||||
// state that contains the crypto + other business data such as network
|
|
||||||
// communication, amounts to verify, swap id, etc.
|
|
||||||
db.insert_latest_state(swap_id, state::Alice::XmrLocked(state3.clone()).into())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::XmrLocked { state3 },
|
AliceState::XmrLocked { state3 },
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -295,8 +190,7 @@ pub async fn simple_swap(
|
|||||||
}
|
}
|
||||||
AliceState::XmrLocked { state3 } => {
|
AliceState::XmrLocked { state3 } => {
|
||||||
let encsig = timeout(
|
let encsig = timeout(
|
||||||
// TODO(Franck): This is now inefficient as time has been spent since btc was
|
// Give a set arbitrary time to Bob to send us `tx_redeem_encsign`
|
||||||
// locked
|
|
||||||
Duration::from_secs(TX_LOCK_MINE_TIMEOUT),
|
Duration::from_secs(TX_LOCK_MINE_TIMEOUT),
|
||||||
async {
|
async {
|
||||||
match swarm.next().await {
|
match swarm.next().await {
|
||||||
@ -318,7 +212,6 @@ pub async fn simple_swap(
|
|||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::WaitingToCancel { state3 },
|
AliceState::WaitingToCancel { state3 },
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -330,7 +223,6 @@ pub async fn simple_swap(
|
|||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::WaitingToCancel { state3 },
|
AliceState::WaitingToCancel { state3 },
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -345,7 +237,6 @@ pub async fn simple_swap(
|
|||||||
encrypted_signature,
|
encrypted_signature,
|
||||||
},
|
},
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -397,7 +288,6 @@ pub async fn simple_swap(
|
|||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::BtcRedeemed,
|
AliceState::BtcRedeemed,
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -441,7 +331,6 @@ pub async fn simple_swap(
|
|||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::BtcCancelled { state3, tx_cancel },
|
AliceState::BtcCancelled { state3, tx_cancel },
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet,
|
bitcoin_wallet,
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -468,7 +357,6 @@ pub async fn simple_swap(
|
|||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::BtcPunishable { tx_refund, state3 },
|
AliceState::BtcPunishable { tx_refund, state3 },
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -482,7 +370,6 @@ pub async fn simple_swap(
|
|||||||
state3,
|
state3,
|
||||||
},
|
},
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -552,7 +439,6 @@ pub async fn simple_swap(
|
|||||||
state3,
|
state3,
|
||||||
},
|
},
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -563,7 +449,7 @@ pub async fn simple_swap(
|
|||||||
tx_refund,
|
tx_refund,
|
||||||
state3,
|
state3,
|
||||||
} => {
|
} => {
|
||||||
let punish_tx_finalised = bitcoin_wallet.watch_for_transaction_finality(punished_tx_id);
|
let punish_tx_finalised = bitcoin_wallet.wait_for_transaction_finality(punished_tx_id);
|
||||||
|
|
||||||
let refund_tx_seen = bitcoin_wallet.watch_for_raw_transaction(tx_refund.txid());
|
let refund_tx_seen = bitcoin_wallet.watch_for_raw_transaction(tx_refund.txid());
|
||||||
|
|
||||||
@ -575,7 +461,6 @@ pub async fn simple_swap(
|
|||||||
simple_swap(
|
simple_swap(
|
||||||
AliceState::Punished,
|
AliceState::Punished,
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
@ -589,7 +474,6 @@ pub async fn simple_swap(
|
|||||||
state3,
|
state3,
|
||||||
},
|
},
|
||||||
swarm,
|
swarm,
|
||||||
db,
|
|
||||||
bitcoin_wallet.clone(),
|
bitcoin_wallet.clone(),
|
||||||
monero_wallet,
|
monero_wallet,
|
||||||
)
|
)
|
||||||
|
119
swap/src/alice/execution.rs
Normal file
119
swap/src/alice/execution.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
use crate::{
|
||||||
|
alice::{amounts, OutEvent, Swarm},
|
||||||
|
network::request_response::AliceToBob,
|
||||||
|
SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK,
|
||||||
|
};
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use libp2p::request_response::ResponseChannel;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use xmr_btc::{
|
||||||
|
alice,
|
||||||
|
alice::{State0, State3},
|
||||||
|
cross_curve_dleq,
|
||||||
|
monero::Transfer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO(Franck): Make all methods here idempotent using db
|
||||||
|
|
||||||
|
pub async fn negotiate(
|
||||||
|
amounts: SwapAmounts,
|
||||||
|
a: crate::bitcoin::SecretKey,
|
||||||
|
s_a: cross_curve_dleq::Scalar,
|
||||||
|
v_a: crate::monero::PrivateViewKey,
|
||||||
|
swarm: &mut Swarm,
|
||||||
|
bitcoin_wallet: Arc<crate::bitcoin::Wallet>,
|
||||||
|
) -> Result<(ResponseChannel<AliceToBob>, SwapAmounts, State3)> {
|
||||||
|
// Bob dials us
|
||||||
|
match swarm.next().await {
|
||||||
|
OutEvent::ConnectionEstablished(_bob_peer_id) => {}
|
||||||
|
other => bail!("Unexpected event received: {:?}", other),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bob sends us a request
|
||||||
|
let (btc, channel) = match swarm.next().await {
|
||||||
|
OutEvent::Request(amounts::OutEvent::Btc { btc, channel }) => (btc, channel),
|
||||||
|
other => bail!("Unexpected event received: {:?}", other),
|
||||||
|
};
|
||||||
|
|
||||||
|
if btc != amounts.btc {
|
||||||
|
bail!(
|
||||||
|
"Bob proposed a different amount; got {}, expected: {}",
|
||||||
|
btc,
|
||||||
|
amounts.btc
|
||||||
|
);
|
||||||
|
}
|
||||||
|
swarm.send_amounts(channel, amounts);
|
||||||
|
|
||||||
|
let SwapAmounts { btc, xmr } = amounts;
|
||||||
|
|
||||||
|
let redeem_address = bitcoin_wallet.as_ref().new_address().await?;
|
||||||
|
let punish_address = redeem_address.clone();
|
||||||
|
|
||||||
|
let state0 = State0::new(
|
||||||
|
a,
|
||||||
|
s_a,
|
||||||
|
v_a,
|
||||||
|
btc,
|
||||||
|
xmr,
|
||||||
|
REFUND_TIMELOCK,
|
||||||
|
PUNISH_TIMELOCK,
|
||||||
|
redeem_address,
|
||||||
|
punish_address,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Bob sends us message0
|
||||||
|
let message0 = match swarm.next().await {
|
||||||
|
OutEvent::Message0(msg) => msg,
|
||||||
|
other => bail!("Unexpected event received: {:?}", other),
|
||||||
|
};
|
||||||
|
|
||||||
|
let state1 = state0.receive(message0)?;
|
||||||
|
|
||||||
|
let (state2, channel) = match swarm.next().await {
|
||||||
|
OutEvent::Message1 { msg, channel } => {
|
||||||
|
let state2 = state1.receive(msg);
|
||||||
|
(state2, channel)
|
||||||
|
}
|
||||||
|
other => bail!("Unexpected event: {:?}", other),
|
||||||
|
};
|
||||||
|
|
||||||
|
let message1 = state2.next_message();
|
||||||
|
swarm.send_message1(channel, message1);
|
||||||
|
|
||||||
|
let (state3, channel) = match swarm.next().await {
|
||||||
|
OutEvent::Message2 { msg, channel } => {
|
||||||
|
let state3 = state2.receive(msg)?;
|
||||||
|
(state3, channel)
|
||||||
|
}
|
||||||
|
other => bail!("Unexpected event: {:?}", other),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((channel, amounts, state3))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn lock_xmr(
|
||||||
|
channel: ResponseChannel<AliceToBob>,
|
||||||
|
amounts: SwapAmounts,
|
||||||
|
state3: State3,
|
||||||
|
swarm: &mut Swarm,
|
||||||
|
monero_wallet: Arc<crate::monero::Wallet>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let S_a = monero::PublicKey::from_private_key(&monero::PrivateKey {
|
||||||
|
scalar: state3.s_a.into_ed25519(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let public_spend_key = S_a + state3.S_b_monero;
|
||||||
|
let public_view_key = state3.v.public();
|
||||||
|
|
||||||
|
let (transfer_proof, _) = monero_wallet
|
||||||
|
.transfer(public_spend_key, public_view_key, amounts.xmr)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
swarm.send_message2(channel, alice::Message2 {
|
||||||
|
tx_lock_proof: transfer_proof,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO(Franck): Wait for Monero to be mined/finalised
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -162,8 +162,8 @@ impl GetRawTransaction for Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl WatchForTransactionFinality for Wallet {
|
impl WaitForTransactionFinality for Wallet {
|
||||||
async fn watch_for_transaction_finality(&self, _txid: Txid) {
|
async fn wait_for_transaction_finality(&self, _txid: Txid) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,9 +186,8 @@ pub trait WatchForRawTransaction {
|
|||||||
async fn watch_for_raw_transaction(&self, txid: Txid) -> Transaction;
|
async fn watch_for_raw_transaction(&self, txid: Txid) -> Transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
pub trait WaitForTransactionFinality {
|
||||||
pub trait GetRawTransaction {
|
async fn wait_for_transaction_finality(&self, txid: Txid);
|
||||||
async fn get_raw_transaction(&self, txid: Txid) -> Result<Transaction>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -208,7 +207,7 @@ pub trait WaitForBlockHeight {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait GetRawTransaction {
|
pub trait GetRawTransaction {
|
||||||
async fn get_raw_transaction(&self, txid: Txid) -> Option<Transaction>;
|
async fn get_raw_transaction(&self, txid: Txid) -> Result<Transaction>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recover(S: PublicKey, sig: Signature, encsig: EncryptedSignature) -> Result<SecretKey> {
|
pub fn recover(S: PublicKey, sig: Signature, encsig: EncryptedSignature) -> Result<SecretKey> {
|
||||||
|
Loading…
Reference in New Issue
Block a user