Skip to content

Commit

Permalink
fixup: Restrict trait functions
Browse files Browse the repository at this point in the history
Restrict trait functions to enforce contextual rules for Incoming,
Outgoing, and WatchOnly swapcoins types
  • Loading branch information
GeneFerneau committed Aug 2, 2021
1 parent 3b8ef60 commit 06b00be
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 164 deletions.
174 changes: 106 additions & 68 deletions src/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,12 @@ pub trait SwapCoin {
fn get_multisig_redeemscript(&self) -> Script;
fn get_contract_tx(&self) -> Transaction;
fn get_contract_redeemscript(&self) -> Script;
fn get_other_privkey(&self) -> Option<&SecretKey>;
fn get_contract_privkey(&self) -> Option<&SecretKey>;
fn get_hash_preimage(&self) -> Option<&[u8; 32]>;
fn get_funding_amount(&self) -> u64;
fn verify_contract_tx_receiver_sig(&self, sig: &Signature) -> bool;
fn verify_contract_tx_sender_sig(&self, sig: &Signature) -> bool;
fn apply_privkey(&mut self, privkey: SecretKey) -> Result<(), Error>;
fn contract_type(&self) -> &str;
fn is_known(&self) -> bool;
}

pub fn calculate_maker_pubkey_from_nonce(
Expand Down Expand Up @@ -459,70 +458,113 @@ fn verify_contract_tx_sig(
secp.verify(&sighash, sig, &pubkey.key).is_ok()
}

macro_rules! impl_swapcoin {
($coin:ident) => {
impl SwapCoin for $coin {
fn get_multisig_redeemscript(&self) -> Script {
let secp = Secp256k1::new();
create_multisig_redeemscript(
&self.other_pubkey,
&PublicKey {
compressed: true,
key: secp256k1::PublicKey::from_secret_key(&secp, &self.my_privkey),
},
)
}
impl SwapCoin for IncomingSwapCoin {
fn get_multisig_redeemscript(&self) -> Script {
let secp = Secp256k1::new();
create_multisig_redeemscript(
&self.other_pubkey,
&PublicKey {
compressed: true,
key: secp256k1::PublicKey::from_secret_key(&secp, &self.my_privkey),
},
)
}

fn get_contract_tx(&self) -> Transaction {
self.contract_tx.clone()
}
fn get_contract_tx(&self) -> Transaction {
self.contract_tx.clone()
}

fn get_contract_redeemscript(&self) -> Script {
self.contract_redeemscript.clone()
}
fn get_contract_redeemscript(&self) -> Script {
self.contract_redeemscript.clone()
}

fn get_other_privkey(&self) -> Option<&SecretKey> {
self.other_privkey.as_ref()
}
fn get_funding_amount(&self) -> u64 {
self.funding_amount
}

fn get_contract_privkey(&self) -> Option<&SecretKey> {
Some(self.get_lock_privkey())
}
fn verify_contract_tx_receiver_sig(&self, sig: &Signature) -> bool {
self.verify_contract_tx_sig(sig)
}

fn get_hash_preimage(&self) -> Option<&[u8; 32]> {
self.hash_preimage.as_ref()
}
fn verify_contract_tx_sender_sig(&self, sig: &Signature) -> bool {
self.verify_contract_tx_sig(sig)
}

fn get_funding_amount(&self) -> u64 {
self.funding_amount
}
fn apply_privkey(&mut self, privkey: SecretKey) -> Result<(), Error> {
let secp = Secp256k1::new();
let pubkey = PublicKey {
compressed: true,
key: secp256k1::PublicKey::from_secret_key(&secp, &privkey),
};
if pubkey != self.other_pubkey {
return Err(Error::Protocol("not correct privkey"));
}
self.other_privkey = Some(privkey);
Ok(())
}

fn verify_contract_tx_receiver_sig(&self, sig: &Signature) -> bool {
self.verify_contract_tx_sig(sig)
}
fn contract_type(&self) -> &str {
self.type_string()
}

fn verify_contract_tx_sender_sig(&self, sig: &Signature) -> bool {
self.verify_contract_tx_sig(sig)
}
fn is_known(&self) -> bool {
self.contract_privkey_is_known()
}
}

fn apply_privkey(&mut self, privkey: SecretKey) -> Result<(), Error> {
let secp = Secp256k1::new();
let pubkey = PublicKey {
compressed: true,
key: secp256k1::PublicKey::from_secret_key(&secp, &privkey),
};
if pubkey != self.other_pubkey {
return Err(Error::Protocol("not correct privkey"));
}
self.other_privkey = Some(privkey);
Ok(())
}
impl SwapCoin for OutgoingSwapCoin {
fn get_multisig_redeemscript(&self) -> Script {
let secp = Secp256k1::new();
create_multisig_redeemscript(
&self.other_pubkey,
&PublicKey {
compressed: true,
key: secp256k1::PublicKey::from_secret_key(&secp, &self.my_privkey),
},
)
}

fn get_contract_tx(&self) -> Transaction {
self.contract_tx.clone()
}

fn get_contract_redeemscript(&self) -> Script {
self.contract_redeemscript.clone()
}

fn get_funding_amount(&self) -> u64 {
self.funding_amount
}

fn verify_contract_tx_receiver_sig(&self, sig: &Signature) -> bool {
self.verify_contract_tx_sig(sig)
}

fn verify_contract_tx_sender_sig(&self, sig: &Signature) -> bool {
self.verify_contract_tx_sig(sig)
}

fn apply_privkey(&mut self, privkey: SecretKey) -> Result<(), Error> {
let secp = Secp256k1::new();
let pubkey = PublicKey {
compressed: true,
key: secp256k1::PublicKey::from_secret_key(&secp, &privkey),
};
if pubkey == self.other_pubkey {
Ok(())
} else {
Err(Error::Protocol("not correct privkey"))
}
};
}
}

impl_swapcoin!(IncomingSwapCoin);
impl_swapcoin!(OutgoingSwapCoin);
fn contract_type(&self) -> &str {
self.type_string()
}

fn is_known(&self) -> bool {
self.contract_privkey_is_known()
}
}

macro_rules! sign_and_verify_contract {
($coin:ident) => {
Expand Down Expand Up @@ -571,18 +613,6 @@ impl SwapCoin for WatchOnlySwapCoin {
self.contract_redeemscript.clone()
}

fn get_other_privkey(&self) -> Option<&SecretKey> {
None
}

fn get_contract_privkey(&self) -> Option<&SecretKey> {
None
}

fn get_hash_preimage(&self) -> Option<&[u8; 32]> {
None
}

fn get_funding_amount(&self) -> u64 {
self.funding_amount
}
Expand Down Expand Up @@ -622,6 +652,14 @@ impl SwapCoin for WatchOnlySwapCoin {
Err(Error::Protocol("not correct privkey"))
}
}

fn contract_type(&self) -> &str {
"watchonly"
}

fn is_known(&self) -> bool {
false
}
}

impl WatchOnlySwapCoin {
Expand Down
32 changes: 3 additions & 29 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use std::path::PathBuf;
use std::sync::{Arc, RwLock};

use bitcoin::hashes::hex::ToHex;
use bitcoin::secp256k1::Secp256k1;
use bitcoin::util::key::PublicKey;
use bitcoin::Amount;
use bitcoin_wallet::mnemonic;
use bitcoincore_rpc::{Auth, Client, Error, RpcApi};
Expand All @@ -20,10 +18,7 @@ mod wallet_sync;
use wallet_sync::Wallet;

mod contracts;
use contracts::{
read_hashlock_pubkey_from_contract, read_locktime_from_contract,
read_timelock_pubkey_from_contract,
};
use contracts::read_locktime_from_contract;

mod error;
mod maker_protocol;
Expand Down Expand Up @@ -173,7 +168,6 @@ fn display_wallet_balance(wallet_file_name: &PathBuf, long_form: Option<bool>) {
println!("coin count = {}", utxo_count);
println!("total balance = {}", balance);

let secp = Secp256k1::new();
let incomplete_coinswaps = wallet.find_incomplete_coinswaps(&rpc).unwrap();
if incomplete_coinswaps.len() > 0 {
println!("= incomplete coinswaps =");
Expand All @@ -187,35 +181,15 @@ fn display_wallet_balance(wallet_file_name: &PathBuf, long_form: Option<bool>) {
);
for (utxo, swapcoin) in utxo_swapcoins {
let txid = utxo.txid.to_hex();
let contract_pubkey = PublicKey {
compressed: true,
key: bitcoin::secp256k1::PublicKey::from_secret_key(
&secp,
swapcoin.get_contract_privkey().unwrap(),
),
};
let type_string = if contract_pubkey
== read_hashlock_pubkey_from_contract(&swapcoin.get_contract_redeemscript())
.unwrap()
{
"hashlock"
} else {
assert_eq!(
contract_pubkey,
read_timelock_pubkey_from_contract(&swapcoin.get_contract_redeemscript())
.unwrap()
);
"timelock"
};

#[rustfmt::skip]
println!("{}{}{}:{} {:8} {:8} {:^15} {:<7} {}",
if long_form { &txid } else {&txid[0..6] },
if long_form { "" } else { ".." },
if long_form { &"" } else { &txid[58..64] },
utxo.vout,
type_string,
if swapcoin.get_hash_preimage().is_some() { "known" } else { "unknown" },
swapcoin.contract_type(),
if swapcoin.is_known() { "known" } else { "unknown" },
read_locktime_from_contract(&swapcoin.get_contract_redeemscript())
.expect("unable to read locktime from contract"),
utxo.confirmations,
Expand Down
Loading

0 comments on commit 06b00be

Please sign in to comment.