2
2
//! spendable on-chain outputs which the user owns and is responsible for using just as any other
3
3
//! on-chain output which is theirs.
4
4
5
- use bitcoin:: blockdata:: transaction:: { OutPoint , TxOut } ;
5
+ use bitcoin:: blockdata:: transaction:: { Transaction , OutPoint , TxOut } ;
6
6
use bitcoin:: blockdata:: script:: { Script , Builder } ;
7
7
use bitcoin:: blockdata:: opcodes;
8
8
use bitcoin:: network:: constants:: Network ;
9
9
use bitcoin:: util:: bip32:: { ExtendedPrivKey , ExtendedPubKey , ChildNumber } ;
10
+ use bitcoin:: util:: bip143;
10
11
11
12
use bitcoin_hashes:: { Hash , HashEngine } ;
12
13
use bitcoin_hashes:: sha256:: HashEngine as Sha256State ;
13
14
use bitcoin_hashes:: sha256:: Hash as Sha256 ;
14
15
use bitcoin_hashes:: hash160:: Hash as Hash160 ;
15
16
16
17
use secp256k1:: key:: { SecretKey , PublicKey } ;
17
- use secp256k1:: Secp256k1 ;
18
+ use secp256k1:: { Secp256k1 , Signature } ;
18
19
use secp256k1;
19
20
20
21
use util:: byte_utils;
21
22
use util:: logger:: Logger ;
22
23
24
+ use ln:: chan_utils;
25
+ use ln:: chan_utils:: { TxCreationKeys , HTLCOutputInCommitment } ;
26
+
23
27
use std:: sync:: Arc ;
24
28
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
25
29
@@ -68,6 +72,9 @@ pub enum SpendableOutputDescriptor {
68
72
69
73
/// A trait to describe an object which can get user secrets and key material.
70
74
pub trait KeysInterface : Send + Sync {
75
+ /// A type which implements ChannelKeys which will be returned by get_channel_keys.
76
+ type ChanKeySigner : ChannelKeys ;
77
+
71
78
/// Get node secret key (aka node_id or network_key)
72
79
fn get_node_secret ( & self ) -> SecretKey ;
73
80
/// Get destination redeemScript to encumber static protocol exit points.
@@ -76,7 +83,7 @@ pub trait KeysInterface: Send + Sync {
76
83
fn get_shutdown_pubkey ( & self ) -> PublicKey ;
77
84
/// Get a new set of ChannelKeys for per-channel secrets. These MUST be unique even if you
78
85
/// restarted with some stale data!
79
- fn get_channel_keys ( & self , inbound : bool ) -> ChannelKeys ;
86
+ fn get_channel_keys ( & self , inbound : bool ) -> Self :: ChanKeySigner ;
80
87
/// Get a secret and PRNG seed for construting an onion packet
81
88
fn get_onion_rand ( & self ) -> ( SecretKey , [ u8 ; 32 ] ) ;
82
89
/// Get a unique temporary channel id. Channels will be referred to by this until the funding
@@ -85,9 +92,59 @@ pub trait KeysInterface: Send + Sync {
85
92
fn get_channel_id ( & self ) -> [ u8 ; 32 ] ;
86
93
}
87
94
88
- /// Set of lightning keys needed to operate a channel as described in BOLT 3
95
+ /// Set of lightning keys needed to operate a channel as described in BOLT 3.
96
+ ///
97
+ /// Signing services could be implemented on a hardware wallet. In this case,
98
+ /// the current ChannelKeys would be a front-end on top of a communication
99
+ /// channel connected to your secure device and lightning key material wouldn't
100
+ /// reside on a hot server. Nevertheless, a this deployment would still need
101
+ /// to trust the ChannelManager to avoid loss of funds as this latest component
102
+ /// could ask to sign commitment transaction with HTLCs paying to attacker pubkeys.
103
+ ///
104
+ /// A more secure iteration would be to use hashlock (or payment points) to pair
105
+ /// invoice/incoming HTLCs with outgoing HTLCs to implement a no-trust-ChannelManager
106
+ /// at the price of more state and computation on the hardware wallet side. In the future,
107
+ /// we are looking forward to design such interface.
108
+ ///
109
+ /// In any case, ChannelMonitor or fallback watchtowers are always going to be trusted
110
+ /// to act, as liveness and breach reply correctness are always going to be hard requirements
111
+ /// of LN security model, orthogonal of key management issues.
112
+ ///
113
+ /// If you're implementing a custom signer, you almost certainly want to implement
114
+ /// Readable/Writable to serialize out a unique reference to this set of keys so
115
+ /// that you can serialize the full ChannelManager object.
116
+ ///
117
+ /// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly
118
+ /// to the possibility of reentrancy issues by calling the user's code during our deserialization
119
+ /// routine).
120
+ pub trait ChannelKeys : Send {
121
+ /// Gets the private key for the anchor tx
122
+ fn funding_key < ' a > ( & ' a self ) -> & ' a SecretKey ;
123
+ /// Gets the local secret key for blinded revocation pubkey
124
+ fn revocation_base_key < ' a > ( & ' a self ) -> & ' a SecretKey ;
125
+ /// Gets the local secret key used in to_remote output of remote commitment tx
126
+ /// (and also as part of obscured commitment number)
127
+ fn payment_base_key < ' a > ( & ' a self ) -> & ' a SecretKey ;
128
+ /// Gets the local secret key used in HTLC-Success/HTLC-Timeout txn and to_local output
129
+ fn delayed_payment_base_key < ' a > ( & ' a self ) -> & ' a SecretKey ;
130
+ /// Gets the local htlc secret key used in commitment tx htlc outputs
131
+ fn htlc_base_key < ' a > ( & ' a self ) -> & ' a SecretKey ;
132
+ /// Gets the commitment seed
133
+ fn commitment_seed < ' a > ( & ' a self ) -> & ' a [ u8 ; 32 ] ;
134
+
135
+ /// Create a signature for a remote commitment transaction and associated HTLC transactions.
136
+ ///
137
+ /// Note that if signing fails or is rejected, the channel will be force-closed.
138
+ ///
139
+ /// TODO: Document the things someone using this interface should enforce before signing.
140
+ /// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
141
+ /// making the callee generate it via some util function we expose)!
142
+ fn sign_remote_commitment < T : secp256k1:: Signing > ( & self , channel_value_satoshis : u64 , channel_funding_script : & Script , feerate_per_kw : u64 , commitment_tx : & Transaction , keys : & TxCreationKeys , htlcs : & [ & HTLCOutputInCommitment ] , to_self_delay : u16 , secp_ctx : & Secp256k1 < T > ) -> Result < ( Signature , Vec < Signature > ) , ( ) > ;
143
+ }
144
+
89
145
#[ derive( Clone ) ]
90
- pub struct ChannelKeys {
146
+ /// A simple implementation of ChannelKeys that just keeps the private keys in memory.
147
+ pub struct InMemoryChannelKeys {
91
148
/// Private key of anchor tx
92
149
pub funding_key : SecretKey ,
93
150
/// Local secret key for blinded revocation pubkey
@@ -102,7 +159,41 @@ pub struct ChannelKeys {
102
159
pub commitment_seed : [ u8 ; 32 ] ,
103
160
}
104
161
105
- impl_writeable ! ( ChannelKeys , 0 , {
162
+ impl ChannelKeys for InMemoryChannelKeys {
163
+ fn funding_key ( & self ) -> & SecretKey { & self . funding_key }
164
+ fn revocation_base_key ( & self ) -> & SecretKey { & self . revocation_base_key }
165
+ fn payment_base_key ( & self ) -> & SecretKey { & self . payment_base_key }
166
+ fn delayed_payment_base_key ( & self ) -> & SecretKey { & self . delayed_payment_base_key }
167
+ fn htlc_base_key ( & self ) -> & SecretKey { & self . htlc_base_key }
168
+ fn commitment_seed ( & self ) -> & [ u8 ; 32 ] { & self . commitment_seed }
169
+
170
+
171
+ fn sign_remote_commitment < T : secp256k1:: Signing > ( & self , channel_value_satoshis : u64 , channel_funding_script : & Script , feerate_per_kw : u64 , commitment_tx : & Transaction , keys : & TxCreationKeys , htlcs : & [ & HTLCOutputInCommitment ] , to_self_delay : u16 , secp_ctx : & Secp256k1 < T > ) -> Result < ( Signature , Vec < Signature > ) , ( ) > {
172
+ if commitment_tx. input . len ( ) != 1 { return Err ( ( ) ) ; }
173
+ let commitment_sighash = hash_to_message ! ( & bip143:: SighashComponents :: new( & commitment_tx) . sighash_all( & commitment_tx. input[ 0 ] , & channel_funding_script, channel_value_satoshis) [ ..] ) ;
174
+ let commitment_sig = secp_ctx. sign ( & commitment_sighash, & self . funding_key ) ;
175
+
176
+ let commitment_txid = commitment_tx. txid ( ) ;
177
+
178
+ let mut htlc_sigs = Vec :: with_capacity ( htlcs. len ( ) ) ;
179
+ for ref htlc in htlcs {
180
+ if let Some ( _) = htlc. transaction_output_index {
181
+ let htlc_tx = chan_utils:: build_htlc_transaction ( & commitment_txid, feerate_per_kw, to_self_delay, htlc, & keys. a_delayed_payment_key , & keys. revocation_key ) ;
182
+ let htlc_redeemscript = chan_utils:: get_htlc_redeemscript ( & htlc, & keys) ;
183
+ let htlc_sighash = hash_to_message ! ( & bip143:: SighashComponents :: new( & htlc_tx) . sighash_all( & htlc_tx. input[ 0 ] , & htlc_redeemscript, htlc. amount_msat / 1000 ) [ ..] ) ;
184
+ let our_htlc_key = match chan_utils:: derive_private_key ( & secp_ctx, & keys. per_commitment_point , & self . htlc_base_key ) {
185
+ Ok ( s) => s,
186
+ Err ( _) => return Err ( ( ) ) ,
187
+ } ;
188
+ htlc_sigs. push ( secp_ctx. sign ( & htlc_sighash, & our_htlc_key) ) ;
189
+ }
190
+ }
191
+
192
+ Ok ( ( commitment_sig, htlc_sigs) )
193
+ }
194
+ }
195
+
196
+ impl_writeable ! ( InMemoryChannelKeys , 0 , {
106
197
funding_key,
107
198
revocation_base_key,
108
199
payment_base_key,
@@ -203,6 +294,8 @@ impl KeysManager {
203
294
}
204
295
205
296
impl KeysInterface for KeysManager {
297
+ type ChanKeySigner = InMemoryChannelKeys ;
298
+
206
299
fn get_node_secret ( & self ) -> SecretKey {
207
300
self . node_secret . clone ( )
208
301
}
@@ -215,7 +308,7 @@ impl KeysInterface for KeysManager {
215
308
self . shutdown_pubkey . clone ( )
216
309
}
217
310
218
- fn get_channel_keys ( & self , _inbound : bool ) -> ChannelKeys {
311
+ fn get_channel_keys ( & self , _inbound : bool ) -> InMemoryChannelKeys {
219
312
// We only seriously intend to rely on the channel_master_key for true secure
220
313
// entropy, everything else just ensures uniqueness. We rely on the unique_start (ie
221
314
// starting_time provided in the constructor) to be unique.
@@ -248,7 +341,7 @@ impl KeysInterface for KeysManager {
248
341
let delayed_payment_base_key = key_step ! ( b"delayed payment base key" , payment_base_key) ;
249
342
let htlc_base_key = key_step ! ( b"HTLC base key" , delayed_payment_base_key) ;
250
343
251
- ChannelKeys {
344
+ InMemoryChannelKeys {
252
345
funding_key,
253
346
revocation_base_key,
254
347
payment_base_key,
0 commit comments