Skip to content

Commit

Permalink
Add ability to spend timelocked contract UTXOs
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-belcher committed Jan 16, 2022
1 parent 8ecde48 commit 5056094
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
5 changes: 5 additions & 0 deletions src/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub trait SwapCoin {
fn get_contract_tx(&self) -> Transaction;
fn get_contract_redeemscript(&self) -> Script;
fn get_timelock_pubkey(&self) -> PublicKey;
fn get_timelock(&self) -> u16;
fn get_hashlock_pubkey(&self) -> PublicKey;
fn get_hashvalue(&self) -> Hash160;
fn get_funding_amount(&self) -> u64;
Expand Down Expand Up @@ -470,6 +471,10 @@ macro_rules! add_simple_swapcoin_get_functions {
read_timelock_pubkey_from_contract(&self.contract_redeemscript).unwrap()
}

fn get_timelock(&self) -> u16 {
read_locktime_from_contract(&self.contract_redeemscript).unwrap()
}

fn get_hashlock_pubkey(&self) -> PublicKey {
read_hashlock_pubkey_from_contract(&self.contract_redeemscript).unwrap()
}
Expand Down
15 changes: 14 additions & 1 deletion src/wallet_direct_send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use bitcoin::{Address, Amount, OutPoint, Script, Transaction, TxIn, TxOut};
use bitcoincore_rpc::json::ListUnspentResultEntry;
use bitcoincore_rpc::Client;

use crate::contracts::SwapCoin;
use crate::error::Error;
use crate::wallet_sync::{UTXOSpendInfo, Wallet, NETWORK};

Expand Down Expand Up @@ -139,9 +140,20 @@ impl Wallet {
}
}
};

let sequence = match spend_info {
UTXOSpendInfo::TimelockContract {
ref swapcoin_multisig_redeemscript,
input_value: _,
} => self
.find_outgoing_swapcoin(swapcoin_multisig_redeemscript)
.unwrap()
.get_timelock() as u32,
_ => 0,
};
tx_inputs.push(TxIn {
previous_output,
sequence: 0,
sequence,
witness: Vec::new(),
script_sig: Script::new(),
});
Expand All @@ -154,6 +166,7 @@ impl Wallet {
tx_inputs
);
}

let dest_addr = match destination {
Destination::Wallet => self.get_next_external_address(rpc)?,
Destination::Address(a) => a,
Expand Down
37 changes: 33 additions & 4 deletions src/wallet_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub enum UTXOSpendInfo {
},
TimelockContract {
swapcoin_multisig_redeemscript: Script,
input_value: u64,
},
}

Expand Down Expand Up @@ -269,6 +270,31 @@ impl OutgoingSwapCoin {
);
signed_contract_tx
}

fn sign_timelocked_transaction_input(
&self,
index: usize,
tx: &Transaction,
input: &mut TxIn,
input_value: u64,
) {
let secp = Secp256k1::new();
let sighash = secp256k1::Message::from_slice(
&SigHashCache::new(tx).signature_hash(
index,
&self.contract_redeemscript,
input_value,
SigHashType::All,
)[..],
)
.unwrap();

let sig_timelock = secp.sign(&sighash, &self.timelock_privkey);
input.witness.push(sig_timelock.serialize_der().to_vec());
input.witness[0].push(SigHashType::All as u8);
input.witness.push(Vec::new());
input.witness.push(self.contract_redeemscript.to_bytes());
}
}

pub trait WalletSwapCoin {
Expand Down Expand Up @@ -750,6 +776,7 @@ impl Wallet {
return if u.confirmations >= timelock.into() {
Some(UTXOSpendInfo::TimelockContract {
swapcoin_multisig_redeemscript: swapcoin.get_multisig_redeemscript(),
input_value: u.amount.as_sat(),
})
} else {
None
Expand Down Expand Up @@ -1094,10 +1121,12 @@ impl Wallet {
input.witness.push(pubkey.to_bytes());
}
UTXOSpendInfo::TimelockContract {
swapcoin_multisig_redeemscript: _,
} => {
panic!("not implemented yet");
}
swapcoin_multisig_redeemscript,
input_value,
} => self
.find_outgoing_swapcoin(&swapcoin_multisig_redeemscript)
.unwrap()
.sign_timelocked_transaction_input(ix, &tx_clone, &mut input, input_value),
}
}
}
Expand Down

0 comments on commit 5056094

Please sign in to comment.