@@ -42,6 +42,12 @@ use chain;
4242use util:: crypto:: sign;
4343
4444pub ( 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 ;
4551
4652/// Gets the weight for an HTLC-Success transaction.
4753#[ inline]
@@ -60,18 +66,72 @@ pub fn htlc_timeout_tx_weight(opt_anchors: bool) -> u64 {
6066}
6167
6268#[ 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 ,
6675}
6776
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+ }
75135 } else {
76136 None
77137 }
@@ -285,7 +345,7 @@ pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_com
285345
286346/// Derives a per-commitment-transaction revocation key from its constituent parts.
287347///
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
289349/// commitment transaction, thus per_commitment_secret always come from cheater
290350/// and revocation_base_secret always come from punisher, which is the broadcaster
291351/// of the transaction spending with this key knowledge.
@@ -320,7 +380,7 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
320380/// the public equivalend of derive_private_revocation_key - using only public keys to derive a
321381/// public key instead of private keys.
322382///
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
324384/// commitment transaction, thus per_commitment_point always come from cheater
325385/// and revocation_base_point always come from punisher, which is the broadcaster
326386/// 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
616676 } else {
617677 htlc_success_tx_weight ( opt_anchors)
618678 } ;
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+ } ;
620685
621686 let mut txouts: Vec < TxOut > = Vec :: new ( ) ;
622687 txouts. push ( TxOut {
623688 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 ,
625690 } ) ;
626691
627692 Transaction {
@@ -680,7 +745,8 @@ pub struct ChannelTransactionParameters {
680745 pub counterparty_parameters : Option < CounterpartyChannelTransactionParameters > ,
681746 /// The late-bound funding outpoint
682747 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.
684750 pub opt_anchors : Option < ( ) >
685751}
686752
0 commit comments