@@ -42,6 +42,12 @@ use chain;
42
42
use util:: crypto:: sign;
43
43
44
44
pub ( crate ) const MAX_HTLCS : u16 = 483 ;
45
+ pub ( crate ) const OFFERED_HTLC_SCRIPT_WEIGHT : usize = 133 ;
46
+ pub ( crate ) const OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS : usize = 136 ;
47
+ // The weight of `accepted_htlc_script` can vary in function of its CLTV argument value. We define a
48
+ // range that encompasses both its non-anchors and anchors variants.
49
+ pub ( crate ) const MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT : usize = 136 ;
50
+ pub ( crate ) const MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT : usize = 143 ;
45
51
46
52
/// Gets the weight for an HTLC-Success transaction.
47
53
#[ inline]
@@ -60,18 +66,72 @@ pub fn htlc_timeout_tx_weight(opt_anchors: bool) -> u64 {
60
66
}
61
67
62
68
#[ derive( PartialEq ) ]
63
- pub ( crate ) enum HTLCType {
64
- AcceptedHTLC ,
65
- OfferedHTLC
69
+ pub ( crate ) enum HTLCClaim {
70
+ OfferedTimeout ,
71
+ OfferedPreimage ,
72
+ AcceptedTimeout ,
73
+ AcceptedPreimage ,
74
+ Revocation ,
66
75
}
67
76
68
- impl HTLCType {
69
- /// Check if a given tx witnessScript len matchs one of a pre-signed HTLC
70
- pub ( crate ) fn scriptlen_to_htlctype ( witness_script_len : usize ) -> Option < HTLCType > {
71
- if witness_script_len == 133 {
72
- Some ( HTLCType :: OfferedHTLC )
73
- } else if witness_script_len >= 136 && witness_script_len <= 139 {
74
- Some ( HTLCType :: AcceptedHTLC )
77
+ impl HTLCClaim {
78
+ /// Check if a given input witness attempts to claim a HTLC.
79
+ pub ( crate ) fn from_witness ( witness : & Witness ) -> Option < Self > {
80
+ debug_assert_eq ! ( OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS , MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT ) ;
81
+ if witness. len ( ) < 2 {
82
+ return None ;
83
+ }
84
+ let witness_script = witness. last ( ) . unwrap ( ) ;
85
+ let second_to_last = witness. second_to_last ( ) . unwrap ( ) ;
86
+ if witness_script. len ( ) == OFFERED_HTLC_SCRIPT_WEIGHT {
87
+ if witness. len ( ) == 3 && second_to_last. len ( ) == 33 {
88
+ // <revocation sig> <revocationpubkey> <witness_script>
89
+ Some ( Self :: Revocation )
90
+ } else if witness. len ( ) == 3 && second_to_last. len ( ) == 32 {
91
+ // <remotehtlcsig> <payment_preimage> <witness_script>
92
+ Some ( Self :: OfferedPreimage )
93
+ } else if witness. len ( ) == 5 && second_to_last. len ( ) == 0 {
94
+ // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
95
+ Some ( Self :: OfferedTimeout )
96
+ } else {
97
+ None
98
+ }
99
+ } else if witness_script. len ( ) == OFFERED_HTLC_SCRIPT_WEIGHT_ANCHORS {
100
+ // It's possible for the weight of `offered_htlc_script` and `accepted_htlc_script` to
101
+ // match so we check for both here.
102
+ if witness. len ( ) == 3 && second_to_last. len ( ) == 33 {
103
+ // <revocation sig> <revocationpubkey> <witness_script>
104
+ Some ( Self :: Revocation )
105
+ } else if witness. len ( ) == 3 && second_to_last. len ( ) == 32 {
106
+ // <remotehtlcsig> <payment_preimage> <witness_script>
107
+ Some ( Self :: OfferedPreimage )
108
+ } else if witness. len ( ) == 5 && second_to_last. len ( ) == 0 {
109
+ // 0 <remotehtlcsig> <localhtlcsig> <> <witness_script>
110
+ Some ( Self :: OfferedTimeout )
111
+ } else if witness. len ( ) == 3 && second_to_last. len ( ) == 0 {
112
+ // <remotehtlcsig> <> <witness_script>
113
+ Some ( Self :: AcceptedTimeout )
114
+ } else if witness. len ( ) == 5 && second_to_last. len ( ) == 32 {
115
+ // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
116
+ Some ( Self :: AcceptedPreimage )
117
+ } else {
118
+ None
119
+ }
120
+ } else if witness_script. len ( ) > MIN_ACCEPTED_HTLC_SCRIPT_WEIGHT &&
121
+ witness_script. len ( ) <= MAX_ACCEPTED_HTLC_SCRIPT_WEIGHT {
122
+ // Handle remaining range of ACCEPTED_HTLC_SCRIPT_WEIGHT.
123
+ if witness. len ( ) == 3 && second_to_last. len ( ) == 33 {
124
+ // <revocation sig> <revocationpubkey> <witness_script>
125
+ Some ( Self :: Revocation )
126
+ } else if witness. len ( ) == 3 && second_to_last. len ( ) == 0 {
127
+ // <remotehtlcsig> <> <witness_script>
128
+ Some ( Self :: AcceptedTimeout )
129
+ } else if witness. len ( ) == 5 && second_to_last. len ( ) == 32 {
130
+ // 0 <remotehtlcsig> <localhtlcsig> <payment_preimage> <witness_script>
131
+ Some ( Self :: AcceptedPreimage )
132
+ } else {
133
+ None
134
+ }
75
135
} else {
76
136
None
77
137
}
@@ -285,7 +345,7 @@ pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_com
285
345
286
346
/// Derives a per-commitment-transaction revocation key from its constituent parts.
287
347
///
288
- /// Only the cheating participant owns a valid witness to propagate a revoked
348
+ /// Only the cheating participant owns a valid witness to propagate a revoked
289
349
/// commitment transaction, thus per_commitment_secret always come from cheater
290
350
/// and revocation_base_secret always come from punisher, which is the broadcaster
291
351
/// of the transaction spending with this key knowledge.
@@ -320,7 +380,7 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
320
380
/// the public equivalend of derive_private_revocation_key - using only public keys to derive a
321
381
/// public key instead of private keys.
322
382
///
323
- /// Only the cheating participant owns a valid witness to propagate a revoked
383
+ /// Only the cheating participant owns a valid witness to propagate a revoked
324
384
/// commitment transaction, thus per_commitment_point always come from cheater
325
385
/// and revocation_base_point always come from punisher, which is the broadcaster
326
386
/// of the transaction spending with this key knowledge.
@@ -616,12 +676,17 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte
616
676
} else {
617
677
htlc_success_tx_weight ( opt_anchors)
618
678
} ;
619
- let total_fee = feerate_per_kw as u64 * weight / 1000 ;
679
+ let output_value = if opt_anchors {
680
+ htlc. amount_msat / 1000
681
+ } else {
682
+ let total_fee = feerate_per_kw as u64 * weight / 1000 ;
683
+ htlc. amount_msat / 1000 - total_fee
684
+ } ;
620
685
621
686
let mut txouts: Vec < TxOut > = Vec :: new ( ) ;
622
687
txouts. push ( TxOut {
623
688
script_pubkey : get_revokeable_redeemscript ( revocation_key, contest_delay, broadcaster_delayed_payment_key) . to_v0_p2wsh ( ) ,
624
- value : htlc . amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
689
+ value : output_value ,
625
690
} ) ;
626
691
627
692
Transaction {
@@ -680,7 +745,8 @@ pub struct ChannelTransactionParameters {
680
745
pub counterparty_parameters : Option < CounterpartyChannelTransactionParameters > ,
681
746
/// The late-bound funding outpoint
682
747
pub funding_outpoint : Option < chain:: transaction:: OutPoint > ,
683
- /// Are anchors used for this channel. Boolean is serialization backwards-compatible
748
+ /// Are anchors (zero fee HTLC transaction variant) used for this channel. Boolean is
749
+ /// serialization backwards-compatible.
684
750
pub opt_anchors : Option < ( ) >
685
751
}
686
752
0 commit comments