Skip to content

Commit f2a2fd0

Browse files
committed
Make ChannelKeys an API and template Channel with it.
Instead of having in-memory access to the list of private keys associated with a channel, we should have a generic API which allows us to request signing, allowing the user to store private keys any way they like. The first step is the (rather mechanical) process of templating the entire tree of ChannelManager -> Channel impls by the key-providing type. In a later commit we should expose only public keys where possible.
1 parent 8defcf1 commit f2a2fd0

File tree

11 files changed

+221
-138
lines changed

11 files changed

+221
-138
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use bitcoin_hashes::sha256d::Hash as Sha256d;
2424
use lightning::chain::chaininterface;
2525
use lightning::chain::transaction::OutPoint;
2626
use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil};
27-
use lightning::chain::keysinterface::{ChannelKeys, KeysInterface};
27+
use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
2828
use lightning::ln::channelmonitor;
2929
use lightning::ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdateErr, HTLCUpdate};
3030
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage, ChannelManagerReadArgs};
@@ -130,6 +130,8 @@ struct KeyProvider {
130130
channel_id: atomic::AtomicU8,
131131
}
132132
impl KeysInterface for KeyProvider {
133+
type ChanKeySigner = InMemoryChannelKeys;
134+
133135
fn get_node_secret(&self) -> SecretKey {
134136
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()
135137
}
@@ -146,8 +148,8 @@ impl KeysInterface for KeyProvider {
146148
PublicKey::from_secret_key(&secp_ctx, &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())
147149
}
148150

149-
fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys {
150-
ChannelKeys {
151+
fn get_channel_keys(&self, _inbound: bool) -> InMemoryChannelKeys {
152+
InMemoryChannelKeys {
151153
funding_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, 4, self.node_id]).unwrap(),
152154
revocation_base_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, 5, self.node_id]).unwrap(),
153155
payment_base_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, 6, self.node_id]).unwrap(),
@@ -223,7 +225,7 @@ pub fn do_test(data: &[u8]) {
223225
channel_monitors: &monitor_refs,
224226
};
225227

226-
let res = (<(Sha256d, ChannelManager)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor);
228+
let res = (<(Sha256d, ChannelManager<InMemoryChannelKeys>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor);
227229
for (_, was_good) in $old_monitors.latest_updates_good_at_last_ser.lock().unwrap().iter() {
228230
if !was_good {
229231
// If the last time we updated a monitor we didn't successfully update (and we

fuzz/src/full_stack.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use bitcoin_hashes::sha256d::Hash as Sha256dHash;
2020

2121
use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil};
2222
use lightning::chain::transaction::OutPoint;
23-
use lightning::chain::keysinterface::{ChannelKeys, KeysInterface};
23+
use lightning::chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
2424
use lightning::ln::channelmonitor;
2525
use lightning::ln::channelmanager::{ChannelManager, PaymentHash, PaymentPreimage};
2626
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
@@ -135,7 +135,7 @@ impl<'a> Hash for Peer<'a> {
135135
}
136136

137137
struct MoneyLossDetector<'a, 'b> {
138-
manager: Arc<ChannelManager<'b>>,
138+
manager: Arc<ChannelManager<'b, InMemoryChannelKeys>>,
139139
monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint>>,
140140
handler: PeerManager<Peer<'a>>,
141141

@@ -148,7 +148,7 @@ struct MoneyLossDetector<'a, 'b> {
148148
blocks_connected: u32,
149149
}
150150
impl<'a, 'b> MoneyLossDetector<'a, 'b> {
151-
pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc<ChannelManager<'b>>, monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint>>, handler: PeerManager<Peer<'a>>) -> Self {
151+
pub fn new(peers: &'a RefCell<[bool; 256]>, manager: Arc<ChannelManager<'b, InMemoryChannelKeys>>, monitor: Arc<channelmonitor::SimpleManyChannelMonitor<OutPoint>>, handler: PeerManager<Peer<'a>>) -> Self {
152152
MoneyLossDetector {
153153
manager,
154154
monitor,
@@ -228,6 +228,8 @@ struct KeyProvider {
228228
counter: AtomicU64,
229229
}
230230
impl KeysInterface for KeyProvider {
231+
type ChanKeySigner = InMemoryChannelKeys;
232+
231233
fn get_node_secret(&self) -> SecretKey {
232234
self.node_secret.clone()
233235
}
@@ -244,10 +246,10 @@ impl KeysInterface for KeyProvider {
244246
PublicKey::from_secret_key(&secp_ctx, &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, 0]).unwrap())
245247
}
246248

247-
fn get_channel_keys(&self, inbound: bool) -> ChannelKeys {
249+
fn get_channel_keys(&self, inbound: bool) -> InMemoryChannelKeys {
248250
let ctr = self.counter.fetch_add(1, Ordering::Relaxed) as u8;
249251
if inbound {
250-
ChannelKeys {
252+
InMemoryChannelKeys {
251253
funding_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, 1, ctr]).unwrap(),
252254
revocation_base_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, ctr]).unwrap(),
253255
payment_base_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, ctr]).unwrap(),
@@ -256,7 +258,7 @@ impl KeysInterface for KeyProvider {
256258
commitment_seed: [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, 6, ctr],
257259
}
258260
} else {
259-
ChannelKeys {
261+
InMemoryChannelKeys {
260262
funding_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, 7, ctr]).unwrap(),
261263
revocation_base_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, 8, ctr]).unwrap(),
262264
payment_base_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, 9, ctr]).unwrap(),

lightning/src/chain/keysinterface.rs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ pub enum SpendableOutputDescriptor {
6868

6969
/// A trait to describe an object which can get user secrets and key material.
7070
pub trait KeysInterface: Send + Sync {
71+
/// A type which implements ChannelKeys which will be returned by get_channel_keys.
72+
type ChanKeySigner : ChannelKeys;
73+
7174
/// Get node secret key (aka node_id or network_key)
7275
fn get_node_secret(&self) -> SecretKey;
7376
/// Get destination redeemScript to encumber static protocol exit points.
@@ -76,7 +79,7 @@ pub trait KeysInterface: Send + Sync {
7679
fn get_shutdown_pubkey(&self) -> PublicKey;
7780
/// Get a new set of ChannelKeys for per-channel secrets. These MUST be unique even if you
7881
/// restarted with some stale data!
79-
fn get_channel_keys(&self, inbound: bool) -> ChannelKeys;
82+
fn get_channel_keys(&self, inbound: bool) -> Self::ChanKeySigner;
8083
/// Get a secret and PRNG seed for construting an onion packet
8184
fn get_onion_rand(&self) -> (SecretKey, [u8; 32]);
8285
/// Get a unique temporary channel id. Channels will be referred to by this until the funding
@@ -85,9 +88,33 @@ pub trait KeysInterface: Send + Sync {
8588
fn get_channel_id(&self) -> [u8; 32];
8689
}
8790

88-
/// Set of lightning keys needed to operate a channel as described in BOLT 3
91+
/// Set of lightning keys needed to operate a channel as described in BOLT 3.
92+
///
93+
/// If you're implementing a custom signer, you almost certainly want to implement
94+
/// Readable/Writable to serialize out a unique reference to this set of keys so
95+
/// that you can serialize the full ChannelManager object.
96+
///
97+
/// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly
98+
/// to the possibility of reentrancy issues by calling the user's code during our deserialization
99+
/// routine).
100+
pub trait ChannelKeys : Send {
101+
/// Gets the private key for the anchor tx
102+
fn funding_key<'a>(&'a self) -> &'a SecretKey;
103+
/// Gets the local secret key for blinded revocation pubkey
104+
fn revocation_base_key<'a>(&'a self) -> &'a SecretKey;
105+
/// Gets the local secret key used in commitment tx htlc outputs
106+
fn payment_base_key<'a>(&'a self) -> &'a SecretKey;
107+
/// Gets the local secret key used in HTLC tx
108+
fn delayed_payment_base_key<'a>(&'a self) -> &'a SecretKey;
109+
/// Gets the local htlc secret key used in commitment tx htlc outputs
110+
fn htlc_base_key<'a>(&'a self) -> &'a SecretKey;
111+
/// Gets the commitment seed
112+
fn commitment_seed<'a>(&'a self) -> &'a [u8; 32];
113+
}
114+
89115
#[derive(Clone)]
90-
pub struct ChannelKeys {
116+
/// A simple implementation of ChannelKeys that just keeps the private keys in memory.
117+
pub struct InMemoryChannelKeys {
91118
/// Private key of anchor tx
92119
pub funding_key: SecretKey,
93120
/// Local secret key for blinded revocation pubkey
@@ -102,7 +129,16 @@ pub struct ChannelKeys {
102129
pub commitment_seed: [u8; 32],
103130
}
104131

105-
impl_writeable!(ChannelKeys, 0, {
132+
impl ChannelKeys for InMemoryChannelKeys {
133+
fn funding_key(&self) -> &SecretKey { &self.funding_key }
134+
fn revocation_base_key(&self) -> &SecretKey { &self.revocation_base_key }
135+
fn payment_base_key(&self) -> &SecretKey { &self.payment_base_key }
136+
fn delayed_payment_base_key(&self) -> &SecretKey { &self.delayed_payment_base_key }
137+
fn htlc_base_key(&self) -> &SecretKey { &self.htlc_base_key }
138+
fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed }
139+
}
140+
141+
impl_writeable!(InMemoryChannelKeys, 0, {
106142
funding_key,
107143
revocation_base_key,
108144
payment_base_key,
@@ -203,6 +239,8 @@ impl KeysManager {
203239
}
204240

205241
impl KeysInterface for KeysManager {
242+
type ChanKeySigner = InMemoryChannelKeys;
243+
206244
fn get_node_secret(&self) -> SecretKey {
207245
self.node_secret.clone()
208246
}
@@ -215,7 +253,7 @@ impl KeysInterface for KeysManager {
215253
self.shutdown_pubkey.clone()
216254
}
217255

218-
fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys {
256+
fn get_channel_keys(&self, _inbound: bool) -> InMemoryChannelKeys {
219257
// We only seriously intend to rely on the channel_master_key for true secure
220258
// entropy, everything else just ensures uniqueness. We rely on the unique_start (ie
221259
// starting_time provided in the constructor) to be unique.
@@ -248,7 +286,7 @@ impl KeysInterface for KeysManager {
248286
let delayed_payment_base_key = key_step!(b"delayed payment base key", payment_base_key);
249287
let htlc_base_key = key_step!(b"HTLC base key", delayed_payment_base_key);
250288

251-
ChannelKeys {
289+
InMemoryChannelKeys {
252290
funding_key,
253291
revocation_base_key,
254292
payment_base_key,

lightning/src/ln/chan_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ pub const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
2020
// Various functions for key derivation and transaction creation for use within channels. Primarily
2121
// used in Channel and ChannelMonitor.
2222

23-
pub fn build_commitment_secret(commitment_seed: [u8; 32], idx: u64) -> [u8; 32] {
24-
let mut res: [u8; 32] = commitment_seed;
23+
pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] {
24+
let mut res: [u8; 32] = commitment_seed.clone();
2525
for i in 0..48 {
2626
let bitpos = 47 - i;
2727
if idx & (1 << bitpos) == (1 << bitpos) {

0 commit comments

Comments
 (0)