use bitcoin::blockdata::script::{Script,Builder};
use bitcoin::blockdata::opcodes;
use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, SigHashType};
-use bitcoin::consensus::encode::{self, Decodable, Encodable};
+use bitcoin::consensus::encode::{Decodable, Encodable};
+use bitcoin::consensus::encode;
use bitcoin::util::bip143;
use bitcoin::hashes::{Hash, HashEngine};
// Various functions for key derivation and transaction creation for use within channels. Primarily
// used in Channel and ChannelMonitor.
-pub(super) fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] {
+/// Build the commitment secret from the seed and the commitment number
+pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] {
let mut res: [u8; 32] = commitment_seed.clone();
for i in 0..48 {
let bitpos = 47 - i;
}
}
-/// Derives a per-commitment-transaction private key (eg an htlc key or payment key) from the base
-/// private key for that type of key and the per_commitment_point (available in TxCreationKeys)
-pub(crate) fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
+/// Derives a per-commitment-transaction private key (eg an htlc key or delayed_payment key)
+/// from the base secret and the per_commitment_point.
+///
+/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
+/// generated (ie our own).
+pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
let mut sha = Sha256::engine();
sha.input(&per_commitment_point.serialize());
sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).serialize());
Ok(key)
}
-pub(super) fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
+/// Derives a per-commitment-transaction public key (eg an htlc key or a delayed_payment key)
+/// from the base point and the per_commitment_key. This is the public equivalent of
+/// derive_private_key - using only public keys to derive a public key instead of private keys.
+///
+/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
+/// generated (ie our own).
+pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
let mut sha = Sha256::engine();
sha.input(&per_commitment_point.serialize());
sha.input(&base_point.serialize());
base_point.combine(&hashkey)
}
-/// Derives a revocation key from its constituent parts.
+/// Derives a per-commitment-transaction revocation key from its constituent parts.
+///
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
Ok(part_a)
}
-pub(super) fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
+/// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
+/// the public equivalend of derive_private_revocation_key - using only public keys to derive a
+/// public key instead of private keys.
+///
+/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
+/// generated (ie our own).
+pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
let rev_append_commit_hash_key = {
let mut sha = Sha256::engine();
sha.input(&revocation_base_point.serialize());
/// on-chain channel lock-in 2-of-2 multisig output.
pub funding_pubkey: PublicKey,
/// The base point which is used (with derive_public_revocation_key) to derive per-commitment
- /// revocation keys. The per-commitment revocation private key is then revealed by the owner of
- /// a commitment transaction so that their counterparty can claim all available funds if they
- /// broadcast an old state.
+ /// revocation keys. This is combined with the per-commitment-secret generated by the
+ /// counterparty to create a secret which the counterparty can reveal to revoke previous
+ /// states.
pub revocation_basepoint: PublicKey,
/// The public key which receives our immediately spendable primary channel balance in
/// remote-broadcasted commitment transactions. This key is static across every commitment
}
}
-/// Gets the "to_local" output redeemscript, ie the script which is time-locked or spendable by
-/// the revocation key
-pub(super) fn get_revokeable_redeemscript(revocation_key: &PublicKey, to_self_delay: u16, delayed_payment_key: &PublicKey) -> Script {
+/// A script either spendable by the revocation
+/// key or the delayed_payment_key and satisfying the relative-locktime OP_CSV constrain.
+/// Encumbering a `to_local` output on a commitment transaction or 2nd-stage HTLC transactions.
+pub fn get_revokeable_redeemscript(revocation_key: &PublicKey, to_self_delay: u16, delayed_payment_key: &PublicKey) -> Script {
Builder::new().push_opcode(opcodes::all::OP_IF)
.push_slice(&revocation_key.serialize())
.push_opcode(opcodes::all::OP_ELSE)
}
/// panics if htlc.transaction_output_index.is_none()!
-pub fn build_htlc_transaction(prev_hash: &Txid, feerate_per_kw: u64, to_self_delay: u16, htlc: &HTLCOutputInCommitment, a_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction {
+pub fn build_htlc_transaction(prev_hash: &Txid, feerate_per_kw: u32, to_self_delay: u16, htlc: &HTLCOutputInCommitment, a_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction {
let mut txins: Vec<TxIn> = Vec::new();
txins.push(TxIn {
previous_output: OutPoint {
});
let total_fee = if htlc.offered {
- feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000
+ feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000
} else {
- feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000
+ feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000
};
let mut txouts: Vec<TxOut> = Vec::new();
#[derive(Clone)]
/// We use this to track local commitment transactions and put off signing them until we are ready
-/// to broadcast. Eventually this will require a signer which is possibly external, but for now we
-/// just pass in the SecretKeys required.
+/// to broadcast. This class can be used inside a signer implementation to generate a signature
+/// given the relevant secret key.
pub struct LocalCommitmentTransaction {
// TODO: We should migrate away from providing the transaction, instead providing enough to
// allow the ChannelKeys to construct it from scratch. Luckily we already have HTLC data here,
pub local_keys: TxCreationKeys,
/// The feerate paid per 1000-weight-unit in this commitment transaction. This value is
/// controlled by the channel initiator.
- pub feerate_per_kw: u64,
+ pub feerate_per_kw: u32,
/// The HTLCs and remote htlc signatures which were included in this commitment transaction.
///
/// Note that this includes all HTLCs, including ones which were considered dust and not
/// Generate a new LocalCommitmentTransaction based on a raw commitment transaction,
/// remote signature and both parties keys
- pub(crate) fn new_missing_local_sig(unsigned_tx: Transaction, their_sig: Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey, local_keys: TxCreationKeys, feerate_per_kw: u64, htlc_data: Vec<(HTLCOutputInCommitment, Option<Signature>)>) -> LocalCommitmentTransaction {
+ pub(crate) fn new_missing_local_sig(unsigned_tx: Transaction, their_sig: Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey, local_keys: TxCreationKeys, feerate_per_kw: u32, htlc_data: Vec<(HTLCOutputInCommitment, Option<Signature>)>) -> LocalCommitmentTransaction {
if unsigned_tx.input.len() != 1 { panic!("Tried to store a commitment transaction that had input count != 1!"); }
if unsigned_tx.input[0].witness.len() != 0 { panic!("Tried to store a signed commitment transaction?"); }