@@ -121,20 +121,38 @@ pub struct StaticPaymentOutputDescriptor {
121
121
pub channel_keys_id : [ u8 ; 32 ] ,
122
122
/// The value of the channel which this transactions spends.
123
123
pub channel_value_satoshis : u64 ,
124
+ /// The necessary channel parameters that need to be provided to the re-derived signer through
125
+ /// [`ChannelSigner::provide_channel_parameters`].
126
+ ///
127
+ /// Added as optional, but always `Some` if the descriptor was produced in v0.0.117 or later.
128
+ pub channel_transaction_parameters : Option < ChannelTransactionParameters > ,
124
129
}
125
130
impl StaticPaymentOutputDescriptor {
126
131
/// The maximum length a well-formed witness spending one of these should have.
127
132
/// Note: If you have the grind_signatures feature enabled, this will be at least 1 byte
128
133
/// shorter.
129
- // Calculated as 1 byte legnth + 73 byte signature, 1 byte empty vec push, 1 byte length plus
130
- // redeemscript push length.
131
- pub const MAX_WITNESS_LENGTH : usize = 1 + 73 + 34 ;
134
+ pub fn max_witness_length ( & self ) -> usize {
135
+ if self . channel_transaction_parameters . as_ref ( )
136
+ . map ( |channel_params| channel_params. channel_type_features . supports_anchors_zero_fee_htlc_tx ( ) )
137
+ . unwrap_or ( false )
138
+ {
139
+ let witness_script_weight = 1 /* pubkey push */ + 33 /* pubkey */ +
140
+ 1 /* OP_CHECKSIGVERIFY */ + 1 /* OP_1 */ + 1 /* OP_CHECKSEQUENCEVERIFY */ ;
141
+ 1 /* num witness items */ + 1 /* sig push */ + 73 /* sig including sighash flag */ +
142
+ 1 /* witness script push */ + witness_script_weight
143
+ } else {
144
+ // Calculated as 1 byte legnth + 73 byte signature, 1 byte empty vec push, 1 byte length plus
145
+ // redeemscript push length.
146
+ 1 + 73 + 34
147
+ }
148
+ }
132
149
}
133
150
impl_writeable_tlv_based ! ( StaticPaymentOutputDescriptor , {
134
151
( 0 , outpoint, required) ,
135
152
( 2 , output, required) ,
136
153
( 4 , channel_keys_id, required) ,
137
154
( 6 , channel_value_satoshis, required) ,
155
+ ( 7 , channel_transaction_parameters, option) ,
138
156
} ) ;
139
157
140
158
/// Describes the necessary information to spend a spendable output.
@@ -201,15 +219,23 @@ pub enum SpendableOutputDescriptor {
201
219
/// [`DelayedPaymentOutputDescriptor::to_self_delay`] contained here to
202
220
/// [`chan_utils::get_revokeable_redeemscript`].
203
221
DelayedPaymentOutput ( DelayedPaymentOutputDescriptor ) ,
204
- /// An output to a P2WPKH, spendable exclusively by our payment key (i.e., the private key
205
- /// which corresponds to the `payment_point` in [`ChannelSigner::pubkeys`]). The witness
206
- /// in the spending input is, thus, simply:
222
+ /// An output spendable exclusively by our payment key (i.e., the private key that corresponds
223
+ /// to the `payment_point` in [`ChannelSigner::pubkeys`]). The output type depends on the
224
+ /// channel type negotiated.
225
+ ///
226
+ /// On an anchor outputs channel, the witness in the spending input is:
227
+ /// ```bitcoin
228
+ /// <BIP 143 signature> <witness script>
229
+ /// ```
230
+ ///
231
+ /// Otherwise, it is:
207
232
/// ```bitcoin
208
233
/// <BIP 143 signature> <payment key>
209
234
/// ```
210
235
///
211
236
/// These are generally the result of our counterparty having broadcast the current state,
212
- /// allowing us to claim the non-HTLC-encumbered outputs immediately.
237
+ /// allowing us to claim the non-HTLC-encumbered outputs immediately, or after one confirmation
238
+ /// in the case of anchor outputs channels.
213
239
StaticPaymentOutput ( StaticPaymentOutputDescriptor ) ,
214
240
}
215
241
@@ -280,13 +306,22 @@ impl SpendableOutputDescriptor {
280
306
match outp {
281
307
SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
282
308
if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
309
+ let sequence =
310
+ if descriptor. channel_transaction_parameters . as_ref ( )
311
+ . map ( |channel_params| channel_params. channel_type_features . supports_anchors_zero_fee_htlc_tx ( ) )
312
+ . unwrap_or ( false )
313
+ {
314
+ Sequence :: from_consensus ( 1 )
315
+ } else {
316
+ Sequence :: ZERO
317
+ } ;
283
318
input. push ( TxIn {
284
319
previous_output : descriptor. outpoint . into_bitcoin_outpoint ( ) ,
285
320
script_sig : Script :: new ( ) ,
286
- sequence : Sequence :: ZERO ,
321
+ sequence,
287
322
witness : Witness :: new ( ) ,
288
323
} ) ;
289
- witness_weight += StaticPaymentOutputDescriptor :: MAX_WITNESS_LENGTH ;
324
+ witness_weight += descriptor . max_witness_length ( ) ;
290
325
#[ cfg( feature = "grind_signatures" ) ]
291
326
{ witness_weight -= 1 ; } // Guarantees a low R signature
292
327
input_value += descriptor. output . value ;
@@ -891,18 +926,30 @@ impl InMemorySigner {
891
926
if !spend_tx. input [ input_idx] . script_sig . is_empty ( ) { return Err ( ( ) ) ; }
892
927
if spend_tx. input [ input_idx] . previous_output != descriptor. outpoint . into_bitcoin_outpoint ( ) { return Err ( ( ) ) ; }
893
928
894
- let remotepubkey = self . pubkeys ( ) . payment_point ;
895
- let witness_script = bitcoin:: Address :: p2pkh ( & :: bitcoin:: PublicKey { compressed : true , inner : remotepubkey} , Network :: Testnet ) . script_pubkey ( ) ;
929
+ let remotepubkey = bitcoin:: PublicKey :: new ( self . pubkeys ( ) . payment_point ) ;
930
+ let witness_script = if self . channel_type_features ( ) . supports_anchors_zero_fee_htlc_tx ( ) {
931
+ chan_utils:: get_to_countersignatory_with_anchors_redeemscript ( & remotepubkey. inner )
932
+ } else {
933
+ Script :: new_p2pkh ( & remotepubkey. pubkey_hash ( ) )
934
+ } ;
896
935
let sighash = hash_to_message ! ( & sighash:: SighashCache :: new( spend_tx) . segwit_signature_hash( input_idx, & witness_script, descriptor. output. value, EcdsaSighashType :: All ) . unwrap( ) [ ..] ) ;
897
936
let remotesig = sign_with_aux_rand ( secp_ctx, & sighash, & self . payment_key , & self ) ;
898
- let payment_script = bitcoin:: Address :: p2wpkh ( & :: bitcoin:: PublicKey { compressed : true , inner : remotepubkey} , Network :: Bitcoin ) . unwrap ( ) . script_pubkey ( ) ;
937
+ let payment_script = if self . channel_type_features ( ) . supports_anchors_zero_fee_htlc_tx ( ) {
938
+ witness_script. to_v0_p2wsh ( )
939
+ } else {
940
+ Script :: new_v0_p2wpkh ( & remotepubkey. wpubkey_hash ( ) . unwrap ( ) )
941
+ } ;
899
942
900
943
if payment_script != descriptor. output . script_pubkey { return Err ( ( ) ) ; }
901
944
902
945
let mut witness = Vec :: with_capacity ( 2 ) ;
903
946
witness. push ( remotesig. serialize_der ( ) . to_vec ( ) ) ;
904
947
witness[ 0 ] . push ( EcdsaSighashType :: All as u8 ) ;
905
- witness. push ( remotepubkey. serialize ( ) . to_vec ( ) ) ;
948
+ if self . channel_type_features ( ) . supports_anchors_zero_fee_htlc_tx ( ) {
949
+ witness. push ( witness_script. to_bytes ( ) ) ;
950
+ } else {
951
+ witness. push ( remotepubkey. to_bytes ( ) ) ;
952
+ }
906
953
Ok ( witness)
907
954
}
908
955
@@ -1353,9 +1400,11 @@ impl KeysManager {
1353
1400
SpendableOutputDescriptor :: StaticPaymentOutput ( descriptor) => {
1354
1401
let input_idx = psbt. unsigned_tx . input . iter ( ) . position ( |i| i. previous_output == descriptor. outpoint . into_bitcoin_outpoint ( ) ) . ok_or ( ( ) ) ?;
1355
1402
if keys_cache. is_none ( ) || keys_cache. as_ref ( ) . unwrap ( ) . 1 != descriptor. channel_keys_id {
1356
- keys_cache = Some ( (
1357
- self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ,
1358
- descriptor. channel_keys_id ) ) ;
1403
+ let mut signer = self . derive_channel_keys ( descriptor. channel_value_satoshis , & descriptor. channel_keys_id ) ;
1404
+ if let Some ( channel_params) = descriptor. channel_transaction_parameters . as_ref ( ) {
1405
+ signer. provide_channel_parameters ( channel_params) ;
1406
+ }
1407
+ keys_cache = Some ( ( signer, descriptor. channel_keys_id ) ) ;
1359
1408
}
1360
1409
let witness = Witness :: from_vec ( keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_counterparty_payment_input ( & psbt. unsigned_tx , input_idx, & descriptor, & secp_ctx) ?) ;
1361
1410
psbt. inputs [ input_idx] . final_script_witness = Some ( witness) ;
0 commit comments