@@ -140,7 +140,7 @@ mod pre_lock_tests {
140140 use crate :: sdk:: parameters:: LendingParameters ;
141141 use crate :: sdk:: {
142142 build_pre_lock_cancellation, build_pre_lock_creation, build_pre_lock_lending_creation,
143- taproot_unspendable_internal_key,
143+ decode_pre_lock_metadata , extract_arguments_from_tx , taproot_unspendable_internal_key,
144144 } ;
145145
146146 use super :: * ;
@@ -178,6 +178,7 @@ mod pre_lock_tests {
178178 second_parameters_nft_amount : u64 ,
179179 borrower_pub_key : & XOnlyPublicKey ,
180180 lending_params : & LendingParameters ,
181+ borrower_output_script_hash : Option < [ u8 ; 32 ] > ,
181182 ) -> Result < ( ( PartiallySignedTransaction , Address ) , PreLockArguments ) > {
182183 // Calculate script hash for the AssetAuth covenant with the Lender NFT auth
183184 let asset_auth_arguments = AssetAuthArguments {
@@ -222,9 +223,9 @@ mod pre_lock_tests {
222223 . script_pubkey ( ) ;
223224 let parameters_nft_output_script_hash = hash_script ( & script_auth_script) ;
224225
225- // Calculate P2TR script hash
226- let borrower_p2tr_address = get_p2pk_address ( borrower_pub_key, NETWORK ) ?;
227- let borrower_p2tr_script_hash = hash_script ( & borrower_p2tr_address . script_pubkey ( ) ) ;
226+ let borrower_p2tr_script_hash = borrower_output_script_hash . unwrap_or ( hash_script (
227+ & get_p2pk_address ( borrower_pub_key, NETWORK ) ?. script_pubkey ( ) ,
228+ ) ) ;
228229
229230 let pre_lock_arguments = PreLockArguments :: new (
230231 collateral_asset_id. into_inner ( ) . 0 ,
@@ -304,6 +305,7 @@ mod pre_lock_tests {
304305 } ,
305306 ) ,
306307 & pre_lock_arguments,
308+ None ,
307309 100 ,
308310 NETWORK ,
309311 ) ?,
@@ -369,6 +371,7 @@ mod pre_lock_tests {
369371 second_parameters_amount,
370372 & test_borrower_key,
371373 & lending_params,
374+ None ,
372375 ) ?;
373376
374377 let pst = pst. extract_tx ( ) ?;
@@ -389,15 +392,86 @@ mod pre_lock_tests {
389392 . push_bytes ( )
390393 . unwrap ( ) ;
391394
392- let ( op_return_pub_key, op_return_asset_id) = op_return_bytes. split_at ( 32 ) ;
393-
394- let op_return_asset_id: [ u8 ; 32 ] =
395- op_return_asset_id. try_into ( ) . expect ( "Length must be 32" ) ;
395+ let borrower_output_script_hash_bytes = pst. output . get ( 6 ) . and_then ( |tx_out| {
396+ if !tx_out. is_null_data ( ) {
397+ return None ;
398+ }
399+
400+ let mut op_return_instr_iter = tx_out. script_pubkey . instructions_minimal ( ) ;
401+ let _ = op_return_instr_iter. next ( ) ?;
402+ op_return_instr_iter
403+ . next ( )
404+ . and_then ( Result :: ok)
405+ . and_then ( |instruction| instruction. push_bytes ( ) )
406+ } ) ;
396407
397- let op_return_public_key = XOnlyPublicKey :: from_slice ( op_return_pub_key) . unwrap ( ) ;
408+ let metadata =
409+ decode_pre_lock_metadata ( op_return_bytes, borrower_output_script_hash_bytes) ?;
410+ let op_return_public_key =
411+ XOnlyPublicKey :: from_slice ( & metadata. borrower_pub_key ( ) ) . unwrap ( ) ;
412+ let borrower_p2tr_script_hash =
413+ hash_script ( & get_p2pk_address ( & test_borrower_key, NETWORK ) ?. script_pubkey ( ) ) ;
398414
399415 assert ! ( op_return_public_key. serialize( ) == test_borrower_key. serialize( ) ) ;
400- assert ! ( principal_asset_id. into_inner( ) . 0 == op_return_asset_id) ;
416+ assert ! ( principal_asset_id. into_inner( ) . 0 == metadata. principal_asset_id( ) ) ;
417+ assert_eq ! (
418+ metadata. borrower_output_script_hash( ) ,
419+ Some ( borrower_p2tr_script_hash)
420+ ) ;
421+
422+ Ok ( ( ) )
423+ }
424+
425+ #[ test]
426+ fn test_pre_lock_creation_round_trips_custom_borrower_output_script_hash ( ) -> Result < ( ) > {
427+ let keypair = Keypair :: from_secret_key (
428+ & Secp256k1 :: new ( ) ,
429+ & secp256k1:: SecretKey :: from_slice ( & [ 1u8 ; 32 ] ) ?,
430+ ) ;
431+ let test_borrower_key = keypair. x_only_public_key ( ) . 0 ;
432+
433+ let principal_asset_id = AssetId :: from_str ( LIQUID_TESTNET_TEST_ASSET_ID_STR ) ?;
434+ let (
435+ first_parameters_nft_asset_id,
436+ second_parameters_nft_asset_id,
437+ borrower_nft_asset_id,
438+ lender_nft_asset_id,
439+ ) = create_test_assets ( ) ?;
440+
441+ let lending_params = LendingParameters {
442+ collateral_amount : 10_000 ,
443+ principal_amount : 4_000 ,
444+ loan_expiration_time : 100 ,
445+ principal_interest_rate : 250 ,
446+ } ;
447+ let ( first_parameters_amount, second_parameters_amount) =
448+ lending_params. encode_parameters_nft_amounts ( 2 ) ?;
449+ let borrower_output_script_hash = hash_script ( & Script :: new_p2pkh ( & PubkeyHash :: hash (
450+ & test_borrower_key. serialize ( ) ,
451+ ) ) ) ;
452+
453+ let ( ( pst, _) , pre_lock_arguments) = get_creation_pst (
454+ * LIQUID_TESTNET_BITCOIN_ASSET ,
455+ principal_asset_id,
456+ first_parameters_nft_asset_id,
457+ second_parameters_nft_asset_id,
458+ borrower_nft_asset_id,
459+ lender_nft_asset_id,
460+ first_parameters_amount,
461+ second_parameters_amount,
462+ & test_borrower_key,
463+ & lending_params,
464+ Some ( borrower_output_script_hash) ,
465+ ) ?;
466+
467+ let tx = pst. extract_tx ( ) ?;
468+ let extracted_arguments = extract_arguments_from_tx ( & tx, NETWORK ) ?;
469+
470+ assert_eq ! ( extracted_arguments, pre_lock_arguments) ;
471+ assert_eq ! (
472+ extracted_arguments. principal_output_script_hash( ) ,
473+ borrower_output_script_hash
474+ ) ;
401475
402476 Ok ( ( ) )
403477 }
@@ -439,6 +513,7 @@ mod pre_lock_tests {
439513 second_parameters_amount,
440514 & test_borrower_key,
441515 & lending_params,
516+ None ,
442517 ) ?;
443518
444519 let pst = pst. extract_tx ( ) ?;
@@ -612,6 +687,7 @@ mod pre_lock_tests {
612687 second_parameters_amount,
613688 & test_borrower_key,
614689 & lending_params,
690+ None ,
615691 ) ?;
616692
617693 let pst = pst. extract_tx ( ) ?;
0 commit comments