lightning 0.3.0-beta1

A Complete Bitcoin Lightning Library in Rust. Handles the core functionality of the Lightning Network, allowing clients to implement custom wallet, chain interactions, storage and network logic without enforcing a specific runtime.
Documentation
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::{Hash, HashEngine};
use bitcoin::secp256k1::{ecdsa::Signature, Message, Secp256k1, SecretKey, Signing};

use chacha20_poly1305::chacha20::{ChaCha20, Key, Nonce};

use crate::sign::EntropySource;

macro_rules! hkdf_extract_expand {
	($salt: expr, $ikm: expr) => {{
		let mut hmac = HmacEngine::<Sha256>::new($salt);
		hmac.input($ikm);
		let prk = Hmac::from_engine(hmac).to_byte_array();
		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&[1; 1]);
		let t1 = Hmac::from_engine(hmac).to_byte_array();
		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&t1);
		hmac.input(&[2; 1]);
		(t1, Hmac::from_engine(hmac).to_byte_array(), prk)
	}};
	($salt: expr, $ikm: expr, 2) => {{
		let (k1, k2, _) = hkdf_extract_expand!($salt, $ikm);
		(k1, k2)
	}};
	($salt: expr, $ikm: expr, 8) => {{
		let (k1, k2, prk) = hkdf_extract_expand!($salt, $ikm);

		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&k2);
		hmac.input(&[3; 1]);
		let k3 = Hmac::from_engine(hmac).to_byte_array();

		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&k3);
		hmac.input(&[4; 1]);
		let k4 = Hmac::from_engine(hmac).to_byte_array();

		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&k4);
		hmac.input(&[5; 1]);
		let k5 = Hmac::from_engine(hmac).to_byte_array();

		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&k5);
		hmac.input(&[6; 1]);
		let k6 = Hmac::from_engine(hmac).to_byte_array();

		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&k6);
		hmac.input(&[7; 1]);
		let k7 = Hmac::from_engine(hmac).to_byte_array();

		let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
		hmac.input(&k7);
		hmac.input(&[8; 1]);
		let k8 = Hmac::from_engine(hmac).to_byte_array();

		(k1, k2, k3, k4, k5, k6, k7, k8)
	}};
}

pub fn hkdf_extract_expand_twice(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
	hkdf_extract_expand!(salt, ikm, 2)
}

pub fn hkdf_extract_expand_8x(
	salt: &[u8], ikm: &[u8],
) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32]) {
	hkdf_extract_expand!(salt, ikm, 8)
}

#[inline]
pub fn sign<C: Signing>(ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey) -> Signature {
	#[cfg(feature = "grind_signatures")]
	let sig = ctx.sign_ecdsa_low_r(msg, sk);
	#[cfg(not(feature = "grind_signatures"))]
	let sig = ctx.sign_ecdsa(msg, sk);
	sig
}

#[inline]
#[allow(unused_variables)]
pub fn sign_with_aux_rand<C: Signing, ES: EntropySource>(
	ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey, entropy_source: &ES,
) -> Signature {
	#[cfg(feature = "grind_signatures")]
	let sig = loop {
		let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
		if sig.serialize_compact()[0] < 0x80 {
			break sig;
		}
	};
	#[cfg(all(not(feature = "grind_signatures"), not(ldk_test_vectors)))]
	let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
	#[cfg(all(not(feature = "grind_signatures"), ldk_test_vectors))]
	let sig = sign(ctx, msg, sk);
	sig
}

pub fn apply_chacha20(key: [u8; 32], nonce: [u8; 16], data: &mut [u8]) {
	ChaCha20::new_from_block(
		Key::new(key),
		Nonce::new(nonce[4..].try_into().unwrap()),
		u32::from_le_bytes(nonce[..4].try_into().unwrap()),
	)
	.apply_keystream(data);
}