Avoid possible mix up between timelocks

Introduce new type to ensure no mix up happens when ordering the fields
in function calls.
pull/190/head
Franck Royer 3 years ago
parent 9a321a4f09
commit b8a84aa34b
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4

@ -1,6 +1,5 @@
pub mod wallet;
mod timelocks;
mod cancel;
mod lock;
mod punish;
@ -9,18 +8,18 @@ mod refund;
mod timelocks;
pub use crate::bitcoin::{
cancel::TxCancel,
cancel::{CancelTimelock, PunishTimelock, TxCancel},
lock::TxLock,
punish::TxPunish,
redeem::TxRedeem,
refund::TxRefund,
timelocks::Timelock,
timelocks::{BlockHeight, ExpiredTimelocks},
};
pub use ::bitcoin::{util::amount::Amount, Address, Network, Transaction, Txid};
pub use ecdsa_fun::{adaptor::EncryptedSignature, fun::Scalar, Signature};
pub use wallet::Wallet;
use crate::{bitcoin::timelocks::BlockHeight, execution_params::ExecutionParams};
use crate::execution_params::ExecutionParams;
use ::bitcoin::{
hashes::{hex::ToHex, Hash},
secp256k1,
@ -35,7 +34,6 @@ use rand::{CryptoRng, RngCore};
use serde::{Deserialize, Serialize};
use sha2::Sha256;
use std::str::FromStr;
use timelocks::ExpiredTimelocks;
// TODO: Configurable tx-fee (note: parties have to agree prior to swapping)
// Current reasoning:
@ -272,8 +270,8 @@ where
pub async fn current_epoch<W>(
bitcoin_wallet: &W,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
lock_tx_id: ::bitcoin::Txid,
) -> anyhow::Result<ExpiredTimelocks>
where
@ -296,7 +294,7 @@ where
pub async fn wait_for_cancel_timelock_to_expire<W>(
bitcoin_wallet: &W,
cancel_timelock: Timelock,
cancel_timelock: CancelTimelock,
lock_tx_id: ::bitcoin::Txid,
) -> Result<()>
where

@ -1,13 +1,57 @@
use crate::bitcoin::{
build_shared_output_descriptor,
timelocks::{CancelTimelock, Timelock},
Address, Amount, PublicKey, Transaction, TxLock, TX_FEE,
build_shared_output_descriptor, Address, Amount, BlockHeight, PublicKey, Transaction, TxLock,
TX_FEE,
};
use ::bitcoin::{util::bip143::SigHashCache, OutPoint, SigHash, SigHashType, TxIn, TxOut, Txid};
use anyhow::Result;
use ecdsa_fun::Signature;
use miniscript::{Descriptor, NullCtx};
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, ops::Add};
/// Represent a timelock, expressed in relative block height as defined in
/// [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki).
/// E.g. The timelock expires 10 blocks after the reference transaction is
/// mined.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)]
#[serde(transparent)]
pub struct CancelTimelock(u32);
impl CancelTimelock {
pub const fn new(number_of_blocks: u32) -> Self {
Self(number_of_blocks)
}
}
impl Add<CancelTimelock> for BlockHeight {
type Output = BlockHeight;
fn add(self, rhs: CancelTimelock) -> Self::Output {
self + rhs.0
}
}
/// Represent a timelock, expressed in relative block height as defined in
/// [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki).
/// E.g. The timelock expires 10 blocks after the reference transaction is
/// mined.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)]
#[serde(transparent)]
pub struct PunishTimelock(u32);
impl PunishTimelock {
pub const fn new(number_of_blocks: u32) -> Self {
Self(number_of_blocks)
}
}
impl Add<PunishTimelock> for BlockHeight {
type Output = BlockHeight;
fn add(self, rhs: PunishTimelock) -> Self::Output {
self + rhs.0
}
}
#[derive(Debug, Clone)]
pub struct TxCancel {
@ -28,7 +72,7 @@ impl TxCancel {
let tx_in = TxIn {
previous_output: tx_lock.as_outpoint(),
script_sig: Default::default(),
sequence: cancel_timelock.into(),
sequence: cancel_timelock.0,
witness: Vec::new(),
};
@ -110,14 +154,14 @@ impl TxCancel {
pub fn build_spend_transaction(
&self,
spend_address: &Address,
sequence: Option<Timelock>,
sequence: Option<PunishTimelock>,
) -> Transaction {
let previous_output = self.as_outpoint();
let tx_in = TxIn {
previous_output,
script_sig: Default::default(),
sequence: sequence.map(Into::into).unwrap_or(0xFFFF_FFFF),
sequence: sequence.map(|seq| seq.0).unwrap_or(0xFFFF_FFFF),
witness: Vec::new(),
};

@ -1,4 +1,4 @@
use crate::bitcoin::{timelocks::PunishTimelock, Address, PublicKey, Transaction, TxCancel};
use crate::bitcoin::{Address, PublicKey, PunishTimelock, Transaction, TxCancel};
use ::bitcoin::{util::bip143::SigHashCache, SigHash, SigHashType};
use anyhow::Result;
use ecdsa_fun::Signature;
@ -17,8 +17,7 @@ impl TxPunish {
punish_address: &Address,
punish_timelock: PunishTimelock,
) -> Self {
let tx_punish =
tx_cancel.build_spend_transaction(punish_address, Some(punish_timelock.into()));
let tx_punish = tx_cancel.build_spend_transaction(punish_address, Some(punish_timelock));
let digest = SigHashCache::new(&tx_punish).signature_hash(
0, // Only one input: cancel transaction

@ -1,26 +1,5 @@
use std::ops::Add;
use serde::{Deserialize, Serialize};
/// Represent a timelock, expressed in relative block height as defined in
/// [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki).
/// E.g. The timelock expires 10 blocks after the reference transaction is
/// mined.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq)]
#[serde(transparent)]
pub struct Timelock(u32);
impl Timelock {
pub const fn new(number_of_blocks: u32) -> Self {
Self(number_of_blocks)
}
}
impl From<Timelock> for u32 {
fn from(timelock: Timelock) -> Self {
timelock.0
}
}
use std::ops::Add;
/// Represent a block height, or block number, expressed in absolute block
/// count. E.g. The transaction was included in block #655123, 655123 block
@ -41,11 +20,11 @@ impl BlockHeight {
}
}
impl Add<Timelock> for BlockHeight {
impl Add<u32> for BlockHeight {
type Output = BlockHeight;
fn add(self, rhs: Timelock) -> Self::Output {
BlockHeight(self.0 + rhs.0)
fn add(self, rhs: u32) -> Self::Output {
BlockHeight(self.0 + rhs)
}
}

@ -1,4 +1,4 @@
use crate::bitcoin::Timelock;
use crate::bitcoin::{CancelTimelock, PunishTimelock};
use conquer_once::Lazy;
use std::time::Duration;
@ -8,8 +8,8 @@ pub struct ExecutionParams {
pub bitcoin_finality_confirmations: u32,
pub bitcoin_avg_block_time: Duration,
pub monero_finality_confirmations: u32,
pub bitcoin_cancel_timelock: Timelock,
pub bitcoin_punish_timelock: Timelock,
pub bitcoin_cancel_timelock: CancelTimelock,
pub bitcoin_punish_timelock: PunishTimelock,
}
pub trait GetExecutionParams {
@ -77,8 +77,8 @@ mod mainnet {
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 15;
// Set to 12 hours, arbitrary value to be reviewed properly
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(72);
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(72);
pub static BITCOIN_CANCEL_TIMELOCK: CancelTimelock = CancelTimelock::new(72);
pub static BITCOIN_PUNISH_TIMELOCK: PunishTimelock = PunishTimelock::new(72);
}
mod testnet {
@ -95,8 +95,8 @@ mod testnet {
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 5;
// This does not reflect recommended values for mainnet!
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(12);
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(6);
pub static BITCOIN_CANCEL_TIMELOCK: CancelTimelock = CancelTimelock::new(12);
pub static BITCOIN_PUNISH_TIMELOCK: PunishTimelock = PunishTimelock::new(6);
}
mod regtest {
@ -111,7 +111,7 @@ mod regtest {
pub static MONERO_FINALITY_CONFIRMATIONS: u32 = 1;
pub static BITCOIN_CANCEL_TIMELOCK: Timelock = Timelock::new(100);
pub static BITCOIN_CANCEL_TIMELOCK: CancelTimelock = CancelTimelock::new(100);
pub static BITCOIN_PUNISH_TIMELOCK: Timelock = Timelock::new(50);
pub static BITCOIN_PUNISH_TIMELOCK: PunishTimelock = PunishTimelock::new(50);
}

@ -1,10 +1,9 @@
use crate::{
bitcoin,
bitcoin::{
current_epoch,
timelocks::{ExpiredTimelocks, Timelock},
wait_for_cancel_timelock_to_expire, GetBlockHeight, TransactionBlockHeight, TxCancel,
TxRefund, WatchForRawTransaction,
current_epoch, wait_for_cancel_timelock_to_expire, CancelTimelock, ExpiredTimelocks,
GetBlockHeight, PunishTimelock, TransactionBlockHeight, TxCancel, TxRefund,
WatchForRawTransaction,
},
execution_params::ExecutionParams,
monero,
@ -90,8 +89,8 @@ pub struct State0 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
pub btc: bitcoin::Amount,
pub xmr: monero::Amount,
pub cancel_timelock: Timelock,
pub punish_timelock: Timelock,
pub cancel_timelock: CancelTimelock,
pub punish_timelock: PunishTimelock,
pub redeem_address: bitcoin::Address,
pub punish_address: bitcoin::Address,
}
@ -172,8 +171,8 @@ pub struct State1 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,
@ -225,8 +224,8 @@ pub struct State2 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,
@ -295,8 +294,8 @@ pub struct State3 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
pub btc: bitcoin::Amount,
pub xmr: monero::Amount,
pub cancel_timelock: Timelock,
pub punish_timelock: Timelock,
pub cancel_timelock: CancelTimelock,
pub punish_timelock: PunishTimelock,
pub refund_address: bitcoin::Address,
pub redeem_address: bitcoin::Address,
pub punish_address: bitcoin::Address,
@ -341,8 +340,8 @@ pub struct State4 {
S_b_bitcoin: bitcoin::PublicKey,
v: monero::PrivateViewKey,
xmr: monero::Amount,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,
@ -433,8 +432,8 @@ pub struct State5 {
S_b_monero: monero::PublicKey,
S_b_bitcoin: bitcoin::PublicKey,
v: monero::PrivateViewKey,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,
@ -483,8 +482,8 @@ pub struct State6 {
S_b_monero: monero::PublicKey,
S_b_bitcoin: bitcoin::PublicKey,
v: monero::PrivateViewKey,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,

@ -1,9 +1,8 @@
use crate::{
bitcoin,
bitcoin::{
poll_until_block_height_is_gte,
timelocks::{BlockHeight, Timelock},
BroadcastSignedTransaction, EncryptedSignature, GetBlockHeight, GetRawTransaction,
poll_until_block_height_is_gte, BlockHeight, BroadcastSignedTransaction, CancelTimelock,
EncryptedSignature, GetBlockHeight, GetRawTransaction, PunishTimelock,
TransactionBlockHeight, TxCancel, TxLock, TxRefund, WaitForTransactionFinality,
WatchForRawTransaction,
},
@ -151,7 +150,7 @@ pub async fn publish_cancel_transaction<W>(
tx_lock: TxLock,
a: bitcoin::SecretKey,
B: bitcoin::PublicKey,
cancel_timelock: Timelock,
cancel_timelock: CancelTimelock,
tx_cancel_sig_bob: bitcoin::Signature,
bitcoin_wallet: Arc<W>,
) -> Result<bitcoin::TxCancel>
@ -198,7 +197,7 @@ where
pub async fn wait_for_bitcoin_refund<W>(
tx_cancel: &TxCancel,
cancel_tx_height: BlockHeight,
punish_timelock: Timelock,
punish_timelock: PunishTimelock,
refund_address: &bitcoin::Address,
bitcoin_wallet: Arc<W>,
) -> Result<(bitcoin::TxRefund, Option<bitcoin::Transaction>)>
@ -250,9 +249,9 @@ pub fn extract_monero_private_key(
pub fn build_bitcoin_punish_transaction(
tx_lock: &TxLock,
cancel_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_address: &bitcoin::Address,
punish_timelock: Timelock,
punish_timelock: PunishTimelock,
tx_punish_sig_bob: bitcoin::Signature,
a: bitcoin::SecretKey,
B: bitcoin::PublicKey,

@ -3,7 +3,7 @@
use crate::{
bitcoin,
bitcoin::{
timelocks::ExpiredTimelocks, TransactionBlockHeight, WaitForTransactionFinality,
ExpiredTimelocks, TransactionBlockHeight, WaitForTransactionFinality,
WatchForRawTransaction,
},
database,

@ -1,5 +1,5 @@
use crate::{
bitcoin::{timelocks::ExpiredTimelocks, Txid, Wallet},
bitcoin::{ExpiredTimelocks, Txid, Wallet},
database::{Database, Swap},
protocol::bob::BobState,
};

@ -1,10 +1,9 @@
use crate::{
bitcoin::{
self, current_epoch,
timelocks::{ExpiredTimelocks, Timelock},
wait_for_cancel_timelock_to_expire, BroadcastSignedTransaction, BuildTxLockPsbt,
GetBlockHeight, GetNetwork, GetRawTransaction, Transaction, TransactionBlockHeight,
TxCancel, Txid, WatchForRawTransaction,
self, current_epoch, wait_for_cancel_timelock_to_expire, BroadcastSignedTransaction,
BuildTxLockPsbt, CancelTimelock, ExpiredTimelocks, GetBlockHeight, GetNetwork,
GetRawTransaction, PunishTimelock, Transaction, TransactionBlockHeight, TxCancel, Txid,
WatchForRawTransaction,
},
execution_params::ExecutionParams,
monero,
@ -82,8 +81,8 @@ pub struct State0 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
min_monero_confirmations: u32,
}
@ -93,8 +92,8 @@ impl State0 {
rng: &mut R,
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
min_monero_confirmations: u32,
) -> Self {
@ -177,8 +176,8 @@ pub struct State1 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,
@ -238,8 +237,8 @@ pub struct State2 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
pub xmr: monero::Amount,
pub cancel_timelock: Timelock,
pub punish_timelock: Timelock,
pub cancel_timelock: CancelTimelock,
pub punish_timelock: PunishTimelock,
pub refund_address: bitcoin::Address,
pub redeem_address: bitcoin::Address,
pub punish_address: bitcoin::Address,
@ -307,8 +306,8 @@ pub struct State3 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
pub cancel_timelock: Timelock,
punish_timelock: Timelock,
pub cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
pub refund_address: bitcoin::Address,
redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,
@ -427,8 +426,8 @@ pub struct State4 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
pub cancel_timelock: Timelock,
punish_timelock: Timelock,
pub cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
pub refund_address: bitcoin::Address,
pub redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,
@ -614,8 +613,8 @@ pub struct State5 {
#[serde(with = "::bitcoin::util::amount::serde::as_sat")]
btc: bitcoin::Amount,
xmr: monero::Amount,
cancel_timelock: Timelock,
punish_timelock: Timelock,
cancel_timelock: CancelTimelock,
punish_timelock: PunishTimelock,
refund_address: bitcoin::Address,
pub redeem_address: bitcoin::Address,
punish_address: bitcoin::Address,

@ -1,6 +1,6 @@
use crate::{
bitcoin,
bitcoin::timelocks::ExpiredTimelocks,
bitcoin::ExpiredTimelocks,
database::{Database, Swap},
execution_params::ExecutionParams,
monero,

@ -7,7 +7,7 @@ use monero_harness::{image, Monero};
use std::{path::PathBuf, sync::Arc};
use swap::{
bitcoin,
bitcoin::Timelock,
bitcoin::{CancelTimelock, PunishTimelock},
database::Database,
execution_params,
execution_params::{ExecutionParams, GetExecutionParams},
@ -484,7 +484,7 @@ pub struct SlowCancelConfig;
impl GetExecutionParams for SlowCancelConfig {
fn get_execution_params() -> ExecutionParams {
ExecutionParams {
bitcoin_cancel_timelock: Timelock::new(180),
bitcoin_cancel_timelock: CancelTimelock::new(180),
..execution_params::Regtest::get_execution_params()
}
}
@ -495,7 +495,7 @@ pub struct FastCancelConfig;
impl GetExecutionParams for FastCancelConfig {
fn get_execution_params() -> ExecutionParams {
ExecutionParams {
bitcoin_cancel_timelock: Timelock::new(1),
bitcoin_cancel_timelock: CancelTimelock::new(1),
..execution_params::Regtest::get_execution_params()
}
}
@ -506,8 +506,8 @@ pub struct FastPunishConfig;
impl GetExecutionParams for FastPunishConfig {
fn get_execution_params() -> ExecutionParams {
ExecutionParams {
bitcoin_cancel_timelock: Timelock::new(1),
bitcoin_punish_timelock: Timelock::new(1),
bitcoin_cancel_timelock: CancelTimelock::new(1),
bitcoin_punish_timelock: PunishTimelock::new(1),
..execution_params::Regtest::get_execution_params()
}
}

Loading…
Cancel
Save