// licenses.
//! Various utilities for building scripts and deriving keys related to channels. These are
-//! largely of interest for those implementing chain::keysinterface::Sign message signing by hand.
+//! largely of interest for those implementing the traits on [`crate::sign`] by hand.
use bitcoin::blockdata::script::{Script,Builder};
use bitcoin::blockdata::opcodes;
use bitcoin::hashes::ripemd160::Hash as Ripemd160;
use bitcoin::hash_types::{Txid, PubkeyHash};
+use crate::sign::EntropySource;
use crate::ln::{PaymentHash, PaymentPreimage};
use crate::ln::msgs::DecodeError;
use crate::util::ser::{Readable, Writeable, Writer};
use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI};
use core::ops::Deref;
use crate::chain;
-use crate::util::crypto::sign;
+use crate::util::crypto::{sign, sign_with_aux_rand};
/// Maximum number of one-way in-flight HTLC (protocol-level value).
pub const MAX_HTLCS: u16 = 483;
});
/// One counterparty's public keys which do not change over the life of a channel.
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ChannelPublicKeys {
/// The public key which is used to sign all commitment transactions, as it appears in the
/// on-chain channel lock-in 2-of-2 multisig output.
let broadcaster_funding_key = broadcaster.serialize();
let countersignatory_funding_key = countersignatory.serialize();
+ make_funding_redeemscript_from_slices(&broadcaster_funding_key, &countersignatory_funding_key)
+}
+
+pub(crate) fn make_funding_redeemscript_from_slices(broadcaster_funding_key: &[u8], countersignatory_funding_key: &[u8]) -> Script {
let builder = Builder::new().push_opcode(opcodes::all::OP_PUSHNUM_2);
if broadcaster_funding_key[..] < countersignatory_funding_key[..] {
- builder.push_slice(&broadcaster_funding_key)
- .push_slice(&countersignatory_funding_key)
+ builder.push_slice(broadcaster_funding_key)
+ .push_slice(countersignatory_funding_key)
} else {
- builder.push_slice(&countersignatory_funding_key)
- .push_slice(&broadcaster_funding_key)
+ builder.push_slice(countersignatory_funding_key)
+ .push_slice(broadcaster_funding_key)
}.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script()
}
} else {
EcdsaSighashType::All
};
- let mut remote_sig = remote_sig.serialize_der().to_vec();
- remote_sig.push(remote_sighash_type as u8);
-
- let mut local_sig = local_sig.serialize_der().to_vec();
- local_sig.push(EcdsaSighashType::All as u8);
let mut witness = Witness::new();
// First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element.
witness.push(vec![]);
- witness.push(remote_sig);
- witness.push(local_sig);
+ witness.push_bitcoin_signature(&remote_sig.serialize_der(), remote_sighash_type);
+ witness.push_bitcoin_signature(&local_sig.serialize_der(), EcdsaSighashType::All);
if let Some(preimage) = preimage {
witness.push(preimage.0.to_vec());
} else {
/// Returns the witness required to satisfy and spend an anchor input.
pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness {
let anchor_redeem_script = chan_utils::get_anchor_redeemscript(funding_key);
- let mut funding_sig = funding_sig.serialize_der().to_vec();
- funding_sig.push(EcdsaSighashType::All as u8);
- Witness::from_vec(vec![funding_sig, anchor_redeem_script.to_bytes()])
+ let mut ret = Witness::new();
+ ret.push_bitcoin_signature(&funding_sig.serialize_der(), EcdsaSighashType::All);
+ ret.push(anchor_redeem_script.as_bytes());
+ ret
}
/// Per-channel data used to build transactions in conjunction with the per-commitment data (CommitmentTransaction).
///
/// Normally, this is converted to the broadcaster/countersignatory-organized DirectedChannelTransactionParameters
/// before use, via the as_holder_broadcastable and as_counterparty_broadcastable functions.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ChannelTransactionParameters {
/// Holder public keys
pub holder_pubkeys: ChannelPublicKeys,
}
/// Late-bound per-channel counterparty data used to build transactions.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CounterpartyChannelTransactionParameters {
/// Counter-party public keys
pub pubkeys: ChannelPublicKeys,
impl HolderCommitmentTransaction {
#[cfg(test)]
- pub fn dummy() -> Self {
+ pub fn dummy(htlcs: &mut Vec<(HTLCOutputInCommitment, ())>) -> Self {
let secp_ctx = Secp256k1::new();
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let dummy_sig = sign(&secp_ctx, &secp256k1::Message::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap());
opt_anchors: None,
opt_non_zero_fee_anchors: None,
};
- let mut htlcs_with_aux: Vec<(_, ())> = Vec::new();
- let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, false, dummy_key.clone(), dummy_key.clone(), keys, 0, &mut htlcs_with_aux, &channel_parameters.as_counterparty_broadcastable());
+ let mut counterparty_htlc_sigs = Vec::new();
+ for _ in 0..htlcs.len() {
+ counterparty_htlc_sigs.push(dummy_sig);
+ }
+ let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, false, dummy_key.clone(), dummy_key.clone(), keys, 0, htlcs, &channel_parameters.as_counterparty_broadcastable());
+ htlcs.sort_by_key(|htlc| htlc.0.transaction_output_index);
HolderCommitmentTransaction {
inner,
counterparty_sig: dummy_sig,
- counterparty_htlc_sigs: Vec::new(),
+ counterparty_htlc_sigs,
holder_sig_first: false
}
}
// First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element.
let mut tx = self.inner.built.transaction.clone();
tx.input[0].witness.push(Vec::new());
- let mut ser_holder_sig = holder_sig.serialize_der().to_vec();
- ser_holder_sig.push(EcdsaSighashType::All as u8);
- let mut ser_cp_sig = self.counterparty_sig.serialize_der().to_vec();
- ser_cp_sig.push(EcdsaSighashType::All as u8);
if self.holder_sig_first {
- tx.input[0].witness.push(ser_holder_sig);
- tx.input[0].witness.push(ser_cp_sig);
+ tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
+ tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
} else {
- tx.input[0].witness.push(ser_cp_sig);
- tx.input[0].witness.push(ser_holder_sig);
+ tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
+ tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
}
tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
hash_to_message!(sighash)
}
- /// Sign a transaction, either because we are counter-signing the counterparty's transaction or
- /// because we are about to broadcast a holder transaction.
- pub fn sign<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
+ /// Signs the counterparty's commitment transaction.
+ pub fn sign_counterparty_commitment<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
sign(secp_ctx, &sighash, funding_key)
}
+
+ /// Signs the holder commitment transaction because we are about to broadcast it.
+ pub fn sign_holder_commitment<T: secp256k1::Signing, ES: Deref>(
+ &self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64,
+ entropy_source: &ES, secp_ctx: &Secp256k1<T>
+ ) -> Signature where ES::Target: EntropySource {
+ let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
+ sign_with_aux_rand(secp_ctx, &sighash, funding_key, entropy_source)
+ }
}
/// This class tracks the per-transaction information needed to build a closing transaction and will
///
/// Only include HTLCs that are above the dust limit for the channel.
///
- /// (C-not exported) due to the generic though we likely should expose a version without
+ /// This is not exported to bindings users due to the generic though we likely should expose a version without
pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, opt_anchors: bool, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
// Sort outputs and populate output indices while keeping track of the auxiliary data
let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, opt_anchors, &broadcaster_funding_key, &countersignatory_funding_key).unwrap();
/// Use non-zero fee anchors
///
- /// (C-not exported) due to move, and also not likely to be useful for binding users
+ /// This is not exported to bindings users due to move, and also not likely to be useful for binding users
pub fn with_non_zero_fee_anchors(mut self) -> Self {
self.opt_non_zero_fee_anchors = Some(());
self
/// which were included in this commitment transaction in output order.
/// The transaction index is always populated.
///
- /// (C-not exported) as we cannot currently convert Vec references to/from C, though we should
+ /// This is not exported to bindings users as we cannot currently convert Vec references to/from C, though we should
/// expose a less effecient version which creates a Vec of references in the future.
pub fn htlcs(&self) -> &Vec<HTLCOutputInCommitment> {
&self.htlcs
/// The returned Vec has one entry for each HTLC, and in the same order.
///
/// This function is only valid in the holder commitment context, it always uses EcdsaSighashType::All.
- pub fn get_htlc_sigs<T: secp256k1::Signing>(&self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters, secp_ctx: &Secp256k1<T>) -> Result<Vec<Signature>, ()> {
+ pub fn get_htlc_sigs<T: secp256k1::Signing, ES: Deref>(
+ &self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters,
+ entropy_source: &ES, secp_ctx: &Secp256k1<T>,
+ ) -> Result<Vec<Signature>, ()> where ES::Target: EntropySource {
let inner = self.inner;
let keys = &inner.keys;
let txid = inner.built.txid;
let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key);
let sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).segwit_signature_hash(0, &htlc_redeemscript, this_htlc.amount_msat / 1000, EcdsaSighashType::All).unwrap()[..]);
- ret.push(sign(secp_ctx, &sighash, &holder_htlc_key));
+ ret.push(sign_with_aux_rand(secp_ctx, &sighash, &holder_htlc_key, entropy_source));
}
Ok(ret)
}
use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment};
use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1};
use crate::util::test_utils;
- use crate::chain::keysinterface::{KeysInterface, BaseSign};
+ use crate::sign::{ChannelSigner, SignerProvider};
use bitcoin::{Network, Txid};
use bitcoin::hashes::Hash;
use crate::ln::PaymentHash;