use bitcoin::{secp256k1, Sequence, Witness, Txid};
use crate::util::transaction_utils;
-use crate::util::crypto::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
+use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs};
use crate::chain::transaction::OutPoint;
use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
use crate::offers::invoice_request::UnsignedInvoiceRequest;
use crate::prelude::*;
-use core::convert::TryInto;
use core::ops::Deref;
use core::sync::atomic::{AtomicUsize, Ordering};
#[cfg(taproot)]
#[cfg(taproot)]
use crate::sign::taproot::TaprootChannelSigner;
use crate::util::atomic_counter::AtomicCounter;
-use crate::util::chacha20::ChaCha20;
+use crate::crypto::chacha20::ChaCha20;
use crate::util::invoice::construct_invoice_preimage;
pub(crate) mod type_resolver;
pub fn witness_script(&self) -> Option<ScriptBuf> {
self.channel_transaction_parameters.as_ref()
.and_then(|channel_params|
- if channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx() {
+ if channel_params.supports_anchors() {
let payment_point = channel_params.holder_pubkeys.payment_point;
Some(chan_utils::get_to_countersignatory_with_anchors_redeemscript(&payment_point))
} else {
/// Note: If you have the grind_signatures feature enabled, this will be at least 1 byte
/// shorter.
pub fn max_witness_length(&self) -> u64 {
- if self.channel_transaction_parameters.as_ref()
- .map(|channel_params| channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx())
- .unwrap_or(false)
+ if self.channel_transaction_parameters.as_ref().map_or(false, |p| p.supports_anchors())
{
let witness_script_weight = 1 /* pubkey push */ + 33 /* pubkey */ +
1 /* OP_CHECKSIGVERIFY */ + 1 /* OP_1 */ + 1 /* OP_CHECKSEQUENCEVERIFY */;
let mut input = Vec::with_capacity(descriptors.len());
let mut input_value = 0;
let mut witness_weight = 0;
- let mut output_set = HashSet::with_capacity(descriptors.len());
+ let mut output_set = hash_set_with_capacity(descriptors.len());
for outp in descriptors {
match outp {
SpendableOutputDescriptor::StaticPaymentOutput(descriptor) => {
if !output_set.insert(descriptor.outpoint) { return Err(()); }
let sequence =
if descriptor.channel_transaction_parameters.as_ref()
- .map(|channel_params| channel_params.channel_type_features.supports_anchors_zero_fee_htlc_tx())
- .unwrap_or(false)
+ .map_or(false, |p| p.supports_anchors())
{
Sequence::from_consensus(1)
} else {
});
witness_weight += descriptor.max_witness_length();
#[cfg(feature = "grind_signatures")]
- { witness_weight -= 1; } // Guarantees a low R signature
+ { // Guarantees a low R signature
+ witness_weight -= 1;
+ }
input_value += descriptor.output.value;
},
SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) => {
});
witness_weight += DelayedPaymentOutputDescriptor::MAX_WITNESS_LENGTH;
#[cfg(feature = "grind_signatures")]
- { witness_weight -= 1; } // Guarantees a low R signature
+ { // Guarantees a low R signature
+ witness_weight -= 1;
+ }
input_value += descriptor.output.value;
},
SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output, .. } => {
});
witness_weight += 1 + 73 + 34;
#[cfg(feature = "grind_signatures")]
- { witness_weight -= 1; } // Guarantees a low R signature
+ { // Guarantees a low R signature
+ witness_weight -= 1;
+ }
input_value += output.value;
}
}
fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()>;
}
+// Primarily needed in doctests because of https://github.com/rust-lang/rust/issues/67295
+/// A dynamic [`SignerProvider`] temporarily needed for doc tests.
+#[cfg(taproot)]
+#[doc(hidden)]
+#[deprecated(note = "Remove once taproot cfg is removed")]
+pub type DynSignerProvider = dyn SignerProvider<EcdsaSigner = InMemorySigner, TaprootSigner = InMemorySigner>;
+
+/// A dynamic [`SignerProvider`] temporarily needed for doc tests.
+#[cfg(not(taproot))]
+#[doc(hidden)]
+#[deprecated(note = "Remove once taproot cfg is removed")]
+pub type DynSignerProvider = dyn SignerProvider<EcdsaSigner = InMemorySigner>;
+
/// A trait that can return signer instances for individual channels.
pub trait SignerProvider {
/// A type which implements [`WriteableEcdsaChannelSigner`] which will be returned by [`Self::derive_channel_signer`].
channel_value_satoshis: u64,
/// Key derivation parameters.
channel_keys_id: [u8; 32],
- /// Seed from which all randomness produced is derived from.
- rand_bytes_unique_start: [u8; 32],
- /// Tracks the number of times we've produced randomness to ensure we don't return the same
- /// bytes twice.
- rand_bytes_index: AtomicCounter,
+ /// A source of random bytes.
+ entropy_source: RandomBytes,
}
impl PartialEq for InMemorySigner {
channel_parameters: self.channel_parameters.clone(),
channel_value_satoshis: self.channel_value_satoshis,
channel_keys_id: self.channel_keys_id,
- rand_bytes_unique_start: self.get_secure_random_bytes(),
- rand_bytes_index: AtomicCounter::new(),
+ entropy_source: RandomBytes::new(self.get_secure_random_bytes()),
}
}
}
holder_channel_pubkeys,
channel_parameters: None,
channel_keys_id,
- rand_bytes_unique_start,
- rand_bytes_index: AtomicCounter::new(),
+ entropy_source: RandomBytes::new(rand_bytes_unique_start),
}
}
impl EntropySource for InMemorySigner {
fn get_secure_random_bytes(&self) -> [u8; 32] {
- let index = self.rand_bytes_index.get_increment();
- let mut nonce = [0u8; 16];
- nonce[..8].copy_from_slice(&index.to_be_bytes());
- ChaCha20::get_single_block(&self.rand_bytes_unique_start, &nonce)
+ self.entropy_source.get_secure_random_bytes()
}
}
holder_channel_pubkeys,
channel_parameters: counterparty_channel_data,
channel_keys_id: keys_id,
- rand_bytes_unique_start: entropy_source.get_secure_random_bytes(),
- rand_bytes_index: AtomicCounter::new(),
+ entropy_source: RandomBytes::new(entropy_source.get_secure_random_bytes()),
})
}
}
channel_master_key: ExtendedPrivKey,
channel_child_index: AtomicUsize,
- rand_bytes_unique_start: [u8; 32],
- rand_bytes_index: AtomicCounter,
+ entropy_source: RandomBytes,
seed: [u8; 32],
starting_time_secs: u64,
channel_master_key,
channel_child_index: AtomicUsize::new(0),
- rand_bytes_unique_start,
- rand_bytes_index: AtomicCounter::new(),
+ entropy_source: RandomBytes::new(rand_bytes_unique_start),
seed: *seed,
starting_time_secs,
impl EntropySource for KeysManager {
fn get_secure_random_bytes(&self) -> [u8; 32] {
- let index = self.rand_bytes_index.get_increment();
- let mut nonce = [0u8; 16];
- nonce[..8].copy_from_slice(&index.to_be_bytes());
- ChaCha20::get_single_block(&self.rand_bytes_unique_start, &nonce)
+ self.entropy_source.get_secure_random_bytes()
}
}
}
}
+/// An implementation of [`EntropySource`] using ChaCha20.
+#[derive(Debug)]
+pub struct RandomBytes {
+ /// Seed from which all randomness produced is derived from.
+ seed: [u8; 32],
+ /// Tracks the number of times we've produced randomness to ensure we don't return the same
+ /// bytes twice.
+ index: AtomicCounter,
+}
+
+impl RandomBytes {
+ /// Creates a new instance using the given seed.
+ pub fn new(seed: [u8; 32]) -> Self {
+ Self {
+ seed,
+ index: AtomicCounter::new(),
+ }
+ }
+}
+
+impl EntropySource for RandomBytes {
+ fn get_secure_random_bytes(&self) -> [u8; 32] {
+ let index = self.index.get_increment();
+ let mut nonce = [0u8; 16];
+ nonce[..8].copy_from_slice(&index.to_be_bytes());
+ ChaCha20::get_single_block(&self.seed, &nonce)
+ }
+}
+
// Ensure that EcdsaChannelSigner can have a vtable
#[test]
pub fn dyn_sign() {