forked from lightningdevkit/rust-lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchannel.rs
3164 lines (2742 loc) · 188 KB
/
channel.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::script::{Script,Builder};
use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
use bitcoin::blockdata::opcodes;
use bitcoin::util::hash::{Sha256dHash, Hash160};
use bitcoin::util::bip143;
use bitcoin::network::serialize::BitcoinHash;
use secp256k1::key::{PublicKey,SecretKey};
use secp256k1::{Secp256k1,Message,Signature};
use secp256k1;
use crypto::digest::Digest;
use crypto::hkdf::{hkdf_extract,hkdf_expand};
use ln::msgs;
use ln::msgs::{ErrorAction, HandleError, MsgEncodable};
use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, PendingForwardHTLCInfo, HTLCFailReason, HTLCFailureMsg};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::transaction::OutPoint;
use util::{transaction_utils,rng};
use util::sha2::Sha256;
use util::logger::Logger;
use util::errors::APIError;
use std;
use std::default::Default;
use std::{cmp,mem};
use std::time::Instant;
use std::sync::{Arc};
pub struct ChannelKeys {
pub funding_key: SecretKey,
pub revocation_base_key: SecretKey,
pub payment_base_key: SecretKey,
pub delayed_payment_base_key: SecretKey,
pub htlc_base_key: SecretKey,
pub channel_close_key: SecretKey,
pub channel_monitor_claim_key: SecretKey,
pub commitment_seed: [u8; 32],
}
impl ChannelKeys {
pub fn new_from_seed(seed: &[u8; 32]) -> Result<ChannelKeys, secp256k1::Error> {
let mut prk = [0; 32];
hkdf_extract(Sha256::new(), b"rust-lightning key gen salt", seed, &mut prk);
let secp_ctx = Secp256k1::without_caps();
let mut okm = [0; 32];
hkdf_expand(Sha256::new(), &prk, b"rust-lightning funding key info", &mut okm);
let funding_key = SecretKey::from_slice(&secp_ctx, &okm)?;
hkdf_expand(Sha256::new(), &prk, b"rust-lightning revocation base key info", &mut okm);
let revocation_base_key = SecretKey::from_slice(&secp_ctx, &okm)?;
hkdf_expand(Sha256::new(), &prk, b"rust-lightning payment base key info", &mut okm);
let payment_base_key = SecretKey::from_slice(&secp_ctx, &okm)?;
hkdf_expand(Sha256::new(), &prk, b"rust-lightning delayed payment base key info", &mut okm);
let delayed_payment_base_key = SecretKey::from_slice(&secp_ctx, &okm)?;
hkdf_expand(Sha256::new(), &prk, b"rust-lightning htlc base key info", &mut okm);
let htlc_base_key = SecretKey::from_slice(&secp_ctx, &okm)?;
hkdf_expand(Sha256::new(), &prk, b"rust-lightning channel close key info", &mut okm);
let channel_close_key = SecretKey::from_slice(&secp_ctx, &okm)?;
hkdf_expand(Sha256::new(), &prk, b"rust-lightning channel monitor claim key info", &mut okm);
let channel_monitor_claim_key = SecretKey::from_slice(&secp_ctx, &okm)?;
hkdf_expand(Sha256::new(), &prk, b"rust-lightning local commitment seed info", &mut okm);
Ok(ChannelKeys {
funding_key: funding_key,
revocation_base_key: revocation_base_key,
payment_base_key: payment_base_key,
delayed_payment_base_key: delayed_payment_base_key,
htlc_base_key: htlc_base_key,
channel_close_key: channel_close_key,
channel_monitor_claim_key: channel_monitor_claim_key,
commitment_seed: okm
})
}
}
#[derive(PartialEq)]
enum InboundHTLCState {
/// Added by remote, to be included in next local commitment tx.
RemoteAnnounced,
/// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
/// accept this HTLC. Implies AwaitingRemoteRevoke.
/// We also have not yet included this HTLC in a commitment_signed message, and are waiting on
/// a remote revoke_and_ack on a previous state before we can do so.
AwaitingRemoteRevokeToAnnounce,
/// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
/// accept this HTLC. Implies AwaitingRemoteRevoke.
/// We have included this HTLC in our latest commitment_signed and are now just waiting on a
/// revoke_and_ack.
AwaitingAnnouncedRemoteRevoke,
Committed,
/// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we
/// created it we would have put it in the holding cell instead). When they next revoke_and_ack
/// we'll drop it.
/// Note that we have to keep an eye on the HTLC until we've received a broadcastable
/// commitment transaction without it as otherwise we'll have to force-close the channel to
/// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim
/// anyway). That said, ChannelMonitor does this for us (see
/// ChannelMonitor::would_broadcast_at_height) so we actually remove the HTLC from our own
/// local state before then, once we're sure that the next commitment_signed and
/// ChannelMonitor::provide_latest_local_commitment_tx_info will not include this HTLC.
LocalRemoved,
}
struct InboundHTLCOutput {
htlc_id: u64,
amount_msat: u64,
cltv_expiry: u32,
payment_hash: [u8; 32],
state: InboundHTLCState,
/// If we're in LocalRemoved, set to true if we fulfilled the HTLC, and can claim money
local_removed_fulfilled: bool,
/// state pre-Committed implies pending_forward_state, otherwise it must be None
pending_forward_state: Option<PendingHTLCStatus>,
}
#[derive(PartialEq)]
enum OutboundHTLCState {
/// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we
/// created it we would have put it in the holding cell instead). When they next revoke_and_ack
/// we will promote to Committed (note that they may not accept it until the next time we
/// revoke, but we dont really care about that:
/// * they've revoked, so worst case we can announce an old state and get our (option on)
/// money back (though we wont), and,
/// * we'll send them a revoke when they send a commitment_signed, and since only they're
/// allowed to remove it, the "can only be removed once committed on both sides" requirement
/// doesn't matter to us and its up to them to enforce it, worst-case they jump ahead but
/// we'll never get out of sync).
LocalAnnounced,
Committed,
/// Remote removed this (outbound) HTLC. We're waiting on their commitment_signed to finalize
/// the change (though they'll need to revoke before we fail the payment).
RemoteRemoved,
/// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
/// can do any backwards failing. Implies AwaitingRemoteRevoke.
/// We also have not yet removed this HTLC in a commitment_signed message, and are waiting on a
/// remote revoke_and_ack on a previous state before we can do so.
AwaitingRemoteRevokeToRemove,
/// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but
/// the remote side hasn't yet revoked their previous state, which we need them to do before we
/// can do any backwards failing. Implies AwaitingRemoteRevoke.
/// We have removed this HTLC in our latest commitment_signed and are now just waiting on a
/// revoke_and_ack to drop completely.
AwaitingRemovedRemoteRevoke,
}
struct OutboundHTLCOutput {
htlc_id: u64,
amount_msat: u64,
cltv_expiry: u32,
payment_hash: [u8; 32],
state: OutboundHTLCState,
source: HTLCSource,
/// If we're in a removed state, set if they failed, otherwise None
fail_reason: Option<HTLCFailReason>,
}
macro_rules! get_htlc_in_commitment {
($htlc: expr, $offered: expr) => {
HTLCOutputInCommitment {
offered: $offered,
amount_msat: $htlc.amount_msat,
cltv_expiry: $htlc.cltv_expiry,
payment_hash: $htlc.payment_hash,
transaction_output_index: 0
}
}
}
/// See AwaitingRemoteRevoke ChannelState for more info
enum HTLCUpdateAwaitingACK {
AddHTLC {
// always outbound
amount_msat: u64,
cltv_expiry: u32,
payment_hash: [u8; 32],
source: HTLCSource,
onion_routing_packet: msgs::OnionPacket,
time_created: Instant, //TODO: Some kind of timeout thing-a-majig
},
ClaimHTLC {
payment_preimage: [u8; 32],
htlc_id: u64,
},
FailHTLC {
htlc_id: u64,
err_packet: msgs::OnionErrorPacket,
},
}
enum ChannelState {
/// Implies we have (or are prepared to) send our open_channel/accept_channel message
OurInitSent = (1 << 0),
/// Implies we have received their open_channel/accept_channel message
TheirInitSent = (1 << 1),
/// We have sent funding_created and are awaiting a funding_signed to advance to FundingSent.
/// Note that this is nonsense for an inbound channel as we immediately generate funding_signed
/// upon receipt of funding_created, so simply skip this state.
FundingCreated = 4,
/// Set when we have received/sent funding_created and funding_signed and are thus now waiting
/// on the funding transaction to confirm. The FundingLocked flags are set to indicate when we
/// and our counterparty consider the funding transaction confirmed.
FundingSent = 8,
/// Flag which can be set on FundingSent to indicate they sent us a funding_locked message.
/// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded.
TheirFundingLocked = (1 << 4),
/// Flag which can be set on FundingSent to indicate we sent them a funding_locked message.
/// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded.
OurFundingLocked = (1 << 5),
ChannelFunded = 64,
/// Flag which implies that we have sent a commitment_signed but are awaiting the responding
/// revoke_and_ack message. During this time period, we can't generate new commitment_signed
/// messages as then we will be unable to determine which HTLCs they included in their
/// revoke_and_ack implicit ACK, so instead we have to hold them away temporarily to be sent
/// later.
/// Flag is set on ChannelFunded.
AwaitingRemoteRevoke = (1 << 7),
/// Flag which is set on ChannelFunded or FundingSent after receiving a shutdown message from
/// the remote end. If set, they may not add any new HTLCs to the channel, and we are expected
/// to respond with our own shutdown message when possible.
RemoteShutdownSent = (1 << 8),
/// Flag which is set on ChannelFunded or FundingSent after sending a shutdown message. At this
/// point, we may not add any new HTLCs to the channel.
/// TODO: Investigate some kind of timeout mechanism by which point the remote end must provide
/// us their shutdown.
LocalShutdownSent = (1 << 9),
/// We've successfully negotiated a closing_signed dance. At this point ChannelManager is about
/// to drop us, but we store this anyway.
ShutdownComplete = (1 << 10),
}
const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 | ChannelState::RemoteShutdownSent as u32);
// TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking
// has been completed, and then turn into a Channel to get compiler-time enforcement of things like
// calling channel_id() before we're set up or things like get_outbound_funding_signed on an
// inbound channel.
pub struct Channel {
user_id: u64,
channel_id: [u8; 32],
channel_state: u32,
channel_outbound: bool,
secp_ctx: Secp256k1<secp256k1::All>,
announce_publicly: bool,
channel_value_satoshis: u64,
local_keys: ChannelKeys,
// Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction
// generation start at 0 and count up...this simplifies some parts of implementation at the
// cost of others, but should really just be changed.
cur_local_commitment_transaction_number: u64,
cur_remote_commitment_transaction_number: u64,
value_to_self_msat: u64, // Excluding all pending_htlcs, excluding fees
pending_inbound_htlcs: Vec<InboundHTLCOutput>,
pending_outbound_htlcs: Vec<OutboundHTLCOutput>,
holding_cell_htlc_updates: Vec<HTLCUpdateAwaitingACK>,
next_local_htlc_id: u64,
next_remote_htlc_id: u64,
channel_update_count: u32,
feerate_per_kw: u64,
#[cfg(test)]
// Used in ChannelManager's tests to send a revoked transaction
pub last_local_commitment_txn: Vec<Transaction>,
#[cfg(not(test))]
last_local_commitment_txn: Vec<Transaction>,
last_sent_closing_fee: Option<(u64, u64)>, // (feerate, fee)
/// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this
/// to detect unconfirmation after a serialize-unserialize roudtrip where we may not see a full
/// series of block_connected/block_disconnected calls. Obviously this is not a guarantee as we
/// could miss the funding_tx_confirmed_in block as well, but it serves as a useful fallback.
funding_tx_confirmed_in: Option<Sha256dHash>,
short_channel_id: Option<u64>,
/// Used to deduplicate block_connected callbacks
last_block_connected: Sha256dHash,
funding_tx_confirmations: u64,
their_dust_limit_satoshis: u64,
our_dust_limit_satoshis: u64,
their_max_htlc_value_in_flight_msat: u64,
//get_our_max_htlc_value_in_flight_msat(): u64,
their_channel_reserve_satoshis: u64,
//get_our_channel_reserve_satoshis(): u64,
their_htlc_minimum_msat: u64,
our_htlc_minimum_msat: u64,
their_to_self_delay: u16,
//implied by BREAKDOWN_TIMEOUT: our_to_self_delay: u16,
their_max_accepted_htlcs: u16,
//implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16,
their_funding_pubkey: Option<PublicKey>,
their_revocation_basepoint: Option<PublicKey>,
their_payment_basepoint: Option<PublicKey>,
their_delayed_payment_basepoint: Option<PublicKey>,
their_htlc_basepoint: Option<PublicKey>,
their_cur_commitment_point: Option<PublicKey>,
their_prev_commitment_point: Option<PublicKey>,
their_node_id: PublicKey,
their_shutdown_scriptpubkey: Option<Script>,
channel_monitor: ChannelMonitor,
logger: Arc<Logger>,
}
const OUR_MAX_HTLCS: u16 = 5; //TODO
/// Confirmation count threshold at which we close a channel. Ideally we'd keep the channel around
/// on ice until the funding transaction gets more confirmations, but the LN protocol doesn't
/// really allow for this, so instead we're stuck closing it out at that point.
const UNCONF_THRESHOLD: u32 = 6;
/// The amount of time we require our counterparty wait to claim their money (ie time between when
/// we, or our watchtower, must check for them having broadcast a theft transaction).
const BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 7; //TODO?
/// The amount of time we're willing to wait to claim money back to us
const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 14;
const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 4, script len: 1, witness lengths: (3+1)/4, sig: 73/4, if-selector: 1, redeemScript: (6 ops + 2*33 pubkeys + 1*2 delay)/4
const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: 4, script len: 1, witness lengths: 3/4, sig: 73/4, pubkey: 33/4, output: 31 (TODO: Wrong? Useless?)
/// Maximmum `funding_satoshis` value, according to the BOLT #2 specification
/// it's 2^24.
pub const MAX_FUNDING_SATOSHIS: u64 = (1 << 24);
macro_rules! secp_call {
( $res: expr, $err: expr, $chan_id: expr ) => {
match $res {
Ok(key) => key,
Err(_) => return Err(HandleError {err: $err, action: Some(msgs::ErrorAction::SendErrorMessage {msg: msgs::ErrorMessage {channel_id: $chan_id, data: $err.to_string()}})})
}
};
}
macro_rules! secp_derived_key {
( $res: expr, $chan_id: expr ) => {
secp_call!($res, "Derived invalid key, peer is maliciously selecting parameters", $chan_id)
}
}
impl Channel {
// Convert constants + channel value to limits:
fn get_our_max_htlc_value_in_flight_msat(channel_value_satoshis: u64) -> u64 {
channel_value_satoshis * 1000 / 10 //TODO
}
/// Guaranteed to return a value no larger than channel_value_satoshis
fn get_our_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 {
let (q, _) = channel_value_satoshis.overflowing_div(100);
cmp::min(channel_value_satoshis, cmp::max(q, 1000)) //TODO
}
fn derive_our_dust_limit_satoshis(at_open_background_feerate: u64) -> u64 {
at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000 //TODO
}
fn derive_our_htlc_minimum_msat(_at_open_channel_feerate_per_kw: u64) -> u64 {
1000 // TODO
}
fn derive_minimum_depth(_channel_value_satoshis_msat: u64, _value_to_self_msat: u64) -> u32 {
// Note that in order to comply with BOLT 7 announcement_signatures requirements this must
// be at least 6.
const CONF_TARGET: u32 = 12; //TODO: Should be much higher
CONF_TARGET
}
fn derive_maximum_minimum_depth(_channel_value_satoshis_msat: u64, _value_to_self_msat: u64) -> u32 {
const CONF_TARGET: u32 = 12; //TODO: Should be much higher
CONF_TARGET * 2
}
// Constructors:
pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, announce_publicly: bool, user_id: u64, logger: Arc<Logger>) -> Result<Channel, APIError> {
if channel_value_satoshis >= MAX_FUNDING_SATOSHIS {
return Err(APIError::APIMisuseError{err: "funding value > 2^24"});
}
if push_msat > channel_value_satoshis * 1000 {
return Err(APIError::APIMisuseError{err: "push value > channel value"});
}
let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
if Channel::get_our_channel_reserve_satoshis(channel_value_satoshis) < Channel::derive_our_dust_limit_satoshis(background_feerate) {
return Err(APIError::FeeRateTooHigh{err: format!("Not enough reserve above dust limit can be found at current fee rate({})", background_feerate), feerate: background_feerate});
}
let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
let secp_ctx = Secp256k1::new();
let our_channel_monitor_claim_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&secp_ctx, &chan_keys.channel_monitor_claim_key).serialize());
let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script();
let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key,
&PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key),
&chan_keys.htlc_base_key,
BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script);
Ok(Channel {
user_id: user_id,
channel_id: rng::rand_u832(),
channel_state: ChannelState::OurInitSent as u32,
channel_outbound: true,
secp_ctx: secp_ctx,
announce_publicly: announce_publicly,
channel_value_satoshis: channel_value_satoshis,
local_keys: chan_keys,
cur_local_commitment_transaction_number: (1 << 48) - 1,
cur_remote_commitment_transaction_number: (1 << 48) - 1,
value_to_self_msat: channel_value_satoshis * 1000 - push_msat,
pending_inbound_htlcs: Vec::new(),
pending_outbound_htlcs: Vec::new(),
holding_cell_htlc_updates: Vec::new(),
next_local_htlc_id: 0,
next_remote_htlc_id: 0,
channel_update_count: 1,
last_local_commitment_txn: Vec::new(),
last_sent_closing_fee: None,
funding_tx_confirmed_in: None,
short_channel_id: None,
last_block_connected: Default::default(),
funding_tx_confirmations: 0,
feerate_per_kw: feerate,
their_dust_limit_satoshis: 0,
our_dust_limit_satoshis: Channel::derive_our_dust_limit_satoshis(background_feerate),
their_max_htlc_value_in_flight_msat: 0,
their_channel_reserve_satoshis: 0,
their_htlc_minimum_msat: 0,
our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(feerate),
their_to_self_delay: 0,
their_max_accepted_htlcs: 0,
their_funding_pubkey: None,
their_revocation_basepoint: None,
their_payment_basepoint: None,
their_delayed_payment_basepoint: None,
their_htlc_basepoint: None,
their_cur_commitment_point: None,
their_prev_commitment_point: None,
their_node_id: their_node_id,
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
logger,
})
}
fn check_remote_fee(fee_estimator: &FeeEstimator, feerate_per_kw: u32) -> Result<(), HandleError> {
if (feerate_per_kw as u64) < fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) {
return Err(HandleError{err: "Peer's feerate much too low", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
}
if (feerate_per_kw as u64) > fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * 2 {
return Err(HandleError{err: "Peer's feerate much too high", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
}
Ok(())
}
/// Creates a new channel from a remote sides' request for one.
/// Assumes chain_hash has already been checked and corresponds with what we expect!
/// Generally prefers to take the DisconnectPeer action on failure, as a notice to the sender
/// that we're rejecting the new channel.
pub fn new_from_req(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, require_announce: bool, allow_announce: bool, logger: Arc<Logger>) -> Result<Channel, HandleError> {
macro_rules! return_error_message {
( $msg: expr ) => {
return Err(HandleError{err: $msg, action: Some(msgs::ErrorAction::SendErrorMessage{ msg: msgs::ErrorMessage { channel_id: msg.temporary_channel_id, data: $msg.to_string() }})});
}
}
// Check sanity of message fields:
if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS {
return_error_message!("funding value > 2^24");
}
if msg.channel_reserve_satoshis > msg.funding_satoshis {
return_error_message!("Bogus channel_reserve_satoshis");
}
if msg.push_msat > (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 {
return_error_message!("push_msat larger than funding value");
}
if msg.dust_limit_satoshis > msg.funding_satoshis {
return_error_message!("Peer never wants payout outputs?");
}
if msg.dust_limit_satoshis > msg.channel_reserve_satoshis {
return_error_message!("Bogus; channel reserve is less than dust limit");
}
if msg.htlc_minimum_msat >= (msg.funding_satoshis - msg.channel_reserve_satoshis) * 1000 {
return_error_message!("Miminum htlc value is full channel value");
}
Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw).map_err(|e|
HandleError{err: e.err, action: Some(msgs::ErrorAction::SendErrorMessage{ msg: msgs::ErrorMessage { channel_id: msg.temporary_channel_id, data: e.err.to_string() }})}
)?;
if msg.to_self_delay > MAX_LOCAL_BREAKDOWN_TIMEOUT {
return_error_message!("They wanted our payments to be delayed by a needlessly long period");
}
if msg.max_accepted_htlcs < 1 {
return_error_message!("0 max_accpted_htlcs makes for a useless channel");
}
if msg.max_accepted_htlcs > 483 {
return_error_message!("max_accpted_htlcs > 483");
}
// Convert things into internal flags and prep our state:
let their_announce = if (msg.channel_flags & 1) == 1 { true } else { false };
if require_announce && !their_announce {
return_error_message!("Peer tried to open unannounced channel, but we require public ones");
}
if !allow_announce && their_announce {
return_error_message!("Peer tried to open announced channel, but we require private ones");
}
let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
let our_dust_limit_satoshis = Channel::derive_our_dust_limit_satoshis(background_feerate);
let our_channel_reserve_satoshis = Channel::get_our_channel_reserve_satoshis(msg.funding_satoshis);
if our_channel_reserve_satoshis < our_dust_limit_satoshis {
return_error_message!("Suitalbe channel reserve not found. aborting");
}
if msg.channel_reserve_satoshis < our_dust_limit_satoshis {
return_error_message!("channel_reserve_satoshis too small");
}
if our_channel_reserve_satoshis < msg.dust_limit_satoshis {
return_error_message!("Dust limit too high for our channel reserve");
}
// check if the funder's amount for the initial commitment tx is sufficient
// for full fee payment
let funders_amount_msat = msg.funding_satoshis * 1000 - msg.push_msat;
if funders_amount_msat < background_feerate * COMMITMENT_TX_BASE_WEIGHT {
return_error_message!("Insufficient funding amount for initial commitment");
}
let to_local_msat = msg.push_msat;
let to_remote_msat = funders_amount_msat - background_feerate * COMMITMENT_TX_BASE_WEIGHT;
if to_local_msat <= msg.channel_reserve_satoshis * 1000 && to_remote_msat <= our_channel_reserve_satoshis * 1000 {
return_error_message!("Insufficient funding amount for initial commitment");
}
let secp_ctx = Secp256k1::new();
let our_channel_monitor_claim_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&secp_ctx, &chan_keys.channel_monitor_claim_key).serialize());
let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script();
let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key,
&PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key),
&chan_keys.htlc_base_key,
BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script);
channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint);
channel_monitor.set_their_to_self_delay(msg.to_self_delay);
let mut chan = Channel {
user_id: user_id,
channel_id: msg.temporary_channel_id,
channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32),
channel_outbound: false,
secp_ctx: secp_ctx,
announce_publicly: their_announce,
local_keys: chan_keys,
cur_local_commitment_transaction_number: (1 << 48) - 1,
cur_remote_commitment_transaction_number: (1 << 48) - 1,
value_to_self_msat: msg.push_msat,
pending_inbound_htlcs: Vec::new(),
pending_outbound_htlcs: Vec::new(),
holding_cell_htlc_updates: Vec::new(),
next_local_htlc_id: 0,
next_remote_htlc_id: 0,
channel_update_count: 1,
last_local_commitment_txn: Vec::new(),
last_sent_closing_fee: None,
funding_tx_confirmed_in: None,
short_channel_id: None,
last_block_connected: Default::default(),
funding_tx_confirmations: 0,
feerate_per_kw: msg.feerate_per_kw as u64,
channel_value_satoshis: msg.funding_satoshis,
their_dust_limit_satoshis: msg.dust_limit_satoshis,
our_dust_limit_satoshis: our_dust_limit_satoshis,
their_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000),
their_channel_reserve_satoshis: msg.channel_reserve_satoshis,
their_htlc_minimum_msat: msg.htlc_minimum_msat,
our_htlc_minimum_msat: Channel::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64),
their_to_self_delay: msg.to_self_delay,
their_max_accepted_htlcs: msg.max_accepted_htlcs,
their_funding_pubkey: Some(msg.funding_pubkey),
their_revocation_basepoint: Some(msg.revocation_basepoint),
their_payment_basepoint: Some(msg.payment_basepoint),
their_delayed_payment_basepoint: Some(msg.delayed_payment_basepoint),
their_htlc_basepoint: Some(msg.htlc_basepoint),
their_cur_commitment_point: Some(msg.first_per_commitment_point),
their_prev_commitment_point: None,
their_node_id: their_node_id,
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
logger,
};
let obscure_factor = chan.get_commitment_transaction_number_obscure_factor();
chan.channel_monitor.set_commitment_obscure_factor(obscure_factor);
Ok(chan)
}
// Utilities to derive keys:
fn build_local_commitment_secret(&self, idx: u64) -> SecretKey {
let res = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, idx);
SecretKey::from_slice(&self.secp_ctx, &res).unwrap()
}
// Utilities to build transactions:
fn get_commitment_transaction_number_obscure_factor(&self) -> u64 {
let mut sha = Sha256::new();
let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key);
if self.channel_outbound {
sha.input(&our_payment_basepoint.serialize());
sha.input(&self.their_payment_basepoint.unwrap().serialize());
} else {
sha.input(&self.their_payment_basepoint.unwrap().serialize());
sha.input(&our_payment_basepoint.serialize());
}
let mut res = [0; 32];
sha.result(&mut res);
((res[26] as u64) << 5*8) |
((res[27] as u64) << 4*8) |
((res[28] as u64) << 3*8) |
((res[29] as u64) << 2*8) |
((res[30] as u64) << 1*8) |
((res[31] as u64) << 0*8)
}
/// Transaction nomenclature is somewhat confusing here as there are many different cases - a
/// transaction is referred to as "a's transaction" implying that a will be able to broadcast
/// the transaction. Thus, b will generally be sending a signature over such a transaction to
/// a, and a can revoke the transaction by providing b the relevant per_commitment_secret. As
/// such, a transaction is generally the result of b increasing the amount paid to a (or adding
/// an HTLC to a).
/// @local is used only to convert relevant internal structures which refer to remote vs local
/// to decide value of outputs and direction of HTLCs.
/// @generated_by_local is used to determine *which* HTLCs to include - noting that the HTLC
/// state may indicate that one peer has informed the other that they'd like to add an HTLC but
/// have not yet committed it. Such HTLCs will only be included in transactions which are being
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
/// which peer generated this transaction and "to whom" this transaction flows.
#[inline]
fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool) -> (Transaction, Vec<HTLCOutputInCommitment>) {
let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (0xffffffffffff - commitment_number);
let txins = {
let mut ins: Vec<TxIn> = Vec::new();
ins.push(TxIn {
previous_output: self.channel_monitor.get_funding_txo().unwrap().into_bitcoin_outpoint(),
script_sig: Script::new(),
sequence: ((0x80 as u32) << 8*3) | ((obscured_commitment_transaction_number >> 3*8) as u32),
witness: Vec::new(),
});
ins
};
let mut txouts: Vec<(TxOut, Option<HTLCOutputInCommitment>)> = Vec::with_capacity(self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len() + 2);
let dust_limit_satoshis = if local { self.our_dust_limit_satoshis } else { self.their_dust_limit_satoshis };
let mut remote_htlc_total_msat = 0;
let mut local_htlc_total_msat = 0;
let mut value_to_self_msat_offset = 0;
macro_rules! add_htlc_output {
($htlc: expr, $outbound: expr) => {
if $outbound == local { // "offered HTLC output"
if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) {
let htlc_in_tx = get_htlc_in_commitment!($htlc, true);
txouts.push((TxOut {
script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
value: $htlc.amount_msat / 1000
}, Some(htlc_in_tx)));
}
} else {
if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) {
let htlc_in_tx = get_htlc_in_commitment!($htlc, false);
txouts.push((TxOut { // "received HTLC output"
script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
value: $htlc.amount_msat / 1000
}, Some(htlc_in_tx)));
}
}
}
}
for ref htlc in self.pending_inbound_htlcs.iter() {
let include = match htlc.state {
InboundHTLCState::RemoteAnnounced => !generated_by_local,
InboundHTLCState::AwaitingRemoteRevokeToAnnounce => !generated_by_local,
InboundHTLCState::AwaitingAnnouncedRemoteRevoke => true,
InboundHTLCState::Committed => true,
InboundHTLCState::LocalRemoved => !generated_by_local,
};
if include {
add_htlc_output!(htlc, false);
remote_htlc_total_msat += htlc.amount_msat;
} else {
match htlc.state {
InboundHTLCState::LocalRemoved => {
if generated_by_local && htlc.local_removed_fulfilled {
value_to_self_msat_offset += htlc.amount_msat as i64;
}
},
_ => {},
}
}
}
for ref htlc in self.pending_outbound_htlcs.iter() {
let include = match htlc.state {
OutboundHTLCState::LocalAnnounced => generated_by_local,
OutboundHTLCState::Committed => true,
OutboundHTLCState::RemoteRemoved => generated_by_local,
OutboundHTLCState::AwaitingRemoteRevokeToRemove => generated_by_local,
OutboundHTLCState::AwaitingRemovedRemoteRevoke => false,
};
if include {
add_htlc_output!(htlc, true);
local_htlc_total_msat += htlc.amount_msat;
} else {
match htlc.state {
OutboundHTLCState::AwaitingRemoteRevokeToRemove|OutboundHTLCState::AwaitingRemovedRemoteRevoke => {
if htlc.fail_reason.is_none() {
value_to_self_msat_offset -= htlc.amount_msat as i64;
}
},
OutboundHTLCState::RemoteRemoved => {
if !generated_by_local && htlc.fail_reason.is_none() {
value_to_self_msat_offset -= htlc.amount_msat as i64;
}
},
_ => {},
}
}
}
let total_fee: u64 = self.feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
let value_to_self: i64 = ((self.value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset) / 1000 - if self.channel_outbound { total_fee as i64 } else { 0 };
let value_to_remote: i64 = (((self.channel_value_satoshis * 1000 - self.value_to_self_msat - remote_htlc_total_msat) as i64 - value_to_self_msat_offset) / 1000) - if self.channel_outbound { 0 } else { total_fee as i64 };
let value_to_a = if local { value_to_self } else { value_to_remote };
let value_to_b = if local { value_to_remote } else { value_to_self };
if value_to_a >= (dust_limit_satoshis as i64) {
txouts.push((TxOut {
script_pubkey: chan_utils::get_revokeable_redeemscript(&keys.revocation_key,
if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT },
&keys.a_delayed_payment_key).to_v0_p2wsh(),
value: value_to_a as u64
}, None));
}
if value_to_b >= (dust_limit_satoshis as i64) {
txouts.push((TxOut {
script_pubkey: Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0)
.push_slice(&Hash160::from_data(&keys.b_payment_key.serialize())[..])
.into_script(),
value: value_to_b as u64
}, None));
}
transaction_utils::sort_outputs(&mut txouts);
let mut outputs: Vec<TxOut> = Vec::with_capacity(txouts.len());
let mut htlcs_used: Vec<HTLCOutputInCommitment> = Vec::with_capacity(txouts.len());
for (idx, out) in txouts.drain(..).enumerate() {
outputs.push(out.0);
if let Some(out_htlc) = out.1 {
htlcs_used.push(out_htlc);
htlcs_used.last_mut().unwrap().transaction_output_index = idx as u32;
}
}
(Transaction {
version: 2,
lock_time: ((0x20 as u32) << 8*3) | ((obscured_commitment_transaction_number & 0xffffffu64) as u32),
input: txins,
output: outputs,
}, htlcs_used)
}
#[inline]
fn get_closing_scriptpubkey(&self) -> Script {
let our_channel_close_key_hash = Hash160::from_data(&PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.channel_close_key).serialize());
Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script()
}
#[inline]
fn get_closing_transaction_weight(a_scriptpubkey: &Script, b_scriptpubkey: &Script) -> u64 {
(4 + 1 + 36 + 4 + 1 + 1 + 2*(8+1) + 4 + a_scriptpubkey.len() as u64 + b_scriptpubkey.len() as u64)*4 + 2 + 1 + 1 + 2*(1 + 72)
}
#[inline]
fn build_closing_transaction(&self, proposed_total_fee_satoshis: u64, skip_remote_output: bool) -> (Transaction, u64) {
let txins = {
let mut ins: Vec<TxIn> = Vec::new();
ins.push(TxIn {
previous_output: self.channel_monitor.get_funding_txo().unwrap().into_bitcoin_outpoint(),
script_sig: Script::new(),
sequence: 0xffffffff,
witness: Vec::new(),
});
ins
};
assert!(self.pending_inbound_htlcs.is_empty());
assert!(self.pending_outbound_htlcs.is_empty());
let mut txouts: Vec<(TxOut, ())> = Vec::new();
let mut total_fee_satoshis = proposed_total_fee_satoshis;
let value_to_self: i64 = (self.value_to_self_msat as i64) / 1000 - if self.channel_outbound { total_fee_satoshis as i64 } else { 0 };
let value_to_remote: i64 = ((self.channel_value_satoshis * 1000 - self.value_to_self_msat) as i64 / 1000) - if self.channel_outbound { 0 } else { total_fee_satoshis as i64 };
if value_to_self < 0 {
assert!(self.channel_outbound);
total_fee_satoshis += (-value_to_self) as u64;
} else if value_to_remote < 0 {
assert!(!self.channel_outbound);
total_fee_satoshis += (-value_to_remote) as u64;
}
if !skip_remote_output && value_to_remote as u64 > self.our_dust_limit_satoshis {
txouts.push((TxOut {
script_pubkey: self.their_shutdown_scriptpubkey.clone().unwrap(),
value: value_to_remote as u64
}, ()));
}
if value_to_self as u64 > self.our_dust_limit_satoshis {
txouts.push((TxOut {
script_pubkey: self.get_closing_scriptpubkey(),
value: value_to_self as u64
}, ()));
}
transaction_utils::sort_outputs(&mut txouts);
let mut outputs: Vec<TxOut> = Vec::new();
for out in txouts.drain(..) {
outputs.push(out.0);
}
(Transaction {
version: 2,
lock_time: 0,
input: txins,
output: outputs,
}, total_fee_satoshis)
}
#[inline]
/// Creates a set of keys for build_commitment_transaction to generate a transaction which our
/// counterparty will sign (ie DO NOT send signatures over a transaction created by this to
/// our counterparty!)
/// The result is a transaction which we can revoke ownership of (ie a "local" transaction)
/// TODO Some magic rust shit to compile-time check this?
fn build_local_transaction_keys(&self, commitment_number: u64) -> Result<TxCreationKeys, HandleError> {
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(commitment_number));
let delayed_payment_base = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key);
let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key);
Ok(secp_derived_key!(TxCreationKeys::new(&self.secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &self.their_revocation_basepoint.unwrap(), &self.their_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap()), self.channel_id()))
}
#[inline]
/// Creates a set of keys for build_commitment_transaction to generate a transaction which we
/// will sign and send to our counterparty.
fn build_remote_transaction_keys(&self) -> Result<TxCreationKeys, HandleError> {
//TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we
//may see payments to it!
let payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key);
let revocation_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.revocation_base_key);
let htlc_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key);
Ok(secp_derived_key!(TxCreationKeys::new(&self.secp_ctx, &self.their_cur_commitment_point.unwrap(), &self.their_delayed_payment_basepoint.unwrap(), &self.their_htlc_basepoint.unwrap(), &revocation_basepoint, &payment_basepoint, &htlc_basepoint), self.channel_id()))
}
/// Gets the redeemscript for the funding transaction output (ie the funding transaction output
/// pays to get_funding_redeemscript().to_v0_p2wsh()).
/// Panics if called before accept_channel/new_from_req
pub fn get_funding_redeemscript(&self) -> Script {
let builder = Builder::new().push_opcode(opcodes::All::OP_PUSHNUM_2);
let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize();
let their_funding_key = self.their_funding_pubkey.expect("get_funding_redeemscript only allowed after accept_channel").serialize();
if our_funding_key[..] < their_funding_key[..] {
builder.push_slice(&our_funding_key)
.push_slice(&their_funding_key)
} else {
builder.push_slice(&their_funding_key)
.push_slice(&our_funding_key)
}.push_opcode(opcodes::All::OP_PUSHNUM_2).push_opcode(opcodes::All::OP_CHECKMULTISIG).into_script()
}
fn sign_commitment_transaction(&self, tx: &mut Transaction, their_sig: &Signature) -> Signature {
if tx.input.len() != 1 {
panic!("Tried to sign commitment transaction that had input count != 1!");
}
if tx.input[0].witness.len() != 0 {
panic!("Tried to re-sign commitment transaction");
}
let funding_redeemscript = self.get_funding_redeemscript();
let sighash = Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
let our_sig = self.secp_ctx.sign(&sighash, &self.local_keys.funding_key);
tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.funding_key).serialize();
let their_funding_key = self.their_funding_pubkey.unwrap().serialize();
if our_funding_key[..] < their_funding_key[..] {
tx.input[0].witness.push(our_sig.serialize_der(&self.secp_ctx).to_vec());
tx.input[0].witness.push(their_sig.serialize_der(&self.secp_ctx).to_vec());
} else {
tx.input[0].witness.push(their_sig.serialize_der(&self.secp_ctx).to_vec());
tx.input[0].witness.push(our_sig.serialize_der(&self.secp_ctx).to_vec());
}
tx.input[0].witness[1].push(SigHashType::All as u8);
tx.input[0].witness[2].push(SigHashType::All as u8);
tx.input[0].witness.push(funding_redeemscript.into_bytes());
our_sig
}
/// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output
/// @local is used only to convert relevant internal structures which refer to remote vs local
/// to decide value of outputs and direction of HTLCs.
fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys) -> Transaction {
chan_utils::build_htlc_transaction(prev_hash, self.feerate_per_kw, if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key)
}
fn create_htlc_tx_signature(&self, tx: &Transaction, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(Script, Signature, bool), HandleError> {
if tx.input.len() != 1 {
panic!("Tried to sign HTLC transaction that had input count != 1!");
}
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
let our_htlc_key = secp_derived_key!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, &self.local_keys.htlc_base_key), self.channel_id());
let sighash = Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
let is_local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key) == keys.a_htlc_key;
Ok((htlc_redeemscript, self.secp_ctx.sign(&sighash, &our_htlc_key), is_local_tx))
}
/// Signs a transaction created by build_htlc_transaction. If the transaction is an
/// HTLC-Success transaction (ie htlc.offered is false), preimate must be set!
fn sign_htlc_transaction(&self, tx: &mut Transaction, their_sig: &Signature, preimage: &Option<[u8; 32]>, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<Signature, HandleError> {
if tx.input.len() != 1 {
panic!("Tried to sign HTLC transaction that had input count != 1!");
}
if tx.input[0].witness.len() != 0 {
panic!("Tried to re-sign HTLC transaction");
}
let (htlc_redeemscript, our_sig, local_tx) = self.create_htlc_tx_signature(tx, htlc, keys)?;