-
Notifications
You must be signed in to change notification settings - Fork 407
Move spendable output descriptors key behind signer interface #562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
ariard
wants to merge
10
commits into
lightningdevkit:master
from
ariard:2020-03-remove-seckey-chanmon
Closed
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
3244e41
Cache remote basepoint and remote_csv in new OnchainTxHandler::Remote…
3caa38f
Cache remote HTLC inside OnchainTxHandler::RemoteTxCache
ea8df9d
Replace is_htlc in InputMaterial by InputDescriptor
b082827
Build witness_script for justice tx inside OnchainTxHandler
bb5b14c
Move justice transaction signature behind ChanSigner
d2a6a78
Build witness_script for remote htlc transactions inside
5a8f68f
Move remote htlc transaction signature behind ChanSigner
4fd727f
Add test-only ChannelMonitor::get_chan_signer to sign spendable output
13a6604
Remove SecretKey from DynamicOutputP2WSH descriptor
7a23c0c
Remove SecretKey from DynamicOuputP2WPKH descriptor
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,11 +2,12 @@ | |
//! spendable on-chain outputs which the user owns and is responsible for using just as any other | ||
//! on-chain output which is theirs. | ||
|
||
use bitcoin::blockdata::transaction::{Transaction, OutPoint, TxOut}; | ||
use bitcoin::blockdata::transaction::{Transaction, OutPoint, TxOut, SigHashType}; | ||
use bitcoin::blockdata::script::{Script, Builder}; | ||
use bitcoin::blockdata::opcodes; | ||
use bitcoin::network::constants::Network; | ||
use bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber}; | ||
use bitcoin::util::address::Address; | ||
use bitcoin::util::bip143; | ||
|
||
use bitcoin_hashes::{Hash, HashEngine}; | ||
|
@@ -26,6 +27,7 @@ use util::ser::{Writeable, Writer, Readable}; | |
use ln::chan_utils; | ||
use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction}; | ||
use ln::msgs; | ||
use ln::channelmanager::PaymentPreimage; | ||
|
||
use std::sync::Arc; | ||
use std::sync::atomic::{AtomicUsize, Ordering}; | ||
|
@@ -64,8 +66,8 @@ pub enum SpendableOutputDescriptor { | |
DynamicOutputP2WSH { | ||
/// The outpoint which is spendable | ||
outpoint: OutPoint, | ||
/// The secret key which must be used to sign the spending transaction | ||
key: SecretKey, | ||
/// Per commitment point to derive delayed_payment_key by key holder | ||
per_commitment_point: PublicKey, | ||
/// The witness redeemScript which is hashed to create the script_pubkey in the given output | ||
witness_script: Script, | ||
/// The nSequence value which must be set in the spending input to satisfy the OP_CSV in | ||
|
@@ -83,7 +85,7 @@ pub enum SpendableOutputDescriptor { | |
/// The outpoint which is spendable | ||
outpoint: OutPoint, | ||
/// The secret key which must be used to sign the spending transaction | ||
key: SecretKey, | ||
per_commitment_point: PublicKey, | ||
/// The output which is reference by the given outpoint | ||
output: TxOut, | ||
} | ||
|
@@ -97,18 +99,18 @@ impl Writeable for SpendableOutputDescriptor { | |
outpoint.write(writer)?; | ||
output.write(writer)?; | ||
}, | ||
&SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref key, ref witness_script, ref to_self_delay, ref output } => { | ||
&SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref per_commitment_point, ref witness_script, ref to_self_delay, ref output } => { | ||
1u8.write(writer)?; | ||
outpoint.write(writer)?; | ||
key.write(writer)?; | ||
per_commitment_point.write(writer)?; | ||
witness_script.write(writer)?; | ||
to_self_delay.write(writer)?; | ||
output.write(writer)?; | ||
}, | ||
&SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => { | ||
&SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref per_commitment_point, ref output } => { | ||
2u8.write(writer)?; | ||
outpoint.write(writer)?; | ||
key.write(writer)?; | ||
per_commitment_point.write(writer)?; | ||
output.write(writer)?; | ||
}, | ||
} | ||
|
@@ -125,14 +127,14 @@ impl Readable for SpendableOutputDescriptor { | |
}), | ||
1u8 => Ok(SpendableOutputDescriptor::DynamicOutputP2WSH { | ||
outpoint: Readable::read(reader)?, | ||
key: Readable::read(reader)?, | ||
per_commitment_point: Readable::read(reader)?, | ||
witness_script: Readable::read(reader)?, | ||
to_self_delay: Readable::read(reader)?, | ||
output: Readable::read(reader)?, | ||
}), | ||
2u8 => Ok(SpendableOutputDescriptor::DynamicOutputP2WPKH { | ||
outpoint: Readable::read(reader)?, | ||
key: Readable::read(reader)?, | ||
per_commitment_point: Readable::read(reader)?, | ||
output: Readable::read(reader)?, | ||
}), | ||
_ => Err(DecodeError::InvalidValue), | ||
|
@@ -245,12 +247,24 @@ pub trait ChannelKeys : Send+Clone { | |
/// return value must contain a signature. | ||
fn sign_local_commitment_htlc_transactions<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, local_csv: u16, secp_ctx: &Secp256k1<T>) -> Result<Vec<Option<Signature>>, ()>; | ||
|
||
/// Signs a justice transaction. | ||
fn sign_justice_transaction<T: secp256k1::Signing>(&self, bumped_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_key: &SecretKey, revocation_pubkey: &PublicKey, is_htlc: bool, secp_ctx: &Secp256k1<T>); | ||
|
||
/// Signs a remote htlc transaction. | ||
fn sign_remote_htlc_transaction<T: secp256k1::Signing>(&self, bumped_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_point: &PublicKey, preimage: &Option<PaymentPreimage>, secp_ctx: &Secp256k1<T>); | ||
|
||
/// Create a signature for a (proposed) closing transaction. | ||
/// | ||
/// Note that, due to rounding, there may be one "missing" satoshi, and either party may have | ||
/// chosen to forgo their output as dust. | ||
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>; | ||
|
||
/// Create a signature for a delayed transaction. | ||
fn sign_delayed_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_point: &PublicKey, secp_ctx: &Secp256k1<T>); | ||
|
||
/// Create a signture for a payment transaction spending a to_remote output on a remote commitment tx. | ||
fn sign_payment_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, network: Network, secp_ctx: &Secp256k1<T>); | ||
|
||
/// Signs a channel announcement message with our funding key, proving it comes from one | ||
/// of the channel participants. | ||
/// | ||
|
@@ -393,6 +407,38 @@ impl ChannelKeys for InMemoryChannelKeys { | |
local_commitment_tx.get_htlc_sigs(&self.htlc_base_key, local_csv, secp_ctx) | ||
} | ||
|
||
fn sign_justice_transaction<T: secp256k1::Signing>(&self, bumped_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_key: &SecretKey, revocation_pubkey: &PublicKey, is_htlc: bool, secp_ctx: &Secp256k1<T>) { | ||
if let Ok(revocation_key) = chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key) { | ||
let sighash_parts = bip143::SighashComponents::new(&bumped_tx); | ||
let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[input], &witness_script, amount)[..]); | ||
let sig = secp_ctx.sign(&sighash, &revocation_key); | ||
bumped_tx.input[input].witness.push(sig.serialize_der().to_vec()); | ||
bumped_tx.input[input].witness[0].push(SigHashType::All as u8); | ||
if is_htlc { | ||
bumped_tx.input[input].witness.push(revocation_pubkey.clone().serialize().to_vec()); | ||
} else { | ||
bumped_tx.input[input].witness.push(vec!(1)); | ||
} | ||
bumped_tx.input[input].witness.push(witness_script.clone().into_bytes()); | ||
} | ||
} | ||
|
||
fn sign_remote_htlc_transaction<T: secp256k1::Signing>(&self, bumped_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_point: &PublicKey, preimage: &Option<PaymentPreimage>, secp_ctx: &Secp256k1<T>) { | ||
if let Ok(htlc_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.htlc_base_key) { | ||
let sighash_parts = bip143::SighashComponents::new(&bumped_tx); | ||
let sighash = hash_to_message!(&sighash_parts.sighash_all(&bumped_tx.input[input], &witness_script, amount)[..]); | ||
let sig = secp_ctx.sign(&sighash, &htlc_key); | ||
bumped_tx.input[input].witness.push(sig.serialize_der().to_vec()); | ||
bumped_tx.input[input].witness[0].push(SigHashType::All as u8); | ||
if let &Some(preimage) = preimage { | ||
bumped_tx.input[input].witness.push(preimage.0.to_vec()); | ||
} else { | ||
bumped_tx.input[input].witness.push(vec![0]); | ||
} | ||
bumped_tx.input[input].witness.push(witness_script.clone().into_bytes()); | ||
} | ||
} | ||
|
||
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> { | ||
if closing_tx.input.len() != 1 { return Err(()); } | ||
if closing_tx.input[0].witness.len() != 0 { return Err(()); } | ||
|
@@ -407,6 +453,31 @@ impl ChannelKeys for InMemoryChannelKeys { | |
Ok(secp_ctx.sign(&sighash, &self.funding_key)) | ||
} | ||
|
||
fn sign_delayed_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, witness_script: &Script, amount: u64, per_commitment_point: &PublicKey, secp_ctx: &Secp256k1<T>) { | ||
if let Ok(htlc_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.delayed_payment_base_key) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. failing here likely indicates a serious internal error, so should propagate the error to the caller |
||
let sighash_parts = bip143::SighashComponents::new(&spend_tx); | ||
let sighash = hash_to_message!(&sighash_parts.sighash_all(&spend_tx.input[input], witness_script, amount)[..]); | ||
let local_delaysig = secp_ctx.sign(&sighash, &htlc_key); | ||
spend_tx.input[0].witness.push(local_delaysig.serialize_der().to_vec()); | ||
spend_tx.input[0].witness[0].push(SigHashType::All as u8); | ||
spend_tx.input[0].witness.push(vec!(0)); | ||
spend_tx.input[0].witness.push(witness_script.clone().into_bytes()); | ||
} | ||
} | ||
|
||
fn sign_payment_transaction<T: secp256k1::Signing>(&self, spend_tx: &mut Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, network: Network, secp_ctx: &Secp256k1<T>) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see two comments on |
||
if let Ok(payment_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.payment_base_key) { | ||
let remotepubkey = PublicKey::from_secret_key(&secp_ctx, &payment_key); | ||
let witness_script = Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: remotepubkey}, network).script_pubkey(); | ||
let sighash_parts = bip143::SighashComponents::new(&spend_tx); | ||
let sighash = hash_to_message!(&sighash_parts.sighash_all(&spend_tx.input[input], &witness_script, amount)[..]); | ||
let remotesig = secp_ctx.sign(&sighash, &payment_key); | ||
spend_tx.input[0].witness.push(remotesig.serialize_der().to_vec()); | ||
spend_tx.input[0].witness[0].push(SigHashType::All as u8); | ||
spend_tx.input[0].witness.push(remotepubkey.serialize().to_vec()); | ||
} | ||
} | ||
|
||
fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> { | ||
let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]); | ||
Ok(secp_ctx.sign(&msghash, &self.funding_key)) | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the
witness_script
could be derived here rather than passed in, if I'm not mistaken