Skip to content

Commit

Permalink
Add time/hashlock privkey to WalletSwapCoin struct
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-belcher committed Jun 29, 2021
1 parent 0d235b3 commit 2e78e15
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 34 deletions.
34 changes: 32 additions & 2 deletions src/contracts.rs
Expand Up @@ -121,6 +121,18 @@ fn read_locktime_from_contract(redeemscript: &Script) -> Option<i64> {
}
}

pub fn read_hashlock_pubkey_from_contract(
redeemscript: &Script,
) -> Result<PublicKey, bitcoin::util::key::Error> {
PublicKey::from_slice(&redeemscript.to_bytes()[27..60])
}

pub fn read_timelock_pubkey_from_contract(
redeemscript: &Script,
) -> Result<PublicKey, bitcoin::util::key::Error> {
PublicKey::from_slice(&redeemscript.to_bytes()[65..98])
}

pub fn read_pubkeys_from_multisig_redeemscript(
redeemscript: &Script,
) -> Option<(PublicKey, PublicKey)> {
Expand Down Expand Up @@ -276,7 +288,8 @@ pub fn verify_proof_of_funding(
funding_info: &ConfirmedCoinSwapTxInfo,
funding_output_index: u32,
next_locktime: i64,
) -> Result<(SecretKey, PublicKey), Error> {
//returns my_multisig_privkey, other_multisig_pubkey, my_hashlock_privkey
) -> Result<(SecretKey, PublicKey, SecretKey), Error> {
//check the funding_tx exists and was really confirmed
if let Some(txout) =
rpc.get_tx_out(&funding_info.funding_tx.txid(), funding_output_index, None)?
Expand Down Expand Up @@ -329,6 +342,19 @@ pub fn verify_proof_of_funding(
return Err(Error::Protocol("locktime too short"));
}

//check that provided hashlock_key_nonce really corresponds to the hashlock_pubkey in contract
let contract_hashlock_pubkey =
read_hashlock_pubkey_from_contract(&funding_info.contract_redeemscript)
.map_err(|_| Error::Protocol("unable to read hashlock pubkey from contract"))?;
let derived_hashlock_pubkey =
calculate_maker_pubkey_from_nonce(tweakable_point, funding_info.hashlock_key_nonce)
.map_err(|_| Error::Protocol("unable to calculate maker pubkey from nonce"))?;
if contract_hashlock_pubkey != derived_hashlock_pubkey {
return Err(Error::Protocol(
"contract hashlock pubkey doesnt match key derived from nonce",
));
}

//check that the provided contract matches the scriptpubkey from the
//cache which was populated when the signsendercontracttx message arrived
let contract_spk = Address::p2wsh(&funding_info.contract_redeemscript, NETWORK).script_pubkey();
Expand All @@ -349,13 +375,17 @@ pub fn verify_proof_of_funding(
my_privkey
.add_assign(funding_info.multisig_key_nonce.as_ref())
.map_err(|_| Error::Protocol("error with wallet tweakable privkey + nonce"))?;
let mut hashlock_privkey = tweakable_privkey;
hashlock_privkey
.add_assign(funding_info.hashlock_key_nonce.as_ref())
.map_err(|_| Error::Protocol("error with wallet tweakable privkey + nonce"))?;

let other_pubkey = if pubkey1 == my_pubkey {
pubkey2
} else {
pubkey1
};
Ok((my_privkey, other_pubkey))
Ok((my_privkey, other_pubkey, hashlock_privkey))
}

pub fn validate_contract_tx(
Expand Down
7 changes: 4 additions & 3 deletions src/maker_protocol.rs
Expand Up @@ -314,7 +314,7 @@ fn handle_proof_of_funding(
) -> Result<Option<MakerToTakerMessage>, Error> {
let mut funding_output_indexes = Vec::<u32>::new();
let mut funding_outputs = Vec::<&TxOut>::new();
let mut incoming_swapcoin_keys = Vec::<(SecretKey, PublicKey)>::new();
let mut incoming_swapcoin_keys = Vec::<(SecretKey, PublicKey, SecretKey)>::new();
if proof.confirmed_funding_txes.len() == 0 {
return Err(Error::Protocol("zero funding txes provided"));
}
Expand Down Expand Up @@ -391,7 +391,7 @@ fn handle_proof_of_funding(
funding_output.value,
&funding_info.contract_redeemscript,
);
let (coin_privkey, coin_other_pubkey) = incoming_swapcoin_keys;
let (coin_privkey, coin_other_pubkey, hashlock_privkey) = incoming_swapcoin_keys;
println!(
"adding incoming_swapcoin contract_tx = {:?} fo = {:?}",
my_receivers_contract_tx.clone(),
Expand All @@ -406,6 +406,7 @@ fn handle_proof_of_funding(
coin_other_pubkey,
my_receivers_contract_tx.clone(),
funding_info.contract_redeemscript.clone(),
hashlock_privkey,
funding_output.value,
));
}
Expand All @@ -416,7 +417,7 @@ fn handle_proof_of_funding(
println!("incoming amount = {}", incoming_amount);
let amount = incoming_amount - coinswap_fees;

let (my_funding_txes, outgoing_swapcoins, timelock_pubkeys, _timelock_privkeys) =
let (my_funding_txes, outgoing_swapcoins, timelock_pubkeys) =
wallet.write().unwrap().initalize_coinswap(
&rpc,
amount,
Expand Down
26 changes: 15 additions & 11 deletions src/taker_protocol.rs
Expand Up @@ -85,17 +85,16 @@ async fn send_coinswap(
mut this_maker_hashlock_privkeys,
) = generate_maker_multisig_and_hashlock_keys(&first_maker.offer.tweakable_point, my_tx_count);

let (my_funding_txes, mut outgoing_swapcoins, my_timelock_pubkeys, _my_timelock_privkeys) =
wallet
.initalize_coinswap(
rpc,
amount,
&first_maker_multisig_pubkeys,
&first_maker_hashlock_pubkeys,
hashvalue,
first_swap_locktime,
)
.unwrap();
let (my_funding_txes, mut outgoing_swapcoins, my_timelock_pubkeys) = wallet
.initalize_coinswap(
rpc,
amount,
&first_maker_multisig_pubkeys,
&first_maker_hashlock_pubkeys,
hashvalue,
first_swap_locktime,
)
.unwrap();

let first_maker_senders_contract_sigs = request_senders_contract_tx_signatures(
&first_maker.address,
Expand Down Expand Up @@ -258,6 +257,7 @@ async fn send_coinswap(
&maker_sign_sender_and_receiver_contracts,
&funding_txes,
&next_swap_contract_redeemscripts,
&next_peer_hashlock_keys_or_nonces,
&next_peer_multisig_pubkeys,
&next_peer_multisig_keys_or_nonces,
preimage,
Expand Down Expand Up @@ -890,6 +890,7 @@ fn create_incoming_swapcoins(
maker_sign_sender_and_receiver_contracts: &SignSendersAndReceiversContractTxes,
funding_txes: &[Transaction],
next_swap_contract_redeemscripts: &[Script],
next_peer_hashlock_keys_or_nonces: &[SecretKey],
next_peer_multisig_pubkeys: &[PublicKey],
next_peer_multisig_keys_or_nonces: &[SecretKey],
preimage: [u8; 32],
Expand Down Expand Up @@ -941,13 +942,15 @@ fn create_incoming_swapcoins(
&maker_funded_multisig_privkey,
my_receivers_contract_tx,
next_contract_redeemscript,
&hashlock_privkey,
&maker_funding_tx_value,
) in izip!(
next_swap_multisig_redeemscripts.iter(),
next_peer_multisig_pubkeys.iter(),
next_peer_multisig_keys_or_nonces.iter(),
my_receivers_contract_txes.iter(),
next_swap_contract_redeemscripts.iter(),
next_peer_hashlock_keys_or_nonces.iter(),
last_makers_funding_tx_values.iter(),
) {
let (o_ms_pubkey1, o_ms_pubkey2) =
Expand All @@ -967,6 +970,7 @@ fn create_incoming_swapcoins(
maker_funded_other_multisig_pubkey,
my_receivers_contract_tx.clone(),
next_contract_redeemscript.clone(),
hashlock_privkey,
maker_funding_tx_value,
);
incoming_swapcoin.hash_preimage = Some(preimage);
Expand Down
39 changes: 21 additions & 18 deletions src/wallet_sync.rs
Expand Up @@ -93,25 +93,42 @@ pub struct WalletSwapCoin {
pub other_privkey: Option<SecretKey>,
pub contract_tx: Transaction,
pub contract_redeemscript: Script,
//either timelock_privkey for outgoing swapcoins or hashlock_privkey for incoming swapcoins
pub contract_privkey: SecretKey,
pub funding_amount: u64,
pub others_contract_sig: Option<Signature>,
pub hash_preimage: Option<[u8; 32]>,
}
//TODO split WalletSwapCoin into two structs, IncomingSwapCoin and OutgoingSwapCoin
//where Incoming has hashlock_privkey and Outgoing has timelock_privkey
//that is a much more rustic way of doing things, which uses the compiler to check for some bugs

impl WalletSwapCoin {
pub fn new(
my_privkey: SecretKey,
other_pubkey: PublicKey,
contract_tx: Transaction,
contract_redeemscript: Script,
contract_privkey: SecretKey,
funding_amount: u64,
) -> WalletSwapCoin {
let secp = Secp256k1::new();
let contract_pubkey = PublicKey {
compressed: true,
key: secp256k1::PublicKey::from_secret_key(&secp, &contract_privkey),
};
assert!(contract_pubkey ==
contracts::read_hashlock_pubkey_from_contract(&contract_redeemscript).unwrap() ||
contract_pubkey ==
contracts::read_timelock_pubkey_from_contract(&contract_redeemscript).unwrap()
);
WalletSwapCoin {
my_privkey,
other_pubkey,
other_privkey: None,
contract_tx,
contract_redeemscript,
contract_privkey,
funding_amount,
others_contract_sig: None,
hash_preimage: None,
Expand Down Expand Up @@ -984,16 +1001,8 @@ impl Wallet {
other_multisig_pubkeys: &[PublicKey],
hashlock_pubkeys: &[PublicKey],
hashvalue: [u8; 20],
locktime: i64, //returns: funding_tx, swapcoin, timelock_pubkey, timelock_privkey
) -> Result<
(
Vec<Transaction>,
Vec<WalletSwapCoin>,
Vec<PublicKey>,
Vec<SecretKey>,
),
Error,
> {
locktime: i64, //returns: funding_txes, swapcoins, timelock_pubkeys
) -> Result<(Vec<Transaction>, Vec<WalletSwapCoin>, Vec<PublicKey>), Error> {
let (coinswap_addresses, my_multisig_privkeys): (Vec<_>, Vec<_>) = other_multisig_pubkeys
.iter()
.map(|other_key| self.create_and_import_coinswap_address(rpc, other_key))
Expand All @@ -1007,7 +1016,6 @@ impl Wallet {
// an integer but also can be Sweep

let mut timelock_pubkeys = Vec::<PublicKey>::new();
let mut timelock_privkeys = Vec::<SecretKey>::new();
let mut outgoing_swapcoins = Vec::<WalletSwapCoin>::new();

for (
Expand Down Expand Up @@ -1042,22 +1050,17 @@ impl Wallet {
);

timelock_pubkeys.push(timelock_pubkey);
timelock_privkeys.push(timelock_privkey);
outgoing_swapcoins.push(WalletSwapCoin::new(
my_multisig_privkey,
other_multisig_pubkey,
my_senders_contract_tx,
contract_redeemscript,
timelock_privkey,
funding_amount,
));
}

Ok((
my_funding_txes,
outgoing_swapcoins,
timelock_pubkeys,
timelock_privkeys,
))
Ok((my_funding_txes, outgoing_swapcoins, timelock_pubkeys))
}
}

Expand Down

0 comments on commit 2e78e15

Please sign in to comment.