@@ -4743,6 +4743,7 @@ static bool finalize_multisig(struct wally_psbt_input *input,
4743
4743
sigs , n_found * EC_SIGNATURE_LEN ,
4744
4744
sighashes , n_found , 0 ,
4745
4745
script , sizeof (script ), & script_len ) != WALLY_OK ||
4746
+ script_len > sizeof (script ) ||
4746
4747
wally_psbt_input_set_final_scriptsig (input , script , script_len ) != WALLY_OK )
4747
4748
goto fail ;
4748
4749
}
@@ -4767,6 +4768,79 @@ static bool finalize_p2tr(struct wally_psbt_input *input)
4767
4768
return true;
4768
4769
}
4769
4770
4771
+ static bool is_input_csv_expired (const struct wally_psbt_input * input , uint32_t blocks )
4772
+ {
4773
+ if (input -> sequence & ((1 << 31 ) | (1 << 22 )))
4774
+ return false; /* Locktime opt-out enabled, or time-based lock */
4775
+ /* Note we don't mask out the locktime value, because we don't want to
4776
+ * finalize inputs if a soft-fork we don't know about has changed the
4777
+ * meaning of locktime extra bits in a way we don't understand.
4778
+ */
4779
+ return blocks <= input -> sequence ;
4780
+ }
4781
+
4782
+ static bool finalize_csv2of2_1 (const struct wally_psbt * psbt ,
4783
+ struct wally_psbt_input * input ,
4784
+ const unsigned char * out_script , size_t out_script_len ,
4785
+ bool is_witness , bool is_p2sh , bool is_optimized )
4786
+ {
4787
+ const struct wally_map_item * sig_1 , * sig_2 , empty = { 0 };
4788
+ const unsigned char * pk_1 , * pk_2 ;
4789
+ const uint32_t tx_version = psbt -> tx ? psbt -> tx -> version : psbt -> tx_version ;
4790
+ uint32_t blocks ;
4791
+ bool is_expired ;
4792
+
4793
+ if (!is_witness )
4794
+ return false; /* Only supported for segwit inputs */
4795
+
4796
+ if (wally_scriptpubkey_csv_blocks_from_csv_2of2_then_1 (out_script , out_script_len ,
4797
+ & blocks ) != WALLY_OK )
4798
+ return false;
4799
+
4800
+ is_expired = tx_version >= 2 && is_input_csv_expired (input , blocks );
4801
+
4802
+ if (is_optimized ) {
4803
+ pk_1 = out_script + 1 ;
4804
+ pk_2 = out_script + 1 + EC_PUBLIC_KEY_LEN + 1 + 1 ;
4805
+ } else {
4806
+ pk_1 = out_script + 4 ;
4807
+ pk_2 = out_script + out_script_len - 1 - EC_PUBLIC_KEY_LEN ;
4808
+ if (is_expired ) {
4809
+ pk_1 = pk_2 ;
4810
+ }
4811
+ }
4812
+
4813
+ sig_1 = wally_map_get (& input -> signatures , pk_1 , EC_PUBLIC_KEY_LEN );
4814
+ if (is_expired ) {
4815
+ sig_2 = & empty ; /* Expired, spend with an empty witness element */
4816
+ } else {
4817
+ sig_2 = wally_map_get (& input -> signatures , pk_2 , EC_PUBLIC_KEY_LEN );
4818
+ }
4819
+
4820
+ if (!sig_1 || !sig_2 )
4821
+ return false; /* Missing required signature(s) */
4822
+
4823
+ if (is_optimized ) {
4824
+ /* Swap the order of the sigs */
4825
+ const struct wally_map_item * tmp = sig_1 ;
4826
+ sig_1 = sig_2 ;
4827
+ sig_2 = tmp ;
4828
+ }
4829
+
4830
+ if (wally_tx_witness_stack_init_alloc (3 , & input -> final_witness ) != WALLY_OK )
4831
+ return false;
4832
+
4833
+ if (wally_tx_witness_stack_add (input -> final_witness , sig_1 -> value , sig_1 -> value_len ) == WALLY_OK &&
4834
+ wally_tx_witness_stack_add (input -> final_witness , sig_2 -> value , sig_2 -> value_len ) == WALLY_OK &&
4835
+ wally_tx_witness_stack_add (input -> final_witness , out_script , out_script_len ) == WALLY_OK ) {
4836
+ if (!is_p2sh || finalize_p2sh_wrapped (input ))
4837
+ return true;
4838
+ }
4839
+ wally_tx_witness_stack_free (input -> final_witness );
4840
+ input -> final_witness = NULL ;
4841
+ return false;
4842
+ }
4843
+
4770
4844
int wally_psbt_finalize_input (struct wally_psbt * psbt , size_t index , uint32_t flags )
4771
4845
{
4772
4846
struct wally_psbt_input * input = psbt_get_input (psbt , index );
@@ -4836,6 +4910,13 @@ int wally_psbt_finalize_input(struct wally_psbt *psbt, size_t index, uint32_t fl
4836
4910
if (!finalize_p2tr (input ))
4837
4911
return WALLY_OK ;
4838
4912
break ;
4913
+ case WALLY_SCRIPT_TYPE_CSV2OF2_1 :
4914
+ case WALLY_SCRIPT_TYPE_CSV2OF2_1_OPT :
4915
+ if (!finalize_csv2of2_1 (psbt , input , out_script , out_script_len ,
4916
+ is_witness , is_p2sh ,
4917
+ type == WALLY_SCRIPT_TYPE_CSV2OF2_1_OPT ))
4918
+ return WALLY_OK ;
4919
+ break ;
4839
4920
default :
4840
4921
return WALLY_OK ; /* Unhandled script type */
4841
4922
}
0 commit comments