use lightning::chain::channelmonitor::{ChannelMonitor, MonitorEvent};
use lightning::chain::transaction::OutPoint;
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
-use lightning::chain::keysinterface::{KeyMaterial, KeysInterface, InMemorySigner, Recipient};
+use lightning::chain::keysinterface::{KeyMaterial, KeysInterface, InMemorySigner, Recipient, EntropySource, NodeSigner, SignerProvider};
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::ln::channelmanager::{self, ChainParameters, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs, PaymentId};
use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
rand_bytes_id: atomic::AtomicU32,
enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
}
-impl KeysInterface for KeyProvider {
- type Signer = EnforcingSigner;
+impl EntropySource for KeyProvider {
+ fn get_secure_random_bytes(&self) -> [u8; 32] {
+ let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed);
+ let mut res = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, self.node_id];
+ res[30-4..30].copy_from_slice(&id.to_le_bytes());
+ res
+ }
+}
+
+impl NodeSigner for KeyProvider {
fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> {
Ok(SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_id]).unwrap())
}
+ fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
+ let secp_ctx = Secp256k1::signing_only();
+ Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+ }
+
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
let mut node_secret = self.get_node_secret(recipient)?;
if let Some(tweak) = tweak {
KeyMaterial([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_id])
}
- fn get_destination_script(&self) -> Script {
- let secp_ctx = Secp256k1::signing_only();
- let channel_monitor_claim_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, self.node_id]).unwrap();
- let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
- Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
+ fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
+ unreachable!()
}
+}
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
- let secp_ctx = Secp256k1::signing_only();
- let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap();
- let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize());
- ShutdownScript::new_p2wpkh(&pubkey_hash)
- }
+impl SignerProvider for KeyProvider {
+ type Signer = EnforcingSigner;
fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed) as u8;
EnforcingSigner::new_with_revoked(keys, revoked_commitment, false)
}
- fn get_secure_random_bytes(&self) -> [u8; 32] {
- let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed);
- let mut res = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, self.node_id];
- res[30-4..30].copy_from_slice(&id.to_le_bytes());
- res
- }
-
fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, DecodeError> {
let mut reader = std::io::Cursor::new(buffer);
})
}
- fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
- unreachable!()
+ fn get_destination_script(&self) -> Script {
+ let secp_ctx = Secp256k1::signing_only();
+ let channel_monitor_claim_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, self.node_id]).unwrap();
+ let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
+ Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
+ }
+
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
+ let secp_ctx = Secp256k1::signing_only();
+ let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap();
+ let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize());
+ ShutdownScript::new_p2wpkh(&pubkey_hash)
}
}
+impl KeysInterface for KeyProvider {}
+
impl KeyProvider {
fn make_enforcement_state_cell(&self, commitment_seed: [u8; 32]) -> Arc<Mutex<EnforcementState>> {
let mut revoked_commitments = self.enforcement_states.lock().unwrap();
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
use lightning::chain::chainmonitor;
use lightning::chain::transaction::OutPoint;
-use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface};
+use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, KeysInterface, EntropySource, NodeSigner, SignerProvider};
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentId};
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,IgnoringMessageHandler};
counter: AtomicU64,
signer_state: RefCell<HashMap<u8, (bool, Arc<Mutex<EnforcementState>>)>>
}
-impl KeysInterface for KeyProvider {
- type Signer = EnforcingSigner;
+impl EntropySource for KeyProvider {
+ fn get_secure_random_bytes(&self) -> [u8; 32] {
+ let ctr = self.counter.fetch_add(1, Ordering::Relaxed);
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8]
+ }
+}
+
+impl NodeSigner for KeyProvider {
fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> {
Ok(self.node_secret.clone())
}
+ fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
+ let secp_ctx = Secp256k1::signing_only();
+ Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+ }
+
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
let mut node_secret = self.get_node_secret(recipient)?;
if let Some(tweak) = tweak {
self.inbound_payment_key.clone()
}
- fn get_destination_script(&self) -> Script {
- let secp_ctx = Secp256k1::signing_only();
- let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap();
- let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
- Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
+ fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
+ unreachable!()
}
+}
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
- let secp_ctx = Secp256k1::signing_only();
- let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).unwrap();
- let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize());
- ShutdownScript::new_p2wpkh(&pubkey_hash)
- }
+impl SignerProvider for KeyProvider {
+ type Signer = EnforcingSigner;
fn generate_channel_keys_id(&self, inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8;
}, state, false)
}
- fn get_secure_random_bytes(&self) -> [u8; 32] {
- let ctr = self.counter.fetch_add(1, Ordering::Relaxed);
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8]
- }
-
fn read_chan_signer(&self, mut data: &[u8]) -> Result<EnforcingSigner, DecodeError> {
let inner: InMemorySigner = ReadableArgs::read(&mut data, self.node_secret.clone())?;
let state = Arc::new(Mutex::new(EnforcementState::new()));
))
}
- fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
- unreachable!()
+ fn get_destination_script(&self) -> Script {
+ let secp_ctx = Secp256k1::signing_only();
+ let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap();
+ let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
+ Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
+ }
+
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
+ let secp_ctx = Secp256k1::signing_only();
+ let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).unwrap();
+ let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize());
+ ShutdownScript::new_p2wpkh(&pubkey_hash)
}
}
+impl KeysInterface for KeyProvider {}
+
#[inline]
pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
let input = Arc::new(InputData {
// Imports that need to be added manually
use bitcoin::bech32::u5;
use bitcoin::blockdata::script::Script;
-use bitcoin::secp256k1::{PublicKey, Scalar, SecretKey};
+use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::RecoverableSignature;
-use lightning::chain::keysinterface::{Recipient, KeyMaterial, KeysInterface};
+use lightning::chain::keysinterface::{Recipient, KeyMaterial, KeysInterface, EntropySource, NodeSigner, SignerProvider};
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
use lightning::ln::script::ShutdownScript;
use lightning::util::enforcing_trait_impls::EnforcingSigner;
node_secret: SecretKey,
counter: AtomicU64,
}
-impl KeysInterface for KeyProvider {
- type Signer = EnforcingSigner;
+impl EntropySource for KeyProvider {
+ fn get_secure_random_bytes(&self) -> [u8; 32] {
+ let ctr = self.counter.fetch_add(1, Ordering::Relaxed);
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8]
+ }
+}
+
+impl NodeSigner for KeyProvider {
fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> {
Ok(self.node_secret.clone())
}
+ fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
+ let secp_ctx = Secp256k1::signing_only();
+ Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+ }
+
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
let mut node_secret = self.get_node_secret(recipient)?;
if let Some(tweak) = tweak {
fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!() }
- fn get_destination_script(&self) -> Script { unreachable!() }
+ fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
+ unreachable!()
+ }
+}
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!() }
+impl SignerProvider for KeyProvider {
+ type Signer = EnforcingSigner;
fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!() }
unreachable!()
}
- fn get_secure_random_bytes(&self) -> [u8; 32] {
- let ctr = self.counter.fetch_add(1, Ordering::Relaxed);
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- (ctr >> 8*7) as u8, (ctr >> 8*6) as u8, (ctr >> 8*5) as u8, (ctr >> 8*4) as u8, (ctr >> 8*3) as u8, (ctr >> 8*2) as u8, (ctr >> 8*1) as u8, 14, (ctr >> 8*0) as u8]
- }
-
fn read_chan_signer(&self, _data: &[u8]) -> Result<EnforcingSigner, DecodeError> { unreachable!() }
- fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> {
- unreachable!()
- }
+ fn get_destination_script(&self) -> Script { unreachable!() }
+
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!() }
}
+impl KeysInterface for KeyProvider {}
+
#[cfg(test)]
mod tests {
use lightning::util::logger::{Logger, Record};
use lightning::chain;
use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use lightning::chain::chainmonitor::{ChainMonitor, Persist};
-use lightning::chain::keysinterface::KeysInterface;
+use lightning::chain::keysinterface::{KeysInterface, SignerProvider};
use lightning::ln::channelmanager::ChannelManager;
use lightning::ln::msgs::{ChannelMessageHandler, OnionMessageHandler, RoutingMessageHandler};
use lightning::ln::peer_handler::{CustomMessageHandler, PeerManager, SocketDescriptor};
EventHandlerFuture: core::future::Future<Output = ()>,
EventHandler: Fn(Event) -> EventHandlerFuture,
PS: 'static + Deref + Send,
- M: 'static + Deref<Target = ChainMonitor<<K::Target as KeysInterface>::Signer, CF, T, F, L, P>> + Send + Sync,
+ M: 'static + Deref<Target = ChainMonitor<<K::Target as SignerProvider>::Signer, CF, T, F, L, P>> + Send + Sync,
CM: 'static + Deref<Target = ChannelManager<CW, T, K, F, L>> + Send + Sync,
PGS: 'static + Deref<Target = P2PGossipSync<G, CA, L>> + Send + Sync,
RGS: 'static + Deref<Target = RapidGossipSync<G, L>> + Send,
where
CA::Target: 'static + chain::Access,
CF::Target: 'static + chain::Filter,
- CW::Target: 'static + chain::Watch<<K::Target as KeysInterface>::Signer>,
+ CW::Target: 'static + chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: 'static + BroadcasterInterface,
K::Target: 'static + KeysInterface,
F::Target: 'static + FeeEstimator,
L::Target: 'static + Logger,
- P::Target: 'static + Persist<<K::Target as KeysInterface>::Signer>,
+ P::Target: 'static + Persist<<K::Target as SignerProvider>::Signer>,
CMH::Target: 'static + ChannelMessageHandler,
OMH::Target: 'static + OnionMessageHandler,
RMH::Target: 'static + RoutingMessageHandler,
RMH: 'static + Deref + Send + Sync,
EH: 'static + EventHandler + Send,
PS: 'static + Deref + Send,
- M: 'static + Deref<Target = ChainMonitor<<K::Target as KeysInterface>::Signer, CF, T, F, L, P>> + Send + Sync,
+ M: 'static + Deref<Target = ChainMonitor<<K::Target as SignerProvider>::Signer, CF, T, F, L, P>> + Send + Sync,
CM: 'static + Deref<Target = ChannelManager<CW, T, K, F, L>> + Send + Sync,
PGS: 'static + Deref<Target = P2PGossipSync<G, CA, L>> + Send + Sync,
RGS: 'static + Deref<Target = RapidGossipSync<G, L>> + Send,
where
CA::Target: 'static + chain::Access,
CF::Target: 'static + chain::Filter,
- CW::Target: 'static + chain::Watch<<K::Target as KeysInterface>::Signer>,
+ CW::Target: 'static + chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: 'static + BroadcasterInterface,
K::Target: 'static + KeysInterface,
F::Target: 'static + FeeEstimator,
L::Target: 'static + Logger,
- P::Target: 'static + Persist<<K::Target as KeysInterface>::Signer>,
+ P::Target: 'static + Persist<<K::Target as SignerProvider>::Signer>,
CMH::Target: 'static + ChannelMessageHandler,
OMH::Target: 'static + OnionMessageHandler,
RMH::Target: 'static + RoutingMessageHandler,
use bitcoin::network::constants::Network;
use lightning::chain::{BestBlock, Confirm, chainmonitor};
use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
- use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeysInterface, KeysManager};
+ use lightning::chain::keysinterface::{InMemorySigner, Recipient, EntropySource, KeysInterface, KeysManager, NodeSigner};
use lightning::chain::transaction::OutPoint;
use lightning::get_event_msg;
use lightning::ln::channelmanager::{self, BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager};
use bitcoin_hashes::Hash;
use lightning::chain;
use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
-use lightning::chain::keysinterface::{Recipient, KeysInterface};
+use lightning::chain::keysinterface::{Recipient, KeysInterface, NodeSigner, SignerProvider};
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, MIN_FINAL_CLTV_EXPIRY};
#[cfg(feature = "std")]
network: Currency, amt_msat: Option<u64>, description: String, invoice_expiry_delta_secs: u32
) -> Result<Invoice, SignOrCreationError<()>>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
invoice_expiry_delta_secs: u32
) -> Result<Invoice, SignOrCreationError<()>>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
) -> Result<Invoice, SignOrCreationError<()>>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
invoice_expiry_delta_secs: u32
) -> Result<Invoice, SignOrCreationError<()>>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
duration_since_epoch: Duration, invoice_expiry_delta_secs: u32
) -> Result<Invoice, SignOrCreationError<()>>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
invoice_expiry_delta_secs: u32, payment_hash: PaymentHash
) -> Result<Invoice, SignOrCreationError<()>>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
invoice_expiry_delta_secs: u32, payment_hash: PaymentHash, payment_secret: PaymentSecret
) -> Result<Invoice, SignOrCreationError<()>>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Payer for ChannelManager<M, T, K, F, L>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
use crate::{Currency, Description, InvoiceDescription};
use bitcoin_hashes::{Hash, sha256};
use bitcoin_hashes::sha256::Hash as Sha256;
- use lightning::chain::keysinterface::PhantomKeysManager;
+ use lightning::chain::keysinterface::{EntropySource, PhantomKeysManager};
use lightning::ln::{PaymentPreimage, PaymentHash};
use lightning::ln::channelmanager::{self, PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY, PaymentId};
use lightning::ln::functional_test_utils::*;
use bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::hashes::hex::FromHex;
use lightning::chain::channelmonitor::ChannelMonitor;
-use lightning::chain::keysinterface::KeysInterface;
+use lightning::chain::keysinterface::{KeysInterface, SignerProvider};
use lightning::util::ser::{ReadableArgs, Writeable};
use lightning::util::persist::KVStorePersister;
use std::fs;
/// Read `ChannelMonitor`s from disk.
pub fn read_channelmonitors<K: Deref> (
&self, keys_manager: K
- ) -> Result<Vec<(BlockHash, ChannelMonitor<<K::Target as KeysInterface>::Signer>)>, std::io::Error>
+ ) -> Result<Vec<(BlockHash, ChannelMonitor<<K::Target as SignerProvider>::Signer>)>, std::io::Error>
where K::Target: KeysInterface + Sized,
{
let mut path = PathBuf::from(&self.path_to_channel_data);
let contents = fs::read(&file.path())?;
let mut buffer = Cursor::new(&contents);
- match <(BlockHash, ChannelMonitor<<K::Target as KeysInterface>::Signer>)>::read(&mut buffer, &*keys_manager) {
+ match <(BlockHash, ChannelMonitor<<K::Target as SignerProvider>::Signer>)>::read(&mut buffer, &*keys_manager) {
Ok((blockhash, channel_monitor)) => {
if channel_monitor.get_funding_txo().0.txid != txid.unwrap() || channel_monitor.get_funding_txo().0.index != index.unwrap() {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "ChannelMonitor was stored in the wrong file"));
/// These may include outputs from a transaction punishing our counterparty or claiming an HTLC
/// on-chain using the payment preimage or after it has timed out.
///
- /// [`get_shutdown_scriptpubkey`]: KeysInterface::get_shutdown_scriptpubkey
- /// [`get_destination_script`]: KeysInterface::get_shutdown_scriptpubkey
+ /// [`get_shutdown_scriptpubkey`]: SignerProvider::get_shutdown_scriptpubkey
+ /// [`get_destination_script`]: SignerProvider::get_shutdown_scriptpubkey
StaticOutput {
/// The outpoint which is spendable.
outpoint: OutPoint,
///
/// This data is static, and will never change for a channel once set. For a given [`BaseSign`]
/// instance, LDK will call this method exactly once - either immediately after construction
- /// (not including if done via [`KeysInterface::read_chan_signer`]) or when the funding
+ /// (not including if done via [`SignerProvider::read_chan_signer`]) or when the funding
/// information has been generated.
///
/// channel_parameters.is_populated() MUST be true.
/// Specifies the recipient of an invoice.
///
-/// This indicates to [`KeysInterface::sign_invoice`] what node secret key should be used to sign
+/// This indicates to [`NodeSigner::sign_invoice`] what node secret key should be used to sign
/// the invoice.
pub enum Recipient {
/// The invoice should be signed with the local node secret key.
PhantomNode,
}
-/// A trait to describe an object which can get user secrets and key material.
-pub trait KeysInterface {
- /// A type which implements [`Sign`] which will be returned by [`Self::derive_channel_signer`].
- type Signer : Sign;
+/// A trait that describes a source of entropy.
+pub trait EntropySource {
+ /// Gets a unique, cryptographically-secure, random 32-byte value. This method must return a
+ /// different value each time it is called.
+ fn get_secure_random_bytes(&self) -> [u8; 32];
+}
+
+/// A trait that can handle cryptographic operations at the scope level of a node.
+pub trait NodeSigner {
/// Get node secret key based on the provided [`Recipient`].
///
/// The `node_id`/`network_key` is the public key that corresponds to this secret key.
///
/// Errors if the [`Recipient`] variant is not supported by the implementation.
fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()>;
+
+ /// Get secret key material as bytes for use in encrypting and decrypting inbound payment data.
+ ///
+ /// If the implementor of this trait supports [phantom node payments], then every node that is
+ /// intended to be included in the phantom invoice route hints must return the same value from
+ /// this method.
+ // This is because LDK avoids storing inbound payment data by encrypting payment data in the
+ // payment hash and/or payment secret, therefore for a payment to be receivable by multiple
+ // nodes, they must share the key that encrypts this payment data.
+ ///
+ /// This method must return the same value each time it is called.
+ ///
+ /// [phantom node payments]: PhantomKeysManager
+ fn get_inbound_payment_key_material(&self) -> KeyMaterial;
+
/// Get node id based on the provided [`Recipient`]. This public key corresponds to the secret in
/// [`get_node_secret`].
///
/// Errors if the [`Recipient`] variant is not supported by the implementation.
///
/// [`get_node_secret`]: Self::get_node_secret
- fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
- let secp_ctx = Secp256k1::signing_only();
- Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
- }
+ fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()>;
+
/// Gets the ECDH shared secret of our [`node secret`] and `other_key`, multiplying by `tweak` if
/// one is provided. Note that this tweak can be applied to `other_key` instead of our node
/// secret, though this is less efficient.
///
/// [`node secret`]: Self::get_node_secret
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()>;
- /// Get a script pubkey which we send funds to when claiming on-chain contestable outputs.
+
+ /// Sign an invoice.
+ /// By parameterizing by the raw invoice bytes instead of the hash, we allow implementors of
+ /// this trait to parse the invoice and make sure they're signing what they expect, rather than
+ /// blindly signing the hash.
+ /// The hrp is ascii bytes, while the invoice data is base32.
///
- /// This method should return a different value each time it is called, to avoid linking
- /// on-chain funds across channels as controlled to the same user.
- fn get_destination_script(&self) -> Script;
- /// Get a script pubkey which we will send funds to when closing a channel.
+ /// The secret key used to sign the invoice is dependent on the [`Recipient`].
///
- /// This method should return a different value each time it is called, to avoid linking
- /// on-chain funds across channels as controlled to the same user.
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript;
+ /// Errors if the [`Recipient`] variant is not supported by the implementation.
+ fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()>;
+}
+
+/// A trait that can return signer instances for individual channels.
+pub trait SignerProvider {
+ /// A type which implements [`Sign`] which will be returned by [`Self::derive_channel_signer`].
+ type Signer : Sign;
+
/// Generates a unique `channel_keys_id` that can be used to obtain a [`Self::Signer`] through
- /// [`KeysInterface::derive_channel_signer`]. The `user_channel_id` is provided to allow
- /// implementations of [`KeysInterface`] to maintain a mapping between it and the generated
+ /// [`SignerProvider::derive_channel_signer`]. The `user_channel_id` is provided to allow
+ /// implementations of [`SignerProvider`] to maintain a mapping between itself and the generated
/// `channel_keys_id`.
///
/// This method must return a different value each time it is called.
fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32];
+
/// Derives the private key material backing a `Signer`.
///
/// To derive a new `Signer`, a fresh `channel_keys_id` should be obtained through
- /// [`KeysInterface::generate_channel_keys_id`]. Otherwise, an existing `Signer` can be
+ /// [`SignerProvider::generate_channel_keys_id`]. Otherwise, an existing `Signer` can be
/// re-derived from its `channel_keys_id`, which can be obtained through its trait method
/// [`BaseSign::channel_keys_id`].
fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> Self::Signer;
- /// Gets a unique, cryptographically-secure, random 32 byte value. This is used for encrypting
- /// onion packets and for temporary channel IDs. There is no requirement that these be
- /// persisted anywhere, though they must be unique across restarts.
- ///
- /// This method must return a different value each time it is called.
- fn get_secure_random_bytes(&self) -> [u8; 32];
+
/// Reads a [`Signer`] for this [`KeysInterface`] from the given input stream.
/// This is only called during deserialization of other objects which contain
/// [`Sign`]-implementing objects (i.e., [`ChannelMonitor`]s and [`ChannelManager`]s).
/// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError>;
- /// Sign an invoice.
- /// By parameterizing by the raw invoice bytes instead of the hash, we allow implementors of
- /// this trait to parse the invoice and make sure they're signing what they expect, rather than
- /// blindly signing the hash.
- /// The `hrp` is ASCII bytes, while the invoice data is base32-encoded.
- ///
- /// The secret key used to sign the invoice is dependent on the [`Recipient`].
- ///
- /// Errors if the [`Recipient`] variant is not supported by the implementation.
- fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], receipient: Recipient) -> Result<RecoverableSignature, ()>;
- /// Get secret key material as bytes for use in encrypting and decrypting inbound payment data.
- ///
- /// If the implementor of this trait supports [phantom node payments], then every node that is
- /// intended to be included in the phantom invoice route hints must return the same value from
- /// this method.
- // This is because LDK avoids storing inbound payment data by encrypting payment data in the
- // payment hash and/or payment secret, therefore for a payment to be receivable by multiple
- // nodes, they must share the key that encrypts this payment data.
+
+ /// Get a script pubkey which we send funds to when claiming on-chain contestable outputs.
///
- /// This method must return the same value each time it is called.
+ /// This method should return a different value each time it is called, to avoid linking
+ /// on-chain funds across channels as controlled to the same user.
+ fn get_destination_script(&self) -> Script;
+
+ /// Get a script pubkey which we will send funds to when closing a channel.
///
- /// [phantom node payments]: PhantomKeysManager
- fn get_inbound_payment_key_material(&self) -> KeyMaterial;
+ /// This method should return a different value each time it is called, to avoid linking
+ /// on-chain funds across channels as controlled to the same user.
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript;
}
+/// A trait to describe an object which can get user secrets and key material.
+pub trait KeysInterface: EntropySource + NodeSigner + SignerProvider {}
+
#[derive(Clone)]
/// A simple implementation of [`Sign`] that just keeps the private keys in memory.
///
}
}
-impl KeysInterface for KeysManager {
- type Signer = InMemorySigner;
+impl EntropySource for KeysManager {
+ fn get_secure_random_bytes(&self) -> [u8; 32] {
+ let mut sha = self.rand_bytes_unique_start.clone();
+
+ let child_ix = self.rand_bytes_child_index.fetch_add(1, Ordering::AcqRel);
+ let child_privkey = self.rand_bytes_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32).expect("key space exhausted")).expect("Your RNG is busted");
+ sha.input(&child_privkey.private_key[..]);
+
+ sha.input(b"Unique Secure Random Bytes Salt");
+ Sha256::from_engine(sha).into_inner()
+ }
+}
+impl NodeSigner for KeysManager {
fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
match recipient {
Recipient::Node => Ok(self.node_secret.clone()),
self.inbound_payment_key.clone()
}
- fn get_destination_script(&self) -> Script {
- self.destination_script.clone()
+ fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
+ let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
+ let secret = match recipient {
+ Recipient::Node => self.get_node_secret(Recipient::Node)?,
+ Recipient::PhantomNode => return Err(()),
+ };
+ Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
}
+}
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
- ShutdownScript::new_p2wpkh_from_pubkey(self.shutdown_pubkey.clone())
- }
+impl SignerProvider for KeysManager {
+ type Signer = InMemorySigner;
fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] {
let child_idx = self.channel_child_index.fetch_add(1, Ordering::AcqRel);
self.derive_channel_keys(channel_value_satoshis, &channel_keys_id)
}
- fn get_secure_random_bytes(&self) -> [u8; 32] {
- let mut sha = self.rand_bytes_unique_start.clone();
-
- let child_ix = self.rand_bytes_child_index.fetch_add(1, Ordering::AcqRel);
- let child_privkey = self.rand_bytes_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32).expect("key space exhausted")).expect("Your RNG is busted");
- sha.input(&child_privkey.private_key[..]);
-
- sha.input(b"Unique Secure Random Bytes Salt");
- Sha256::from_engine(sha).into_inner()
- }
-
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
InMemorySigner::read(&mut io::Cursor::new(reader), self.node_secret.clone())
}
- fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
- let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
- let secret = match recipient {
- Recipient::Node => self.get_node_secret(Recipient::Node)?,
- Recipient::PhantomNode => return Err(()),
- };
- Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
+ fn get_destination_script(&self) -> Script {
+ self.destination_script.clone()
+ }
+
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
+ ShutdownScript::new_p2wpkh_from_pubkey(self.shutdown_pubkey.clone())
}
}
+impl KeysInterface for KeysManager {}
+
/// Similar to [`KeysManager`], but allows the node using this struct to receive phantom node
/// payments.
///
phantom_node_id: PublicKey,
}
-impl KeysInterface for PhantomKeysManager {
- type Signer = InMemorySigner;
+impl EntropySource for PhantomKeysManager {
+ fn get_secure_random_bytes(&self) -> [u8; 32] {
+ self.inner.get_secure_random_bytes()
+ }
+}
+impl NodeSigner for PhantomKeysManager {
fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
match recipient {
Recipient::Node => self.inner.get_node_secret(Recipient::Node),
self.inbound_payment_key.clone()
}
- fn get_destination_script(&self) -> Script {
- self.inner.get_destination_script()
+ fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
+ let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
+ let secret = self.get_node_secret(recipient)?;
+ Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
}
+}
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
- self.inner.get_shutdown_scriptpubkey()
- }
+impl SignerProvider for PhantomKeysManager {
+ type Signer = InMemorySigner;
fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] {
self.inner.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id)
self.inner.derive_channel_signer(channel_value_satoshis, channel_keys_id)
}
- fn get_secure_random_bytes(&self) -> [u8; 32] {
- self.inner.get_secure_random_bytes()
- }
-
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
self.inner.read_chan_signer(reader)
}
- fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
- let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
- let secret = self.get_node_secret(recipient)?;
- Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), &secret))
+ fn get_destination_script(&self) -> Script {
+ self.inner.get_destination_script()
+ }
+
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
+ self.inner.get_shutdown_scriptpubkey()
}
}
+impl KeysInterface for PhantomKeysManager {}
+
impl PhantomKeysManager {
/// Constructs a [`PhantomKeysManager`] given a 32-byte seed and an additional `cross_node_seed`
/// that is shared across all nodes that intend to participate in [phantom node payments]
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::chain::keysinterface::{KeysInterface, BaseSign, SignerProvider};
use bitcoin::{Network, Txid};
use bitcoin::hashes::Hash;
use crate::ln::PaymentHash;
use crate::chain::chaininterface::{FeeEstimator, ConfirmationTarget, LowerBoundedFeeEstimator};
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, LATENCY_GRACE_PERIOD_BLOCKS};
use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::chain::keysinterface::{Sign, KeysInterface, BaseSign};
+use crate::chain::keysinterface::{Sign, EntropySource, KeysInterface, BaseSign, SignerProvider};
use crate::util::events::ClosureReason;
use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
use crate::util::logger::Logger;
channel_ready_event_emitted: bool,
/// The unique identifier used to re-derive the private key material for the channel through
- /// [`KeysInterface::derive_channel_signer`].
+ /// [`SignerProvider::derive_channel_signer`].
channel_keys_id: [u8; 32],
}
pub fn funding_created<K: Deref, L: Deref>(
&mut self, msg: &msgs::FundingCreated, best_block: BestBlock, keys_source: &K, logger: &L
- ) -> Result<(msgs::FundingSigned, ChannelMonitor<<K::Target as KeysInterface>::Signer>, Option<msgs::ChannelReady>), ChannelError>
+ ) -> Result<(msgs::FundingSigned, ChannelMonitor<<K::Target as SignerProvider>::Signer>, Option<msgs::ChannelReady>), ChannelError>
where
K::Target: KeysInterface,
L::Target: Logger
/// If this call is successful, broadcast the funding transaction (and not before!)
pub fn funding_signed<K: Deref, L: Deref>(
&mut self, msg: &msgs::FundingSigned, best_block: BestBlock, keys_source: &K, logger: &L
- ) -> Result<(ChannelMonitor<<K::Target as KeysInterface>::Signer>, Transaction, Option<msgs::ChannelReady>), ChannelError>
+ ) -> Result<(ChannelMonitor<<K::Target as SignerProvider>::Signer>, Transaction, Option<msgs::ChannelReady>), ChannelError>
where
K::Target: KeysInterface,
L::Target: Logger
}
const MAX_ALLOC_SIZE: usize = 64*1024;
-impl<'a, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<<K::Target as KeysInterface>::Signer>
+impl<'a, K: Deref> ReadableArgs<(&'a K, u32)> for Channel<<K::Target as SignerProvider>::Signer>
where K::Target: KeysInterface {
fn read<R : io::Read>(reader: &mut R, args: (&'a K, u32)) -> Result<Self, DecodeError> {
let (keys_source, serialized_height) = args;
use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
use crate::chain::BestBlock;
use crate::chain::chaininterface::{FeeEstimator, LowerBoundedFeeEstimator, ConfirmationTarget};
- use crate::chain::keysinterface::{BaseSign, InMemorySigner, Recipient, KeyMaterial, KeysInterface};
+ use crate::chain::keysinterface::{BaseSign, InMemorySigner, Recipient, KeyMaterial, KeysInterface, EntropySource, NodeSigner, SignerProvider};
use crate::chain::transaction::OutPoint;
use crate::util::config::UserConfig;
use crate::util::enforcing_trait_impls::EnforcingSigner;
struct Keys {
signer: InMemorySigner,
}
- impl KeysInterface for Keys {
- type Signer = InMemorySigner;
+ impl EntropySource for Keys {
+ fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
+ }
+
+ impl NodeSigner for Keys {
fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> { panic!(); }
+
+ fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
+ let secp_ctx = Secp256k1::signing_only();
+ Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+ }
+
fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&Scalar>) -> Result<SharedSecret, ()> { panic!(); }
+
fn get_inbound_payment_key_material(&self) -> KeyMaterial { panic!(); }
+
+ fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { panic!(); }
+ }
+
+ impl SignerProvider for Keys {
+ type Signer = InMemorySigner;
+
+ fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
+ self.signer.channel_keys_id()
+ }
+
+ fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer {
+ self.signer.clone()
+ }
+
+ fn read_chan_signer(&self, _data: &[u8]) -> Result<Self::Signer, DecodeError> { panic!(); }
+
fn get_destination_script(&self) -> Script {
let secp_ctx = Secp256k1::signing_only();
let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap();
let channel_close_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap();
ShutdownScript::new_p2wpkh_from_pubkey(PublicKey::from_secret_key(&secp_ctx, &channel_close_key))
}
-
- fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] {
- self.signer.channel_keys_id()
- }
- fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer {
- self.signer.clone()
- }
- fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
- fn read_chan_signer(&self, _data: &[u8]) -> Result<Self::Signer, DecodeError> { panic!(); }
- fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { panic!(); }
}
+ impl KeysInterface for Keys {}
+
#[cfg(not(feature = "grind_signatures"))]
fn public_from_secret_hex(secp_ctx: &Secp256k1<bitcoin::secp256k1::All>, hex: &str) -> PublicKey {
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode(hex).unwrap()[..]).unwrap())
use crate::ln::onion_utils::HTLCFailReason;
use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, MAX_VALUE_MSAT};
use crate::ln::wire::Encode;
-use crate::chain::keysinterface::{Sign, KeysInterface, KeysManager, Recipient};
+use crate::chain::keysinterface::{EntropySource, KeysInterface, KeysManager, NodeSigner, Recipient, Sign, SignerProvider};
use crate::util::config::{UserConfig, ChannelConfig};
use crate::util::events::{Event, EventHandler, EventsProvider, MessageSendEvent, MessageSendEventsProvider, ClosureReason, HTLCDestination};
use crate::util::events;
// | |__`pending_background_events`
//
pub struct ChannelManager<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
/// See `ChannelManager` struct-level documentation for lock order requirements.
#[cfg(any(test, feature = "_test_utils"))]
- pub(super) channel_state: Mutex<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
+ pub(super) channel_state: Mutex<ChannelHolder<<K::Target as SignerProvider>::Signer>>,
#[cfg(not(any(test, feature = "_test_utils")))]
- channel_state: Mutex<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
+ channel_state: Mutex<ChannelHolder<<K::Target as SignerProvider>::Signer>>,
/// Storage for PaymentSecrets and any requirements on future inbound payments before we will
/// expose them to users via a PaymentClaimable event. HTLCs which do not meet the requirements
}
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F, L>
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
Ok(temporary_channel_id)
}
- fn list_channels_with_filter<Fn: FnMut(&(&[u8; 32], &Channel<<K::Target as KeysInterface>::Signer>)) -> bool>(&self, f: Fn) -> Vec<ChannelDetails> {
+ fn list_channels_with_filter<Fn: FnMut(&(&[u8; 32], &Channel<<K::Target as SignerProvider>::Signer>)) -> bool>(&self, f: Fn) -> Vec<ChannelDetails> {
let mut res = Vec::new();
{
let channel_state = self.channel_state.lock().unwrap();
}
/// Helper function that issues the channel close events
- fn issue_channel_close_events(&self, channel: &Channel<<K::Target as KeysInterface>::Signer>, closure_reason: ClosureReason) {
+ fn issue_channel_close_events(&self, channel: &Channel<<K::Target as SignerProvider>::Signer>, closure_reason: ClosureReason) {
let mut pending_events_lock = self.pending_events.lock().unwrap();
match channel.unbroadcasted_funding() {
Some(transaction) => {
/// [`MessageSendEvent::BroadcastChannelUpdate`] event.
///
/// May be called with channel_state already locked!
- fn get_channel_update_for_broadcast(&self, chan: &Channel<<K::Target as KeysInterface>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
+ fn get_channel_update_for_broadcast(&self, chan: &Channel<<K::Target as SignerProvider>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
if !chan.should_announce() {
return Err(LightningError {
err: "Cannot broadcast a channel_update for a private channel".to_owned(),
/// and thus MUST NOT be called unless the recipient of the resulting message has already
/// provided evidence that they know about the existence of the channel.
/// May be called with channel_state already locked!
- fn get_channel_update_for_unicast(&self, chan: &Channel<<K::Target as KeysInterface>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
+ fn get_channel_update_for_unicast(&self, chan: &Channel<<K::Target as SignerProvider>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
log_trace!(self.logger, "Attempting to generate channel update for channel {}", log_bytes!(chan.channel_id()));
let short_channel_id = match chan.get_short_channel_id().or(chan.latest_inbound_scid_alias()) {
None => return Err(LightningError{err: "Channel not yet established".to_owned(), action: msgs::ErrorAction::IgnoreError}),
self.get_channel_update_for_onion(short_channel_id, chan)
}
- fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel<<K::Target as KeysInterface>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
+ fn get_channel_update_for_onion(&self, short_channel_id: u64, chan: &Channel<<K::Target as SignerProvider>::Signer>) -> Result<msgs::ChannelUpdate, LightningError> {
log_trace!(self.logger, "Generating channel update for channel {}", log_bytes!(chan.channel_id()));
let were_node_one = PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).serialize()[..] < chan.get_counterparty_node_id().serialize()[..];
/// Handles the generation of a funding transaction, optionally (for tests) with a function
/// which checks the correctness of the funding transaction given the associated channel.
- fn funding_transaction_generated_intern<FundingOutput: Fn(&Channel<<K::Target as KeysInterface>::Signer>, &Transaction) -> Result<OutPoint, APIError>>(
+ fn funding_transaction_generated_intern<FundingOutput: Fn(&Channel<<K::Target as SignerProvider>::Signer>, &Transaction) -> Result<OutPoint, APIError>>(
&self, temporary_channel_id: &[u8; 32], _counterparty_node_id: &PublicKey, funding_transaction: Transaction, find_funding_output: FundingOutput
) -> Result<(), APIError> {
let (chan, msg) = {
self.process_background_events();
}
- fn update_channel_fee(&self, chan_id: &[u8; 32], chan: &mut Channel<<K::Target as KeysInterface>::Signer>, new_feerate: u32) -> NotifyOption {
+ fn update_channel_fee(&self, chan_id: &[u8; 32], chan: &mut Channel<<K::Target as SignerProvider>::Signer>, new_feerate: u32) -> NotifyOption {
if !chan.is_outbound() { return NotifyOption::SkipPersist; }
// If the feerate has decreased by less than half, don't bother
if new_feerate <= chan.get_feerate() && new_feerate * 2 > chan.get_feerate() {
///
/// This is for failures on the channel on which the HTLC was *received*, not failures
/// forwarding
- fn get_htlc_inbound_temp_fail_err_and_data(&self, desired_err_code: u16, chan: &Channel<<K::Target as KeysInterface>::Signer>) -> (u16, Vec<u8>) {
+ fn get_htlc_inbound_temp_fail_err_and_data(&self, desired_err_code: u16, chan: &Channel<<K::Target as SignerProvider>::Signer>) -> (u16, Vec<u8>) {
// We can't be sure what SCID was used when relaying inbound towards us, so we have to
// guess somewhat. If its a public channel, we figure best to just use the real SCID (as
// we're not leaking that we have a channel with the counterparty), otherwise we try to use
/// Gets an HTLC onion failure code and error data for an `UPDATE` error, given the error code
/// that we want to return and a channel.
- fn get_htlc_temp_fail_err_and_data(&self, desired_err_code: u16, scid: u64, chan: &Channel<<K::Target as KeysInterface>::Signer>) -> (u16, Vec<u8>) {
+ fn get_htlc_temp_fail_err_and_data(&self, desired_err_code: u16, scid: u64, chan: &Channel<<K::Target as SignerProvider>::Signer>) -> (u16, Vec<u8>) {
debug_assert_eq!(desired_err_code & 0x1000, 0x1000);
if let Ok(upd) = self.get_channel_update_for_onion(scid, chan) {
let mut enc = VecWriter(Vec::with_capacity(upd.serialized_length() + 6));
}
fn claim_funds_from_hop<ComplFunc: FnOnce(Option<u64>) -> Option<MonitorUpdateCompletionAction>>(&self,
- mut channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
+ mut channel_state_lock: MutexGuard<ChannelHolder<<K::Target as SignerProvider>::Signer>>,
prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, completion_action: ComplFunc)
-> Result<(), (PublicKey, MsgHandleErrInternal)> {
//TODO: Delay the claimed_funds relaying just like we do outbound relay!
}
}
- fn claim_funds_internal(&self, channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option<u64>, from_onchain: bool, next_channel_id: [u8; 32]) {
+ fn claim_funds_internal(&self, channel_state_lock: MutexGuard<ChannelHolder<<K::Target as SignerProvider>::Signer>>, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option<u64>, from_onchain: bool, next_channel_id: [u8; 32]) {
match source {
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
mem::drop(channel_state_lock);
/// Handles a channel reentering a functional state, either due to reconnect or a monitor
/// update completion.
fn handle_channel_resumption(&self, pending_msg_events: &mut Vec<MessageSendEvent>,
- channel: &mut Channel<<K::Target as KeysInterface>::Signer>, raa: Option<msgs::RevokeAndACK>,
+ channel: &mut Channel<<K::Target as SignerProvider>::Signer>, raa: Option<msgs::RevokeAndACK>,
commitment_update: Option<msgs::CommitmentUpdate>, order: RAACommitmentOrder,
pending_forwards: Vec<(PendingHTLCInfo, u64)>, funding_broadcastable: Option<Transaction>,
channel_ready: Option<msgs::ChannelReady>, announcement_sigs: Option<msgs::AnnouncementSignatures>)
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
}
- let create_pending_htlc_status = |chan: &Channel<<K::Target as KeysInterface>::Signer>, pending_forward_info: PendingHTLCStatus, error_code: u16| {
+ let create_pending_htlc_status = |chan: &Channel<<K::Target as SignerProvider>::Signer>, pending_forward_info: PendingHTLCStatus, error_code: u16| {
// If the update_add is completely bogus, the call will Err and we will close,
// but if we've sent a shutdown and they haven't acknowledged it yet, we just
// want to reject the new HTLC and fail it backwards instead of forwarding.
}
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> MessageSendEventsProvider for ChannelManager<M, T, K, F, L>
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> EventsProvider for ChannelManager<M, T, K, F, L>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> chain::Listen for ChannelManager<M, T, K, F, L>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> chain::Confirm for ChannelManager<M, T, K, F, L>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F, L>
where
- M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
/// Calls a function which handles an on-chain event (blocks dis/connected, transactions
/// un/confirmed, etc) on each channel, handling any resulting errors or messages generated by
/// the function.
- fn do_chain_event<FN: Fn(&mut Channel<<K::Target as KeysInterface>::Signer>) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>>
+ fn do_chain_event<FN: Fn(&mut Channel<<K::Target as SignerProvider>::Signer>) -> Result<(Option<msgs::ChannelReady>, Vec<(HTLCSource, PaymentHash)>, Option<msgs::AnnouncementSignatures>), ClosureReason>>
(&self, height_opt: Option<u32>, f: FN) {
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
// during initialization prior to the chain_monitor being fully configured in some cases.
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref >
ChannelMessageHandler for ChannelManager<M, T, K, F, L>
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
);
impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelManager<M, T, K, F, L>
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
///
/// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor
pub struct ChannelManagerReadArgs<'a, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
/// this struct.
///
/// (C-not exported) because we have no HashMap bindings
- pub channel_monitors: HashMap<OutPoint, &'a mut ChannelMonitor<<K::Target as KeysInterface>::Signer>>,
+ pub channel_monitors: HashMap<OutPoint, &'a mut ChannelMonitor<<K::Target as SignerProvider>::Signer>>,
}
impl<'a, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ChannelManagerReadArgs<'a, M, T, K, F, L>
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
/// HashMap for you. This is primarily useful for C bindings where it is not practical to
/// populate a HashMap directly from C.
pub fn new(keys_manager: K, fee_estimator: F, chain_monitor: M, tx_broadcaster: T, logger: L, default_config: UserConfig,
- mut channel_monitors: Vec<&'a mut ChannelMonitor<<K::Target as KeysInterface>::Signer>>) -> Self {
+ mut channel_monitors: Vec<&'a mut ChannelMonitor<<K::Target as SignerProvider>::Signer>>) -> Self {
Self {
keys_manager, fee_estimator, chain_monitor, tx_broadcaster, logger, default_config,
channel_monitors: channel_monitors.drain(..).map(|monitor| { (monitor.get_funding_txo().0, monitor) }).collect()
// SipmleArcChannelManager type:
impl<'a, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ReadableArgs<ChannelManagerReadArgs<'a, M, T, K, F, L>> for (BlockHash, Arc<ChannelManager<M, T, K, F, L>>)
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
impl<'a, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
ReadableArgs<ChannelManagerReadArgs<'a, M, T, K, F, L>> for (BlockHash, ChannelManager<M, T, K, F, L>)
- where M::Target: chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128));
let mut channel_closures = Vec::new();
for _ in 0..channel_count {
- let mut channel: Channel<<K::Target as KeysInterface>::Signer> = Channel::read(reader, (&args.keys_manager, best_block_height))?;
+ let mut channel: Channel<<K::Target as SignerProvider>::Signer> = Channel::read(reader, (&args.keys_manager, best_block_height))?;
let funding_txo = channel.get_funding_txo().ok_or(DecodeError::InvalidValue)?;
funding_txo_set.insert(funding_txo.clone());
if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
use crate::util::errors::APIError;
use crate::util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
use crate::util::test_utils;
- use crate::chain::keysinterface::KeysInterface;
+ use crate::chain::keysinterface::{EntropySource, KeysInterface};
#[test]
fn test_notify_limits() {
pub mod bench {
use crate::chain::Listen;
use crate::chain::chainmonitor::{ChainMonitor, Persist};
- use crate::chain::keysinterface::{KeysManager, KeysInterface, InMemorySigner};
+ use crate::chain::keysinterface::{EntropySource, KeysManager, KeysInterface, InMemorySigner};
use crate::ln::channelmanager::{self, BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage, PaymentId};
use crate::ln::functional_test_utils::*;
use crate::ln::msgs::{ChannelMessageHandler, Init};
//! A bunch of useful utilities for building networks of nodes and exchanging messages between
//! nodes for functional tests.
-use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch, keysinterface::KeysInterface};
+use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch, keysinterface::EntropySource};
use crate::chain::channelmonitor::ChannelMonitor;
use crate::chain::transaction::OutPoint;
use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret};
#[macro_export]
macro_rules! get_route {
($send_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{
- use $crate::chain::keysinterface::KeysInterface;
+ use $crate::chain::keysinterface::EntropySource;
let scorer = $crate::util::test_utils::TestScorer::with_penalty(0);
let keys_manager = $crate::util::test_utils::TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
let random_seed_bytes = keys_manager.get_secure_random_bytes();
use crate::chain::channelmonitor;
use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
use crate::chain::transaction::OutPoint;
-use crate::chain::keysinterface::{BaseSign, KeysInterface};
+use crate::chain::keysinterface::{BaseSign, EntropySource, KeysInterface};
use crate::ln::{PaymentPreimage, PaymentSecret, PaymentHash};
use crate::ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT};
use crate::ln::channelmanager::{self, PaymentId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA};
use bitcoin::hashes::cmp::fixed_time_eq;
use bitcoin::hashes::hmac::{Hmac, HmacEngine};
use bitcoin::hashes::sha256::Hash as Sha256;
-use crate::chain::keysinterface::{KeyMaterial, KeysInterface};
+use crate::chain::keysinterface::{KeyMaterial, KeysInterface, EntropySource};
use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
use crate::ln::msgs;
use crate::ln::msgs::MAX_VALUE_MSAT;
const METHOD_TYPE_OFFSET: usize = 5;
/// A set of keys that were HKDF-expanded from an initial call to
-/// [`KeysInterface::get_inbound_payment_key_material`].
+/// [`NodeSigner::get_inbound_payment_key_material`].
///
-/// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
+/// [`NodeSigner::get_inbound_payment_key_material`]: crate::chain::keysinterface::NodeSigner::get_inbound_payment_key_material
pub struct ExpandedKey {
/// The key used to encrypt the bytes containing the payment metadata (i.e. the amount and
/// expiry, included for payment verification on decryption).
/// `ChannelManager` is required. Useful for generating invoices for [phantom node payments] without
/// a `ChannelManager`.
///
-/// `keys` is generated by calling [`KeysInterface::get_inbound_payment_key_material`] and then
+/// `keys` is generated by calling [`NodeSigner::get_inbound_payment_key_material`] and then
/// calling [`ExpandedKey::new`] with its result. It is recommended to cache this value and not
/// regenerate it for each new inbound payment.
///
/// `current_time` is a Unix timestamp representing the current time.
///
/// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
+/// [`NodeSigner::get_inbound_payment_key_material`]: crate::chain::keysinterface::NodeSigner::get_inbound_payment_key_material
pub fn create<K: Deref>(keys: &ExpandedKey, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32, keys_manager: &K, current_time: u64) -> Result<(PaymentHash, PaymentSecret), ()>
where K::Target: KeysInterface
{
///
/// The metadata is constructed as:
/// payment method (3 bits) || payment amount (8 bytes - 3 bits) || expiry (8 bytes)
-/// and encrypted using a key derived from [`KeysInterface::get_inbound_payment_key_material`].
+/// and encrypted using a key derived from [`NodeSigner::get_inbound_payment_key_material`].
///
/// Then on payment receipt, we verify in this method that the payment preimage and payment secret
/// match what was constructed.
///
/// See [`ExpandedKey`] docs for more info on the individual keys used.
///
-/// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
+/// [`NodeSigner::get_inbound_payment_key_material`]: crate::chain::keysinterface::NodeSigner::get_inbound_payment_key_material
/// [`create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
/// [`create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::FinalOnionHopData, highest_seen_timestamp: u64, keys: &ExpandedKey, logger: &L) -> Result<Option<PaymentPreimage>, ()>
//! returned errors decode to the correct thing.
use crate::chain::channelmonitor::{CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
-use crate::chain::keysinterface::{KeysInterface, Recipient};
+use crate::chain::keysinterface::{EntropySource, KeysInterface, NodeSigner, Recipient};
use crate::ln::{PaymentHash, PaymentSecret};
use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
use crate::ln::channelmanager::{self, HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, PendingAddHTLCInfo, PendingHTLCInfo, PendingHTLCRouting, PaymentId};
use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS};
use crate::chain::transaction::OutPoint;
-use crate::chain::keysinterface::KeysInterface;
+use crate::chain::keysinterface::{EntropySource, KeysInterface};
use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
use crate::ln::channelmanager::{self, BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, IDEMPOTENCY_TIMEOUT_TICKS};
use crate::ln::msgs;
//! LSP).
use crate::chain::ChannelMonitorUpdateStatus;
-use crate::chain::keysinterface::{Recipient, KeysInterface};
+use crate::chain::keysinterface::{Recipient, KeysInterface, NodeSigner};
use crate::ln::channelmanager::{self, ChannelManager, MIN_CLTV_EXPIRY_DELTA, PaymentId};
use crate::routing::gossip::RoutingFees;
use crate::routing::router::{PaymentParameters, RouteHint, RouteHintHop};
use crate::chain::{ChannelMonitorUpdateStatus, Watch};
use crate::chain::chaininterface::LowerBoundedFeeEstimator;
use crate::chain::channelmonitor::ChannelMonitor;
-use crate::chain::keysinterface::KeysInterface;
+use crate::chain::keysinterface::{EntropySource, KeysInterface};
use crate::chain::transaction::OutPoint;
use crate::ln::channelmanager::{self, ChannelManager, ChannelManagerReadArgs, PaymentId};
use crate::ln::msgs;
//! Tests of our shutdown and closing_signed negotiation logic.
-use crate::chain::keysinterface::KeysInterface;
+use crate::chain::keysinterface::{EntropySource, KeysInterface, SignerProvider};
use crate::chain::transaction::OutPoint;
use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId};
use crate::routing::router::{PaymentParameters, get_route};
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
-use crate::chain::keysinterface::{KeysInterface, Recipient};
+use crate::chain::keysinterface::{KeysInterface, NodeSigner, Recipient};
use super::packet::ControlTlvs;
use super::utils;
use crate::ln::msgs::DecodeError;
//! Onion message testing and test utilities live here.
-use crate::chain::keysinterface::{KeysInterface, Recipient};
+use crate::chain::keysinterface::{KeysInterface, NodeSigner, Recipient};
use crate::ln::features::InitFeatures;
use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
use super::{BlindedPath, CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents, OnionMessenger, SendError};
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::secp256k1::{self, PublicKey, Scalar, Secp256k1, SecretKey};
-use crate::chain::keysinterface::{KeysInterface, KeysManager, Recipient};
+use crate::chain::keysinterface::{EntropySource, KeysInterface, KeysManager, NodeSigner, Recipient};
use crate::ln::features::{InitFeatures, NodeFeatures};
use crate::ln::msgs::{self, OnionMessageHandler};
use crate::ln::onion_utils;
GetNodeIdFailed,
/// We attempted to send to a blinded path where we are the introduction node, and failed to
/// advance the blinded path to make the second hop the new introduction node. Either
- /// [`KeysInterface::ecdh`] failed, we failed to tweak the current blinding point to get the
+ /// [`NodeSigner::ecdh`] failed, we failed to tweak the current blinding point to get the
/// new blinding point, or we were attempting to send to ourselves.
BlindedPathAdvanceFailed,
}
use crate::routing::scoring::{ChannelUsage, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
use crate::chain::transaction::OutPoint;
- use crate::chain::keysinterface::KeysInterface;
+ use crate::chain::keysinterface::{EntropySource, KeysInterface};
use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
use crate::ln::channelmanager;
use bitcoin::hashes::Hash;
use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
use crate::chain::transaction::OutPoint;
- use crate::chain::keysinterface::{KeysManager,KeysInterface};
+ use crate::chain::keysinterface::{EntropySource, KeysManager,KeysInterface};
use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
use crate::ln::features::InvoiceFeatures;
use crate::routing::gossip::NetworkGraph;
/// any attacker who is able to take control of a channel can just as easily send the funds via
/// lightning payments, so we never require that our counterparties support this option.
///
- /// The upfront key committed is provided from [`KeysInterface::get_shutdown_scriptpubkey`].
+ /// The upfront key committed is provided from [`SignerProvider::get_shutdown_scriptpubkey`].
///
/// Default value: true.
///
- /// [`KeysInterface::get_shutdown_scriptpubkey`]: crate::chain::keysinterface::KeysInterface::get_shutdown_scriptpubkey
+ /// [`SignerProvider::get_shutdown_scriptpubkey`]: crate::chain::keysinterface::SignerProvider::get_shutdown_scriptpubkey
pub commit_upfront_shutdown_pubkey: bool,
/// The Proportion of the channel value to configure as counterparty's channel reserve,
/// [`chain::Watch::update_channel`]: crate::chain::Watch::update_channel
/// [`ChannelMonitorUpdateStatus::InProgress`]: crate::chain::ChannelMonitorUpdateStatus::InProgress
MonitorUpdateInProgress,
- /// [`KeysInterface::get_shutdown_scriptpubkey`] returned a shutdown scriptpubkey incompatible
+ /// [`SignerProvider::get_shutdown_scriptpubkey`] returned a shutdown scriptpubkey incompatible
/// with the channel counterparty as negotiated in [`InitFeatures`].
///
/// Using a SegWit v0 script should resolve this issue. If you cannot, you won't be able to open
/// a channel or cooperatively close one with this peer (and will have to force-close instead).
///
- /// [`KeysInterface::get_shutdown_scriptpubkey`]: crate::chain::keysinterface::KeysInterface::get_shutdown_scriptpubkey
+ /// [`SignerProvider::get_shutdown_scriptpubkey`]: crate::chain::keysinterface::SignerProvider::get_shutdown_scriptpubkey
/// [`InitFeatures`]: crate::ln::features::InitFeatures
IncompatibleShutdownScript {
/// The incompatible shutdown script.
use crate::chain;
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
use crate::chain::chainmonitor::{Persist, MonitorUpdateId};
-use crate::chain::keysinterface::{Sign, KeysInterface};
+use crate::chain::keysinterface::{Sign, KeysInterface, SignerProvider};
use crate::chain::transaction::OutPoint;
use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate};
use crate::ln::channelmanager::ChannelManager;
/// Trait that handles persisting a [`ChannelManager`], [`NetworkGraph`], and [`WriteableScore`] to disk.
pub trait Persister<'a, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S: WriteableScore<'a>>
- where M::Target: 'static + chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: 'static + chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: 'static + BroadcasterInterface,
K::Target: 'static + KeysInterface,
F::Target: 'static + FeeEstimator,
}
impl<'a, A: KVStorePersister, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, M, T, K, F, L, S> for A
- where M::Target: 'static + chain::Watch<<K::Target as KeysInterface>::Signer>,
+ where M::Target: 'static + chain::Watch<<K::Target as SignerProvider>::Signer>,
T::Target: 'static + BroadcasterInterface,
K::Target: 'static + KeysInterface,
F::Target: 'static + FeeEstimator,
pub(crate) mod fake_scid {
use bitcoin::hash_types::BlockHash;
use bitcoin::hashes::hex::FromHex;
- use crate::chain::keysinterface::KeysInterface;
+ use crate::chain::keysinterface::{KeysInterface, EntropySource};
use crate::util::chacha20::ChaCha20;
use crate::util::scid_utils;
use bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::secp256k1::{SecretKey, PublicKey, Secp256k1, ecdsa::Signature, Scalar};
-use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::RecoverableSignature;
use regex;
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use core::mem;
use bitcoin::bech32::u5;
-use crate::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial};
+use crate::chain::keysinterface::{InMemorySigner, Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
#[cfg(feature = "std")]
use std::time::{SystemTime, UNIX_EPOCH};
+use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::Sequence;
pub struct TestVecWriter(pub Vec<u8>);
}
pub struct OnlyReadsKeysInterface {}
-impl keysinterface::KeysInterface for OnlyReadsKeysInterface {
- type Signer = EnforcingSigner;
+impl EntropySource for OnlyReadsKeysInterface {
+ fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }}
+
+impl NodeSigner for OnlyReadsKeysInterface {
fn get_node_secret(&self, _recipient: Recipient) -> Result<SecretKey, ()> { unreachable!(); }
+ fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
+ let secp_ctx = Secp256k1::signing_only();
+ Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
+ }
fn ecdh(&self, _recipient: Recipient, _other_key: &PublicKey, _tweak: Option<&Scalar>) -> Result<SharedSecret, ()> { unreachable!(); }
fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!(); }
- fn get_destination_script(&self) -> Script { unreachable!(); }
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!(); }
+ fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { unreachable!(); }
+}
+
+impl SignerProvider for OnlyReadsKeysInterface {
+ type Signer = EnforcingSigner;
+
fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32] { unreachable!(); }
+
fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::Signer { unreachable!(); }
- fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] }
fn read_chan_signer(&self, mut reader: &[u8]) -> Result<Self::Signer, msgs::DecodeError> {
let dummy_sk = SecretKey::from_slice(&[42; 32]).unwrap();
false
))
}
- fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5], _recipient: Recipient) -> Result<RecoverableSignature, ()> { unreachable!(); }
+
+ fn get_destination_script(&self) -> Script { unreachable!(); }
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { unreachable!(); }
+}
+
+impl keysinterface::KeysInterface for OnlyReadsKeysInterface {
}
pub struct TestChainMonitor<'a> {
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
}
-impl keysinterface::KeysInterface for TestKeysInterface {
- type Signer = EnforcingSigner;
+impl EntropySource for TestKeysInterface {
+ fn get_secure_random_bytes(&self) -> [u8; 32] {
+ let override_random_bytes = self.override_random_bytes.lock().unwrap();
+ if let Some(bytes) = &*override_random_bytes {
+ return *bytes;
+ }
+ self.backing.get_secure_random_bytes()
+ }
+}
+impl NodeSigner for TestKeysInterface {
fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
self.backing.get_node_secret(recipient)
}
+
fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
self.backing.get_node_id(recipient)
}
+
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
self.backing.ecdh(recipient, other_key, tweak)
}
+
fn get_inbound_payment_key_material(&self) -> keysinterface::KeyMaterial {
self.backing.get_inbound_payment_key_material()
}
- fn get_destination_script(&self) -> Script { self.backing.get_destination_script() }
- fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
- match &mut *self.expectations.lock().unwrap() {
- None => self.backing.get_shutdown_scriptpubkey(),
- Some(expectations) => match expectations.pop_front() {
- None => panic!("Unexpected get_shutdown_scriptpubkey"),
- Some(expectation) => expectation.returns,
- },
- }
+ fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
+ self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
}
+}
+
+impl SignerProvider for TestKeysInterface {
+ type Signer = EnforcingSigner;
fn generate_channel_keys_id(&self, inbound: bool, channel_value_satoshis: u64, user_channel_id: u128) -> [u8; 32] {
self.backing.generate_channel_keys_id(inbound, channel_value_satoshis, user_channel_id)
EnforcingSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check)
}
- fn get_secure_random_bytes(&self) -> [u8; 32] {
- let override_random_bytes = self.override_random_bytes.lock().unwrap();
- if let Some(bytes) = &*override_random_bytes {
- return *bytes;
- }
- self.backing.get_secure_random_bytes()
- }
-
fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, msgs::DecodeError> {
let mut reader = io::Cursor::new(buffer);
))
}
- fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()> {
- self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
+ fn get_destination_script(&self) -> Script { self.backing.get_destination_script() }
+
+ fn get_shutdown_scriptpubkey(&self) -> ShutdownScript {
+ match &mut *self.expectations.lock().unwrap() {
+ None => self.backing.get_shutdown_scriptpubkey(),
+ Some(expectations) => match expectations.pop_front() {
+ None => panic!("Unexpected get_shutdown_scriptpubkey"),
+ Some(expectation) => expectation.returns,
+ },
+ }
}
}
+impl keysinterface::KeysInterface for TestKeysInterface {}
+
impl TestKeysInterface {
pub fn new(seed: &[u8; 32], network: Network) -> Self {
let now = Duration::from_secs(genesis_block(network).header.time as u64);
}
}
- /// Sets an expectation that [`keysinterface::KeysInterface::get_shutdown_scriptpubkey`] is
+ /// Sets an expectation that [`keysinterface::SignerProvider::get_shutdown_scriptpubkey`] is
/// called.
pub fn expect(&self, expectation: OnGetShutdownScriptpubkey) -> &Self {
self.expectations.lock().unwrap()
}
}
-/// An expectation that [`keysinterface::KeysInterface::get_shutdown_scriptpubkey`] was called and
+/// An expectation that [`keysinterface::SignerProvider::get_shutdown_scriptpubkey`] was called and
/// returns a [`ShutdownScript`].
pub struct OnGetShutdownScriptpubkey {
/// A shutdown script used to close a channel.