@@ -217,6 +217,48 @@ pub fn generate_unspent_outputs_pool(
217217 unspent_outputs
218218}
219219
220+ fn get_vtis_from_utxo_set (
221+ utxo_set : & UnspentOutputsPool ,
222+ vtos : & [ ValueTransferOutput ] ,
223+ ) -> Vec < Input > {
224+ let mut utxos_list: Vec < _ > = utxo_set. iter ( ) . collect ( ) ;
225+ let mut vtis = vec ! [ ] ;
226+
227+ for vto in vtos {
228+ // Search for this output in the list
229+ let found_index = utxos_list
230+ . iter ( )
231+ . position ( |( _output_pointer, ( output, _block_number) ) | output == vto)
232+ . expect ( "failed to find vto in utxo set" ) ;
233+ // Remove UTXO from list
234+ let ( output_pointer, ( _output, _block_number) ) = utxos_list. remove ( found_index) ;
235+ vtis. push ( Input :: new ( output_pointer) ) ;
236+ }
237+
238+ vtis
239+ }
240+
241+ fn get_block_numbers_from_utxo_set (
242+ utxo_set : & UnspentOutputsPool ,
243+ vtos : & [ ValueTransferOutput ] ,
244+ ) -> Vec < u32 > {
245+ let mut utxos_list: Vec < _ > = utxo_set. iter ( ) . collect ( ) ;
246+ let mut vtis = vec ! [ ] ;
247+
248+ for vto in vtos {
249+ // Search for this output in the list
250+ let found_index = utxos_list
251+ . iter ( )
252+ . position ( |( _output_pointer, ( output, _block_number) ) | output == vto)
253+ . expect ( "failed to find vto in utxo set" ) ;
254+ // Remove UTXO from list
255+ let ( _output_pointer, ( _output, block_number) ) = utxos_list. remove ( found_index) ;
256+ vtis. push ( block_number) ;
257+ }
258+
259+ vtis
260+ }
261+
220262// Validate transactions in block
221263#[ test]
222264fn mint_mismatched_reward ( ) {
@@ -10605,6 +10647,109 @@ fn validate_commit_transactions_included_in_utxo_diff() {
1060510647 assert_eq ! ( utxos, expected_utxos) ;
1060610648}
1060710649
10650+ #[ test]
10651+ fn validate_update_utxo_diff ( ) {
10652+ let pkh1 = MY_PKH_1 . parse ( ) . unwrap ( ) ;
10653+ let pkh2 = MY_PKH_2 . parse ( ) . unwrap ( ) ;
10654+
10655+ // For the get_vtis_from_utxo_set function to work correctly, all the vtos here need to be different, so they have different value
10656+ let vto1 = ValueTransferOutput {
10657+ pkh : pkh1,
10658+ value : 1000 ,
10659+ time_lock : 0 ,
10660+ } ;
10661+ let vto2 = ValueTransferOutput {
10662+ pkh : pkh1,
10663+ value : 1001 ,
10664+ time_lock : 0 ,
10665+ } ;
10666+ let vto3 = ValueTransferOutput {
10667+ pkh : pkh2,
10668+ value : 1002 ,
10669+ time_lock : 0 ,
10670+ } ;
10671+ let mut utxo_set = build_utxo_set_with_mint ( vec ! [ vto1. clone( ) , vto3. clone( ) ] , None , vec ! [ ] ) ;
10672+ let vto2_ptr = "2222222222222222222222222222222222222222222222222222222222222222:0"
10673+ . parse ( )
10674+ . unwrap ( ) ;
10675+ utxo_set. insert ( vto2_ptr, vto2. clone ( ) , 999 ) ;
10676+
10677+ let vtis = get_vtis_from_utxo_set ( & utxo_set, & [ vto1, vto2, vto3] ) ;
10678+ let vti0 = vtis[ 0 ] ;
10679+ let vti1 = vtis[ 1 ] ;
10680+ let vti2 = vtis[ 2 ] ;
10681+
10682+ let block_number = 1000 ;
10683+ let tx_hash = Hash :: default ( ) ;
10684+
10685+ let test_diff_block_numbers =
10686+ |inputs : & [ Input ] , outputs : & [ ValueTransferOutput ] , block_numbers : & [ u32 ] | {
10687+ let mut utxo_diff = UtxoDiff :: new ( & utxo_set, block_number) ;
10688+
10689+ update_utxo_diff ( & mut utxo_diff, inputs, outputs, tx_hash) ;
10690+
10691+ let diff = utxo_diff. take_diff ( ) ;
10692+
10693+ let mut utxo_set_copy = utxo_set. clone ( ) ;
10694+ diff. apply ( & mut utxo_set_copy) ;
10695+ let utxo_block_numbers = get_block_numbers_from_utxo_set ( & utxo_set_copy, outputs) ;
10696+
10697+ assert_eq ! ( utxo_block_numbers, block_numbers) ;
10698+ } ;
10699+
10700+ let vto4 = ValueTransferOutput {
10701+ pkh : pkh1,
10702+ value : 100 ,
10703+ time_lock : 0 ,
10704+ } ;
10705+ let vto5 = ValueTransferOutput {
10706+ pkh : pkh1,
10707+ value : 101 ,
10708+ time_lock : 0 ,
10709+ } ;
10710+ let vto6 = ValueTransferOutput {
10711+ pkh : pkh2,
10712+ value : 102 ,
10713+ time_lock : 0 ,
10714+ } ;
10715+
10716+ // 1 input and 1 output with same PKH: keep block number
10717+ test_diff_block_numbers ( & [ vti0] , & [ vto4. clone ( ) ] , & [ 0 ] ) ;
10718+
10719+ // 2 inputs and 1 output with same PKH: keep block number of max input
10720+ test_diff_block_numbers ( & [ vti0, vti1] , & [ vto4. clone ( ) ] , & [ 999 ] ) ;
10721+
10722+ // 1 input and 2 outputs with same PKH: keep block number
10723+ test_diff_block_numbers ( & [ vti0] , & [ vto4. clone ( ) , vto5. clone ( ) ] , & [ 0 , 0 ] ) ;
10724+
10725+ // 2 inputs and 2 outputs with same PKH: keep block number of max input
10726+ test_diff_block_numbers ( & [ vti0, vti1] , & [ vto4. clone ( ) , vto5] , & [ 999 , 999 ] ) ;
10727+
10728+ // No inputs: reset block number
10729+ test_diff_block_numbers ( & [ ] , & [ vto4. clone ( ) ] , & [ 1000 ] ) ;
10730+
10731+ // 1 input and 1 output with different PKH: reset block number
10732+ test_diff_block_numbers ( & [ vti0] , & [ vto6. clone ( ) ] , & [ 1000 ] ) ;
10733+
10734+ // 2 inputs with different PKH: reset block number for all outputs
10735+ test_diff_block_numbers ( & [ vti0, vti2] , & [ vto4. clone ( ) ] , & [ 1000 ] ) ;
10736+
10737+ // 2 inputs with different PKH: reset block number for all outputs
10738+ test_diff_block_numbers ( & [ vti0, vti2] , & [ vto6. clone ( ) ] , & [ 1000 ] ) ;
10739+
10740+ // 2 inputs with different PKH: reset block number for all outputs
10741+ test_diff_block_numbers ( & [ vti0, vti2] , & [ vto4. clone ( ) , vto6. clone ( ) ] , & [ 1000 , 1000 ] ) ;
10742+
10743+ // 2 outputs with different PKH: reset the block number of the new PKH only
10744+ test_diff_block_numbers ( & [ vti0] , & [ vto4. clone ( ) , vto6. clone ( ) ] , & [ 0 , 1000 ] ) ;
10745+
10746+ // 2 outputs with different PKH: the order of the outputs does not matter
10747+ test_diff_block_numbers ( & [ vti0] , & [ vto6. clone ( ) , vto4. clone ( ) ] , & [ 1000 , 0 ] ) ;
10748+
10749+ // 2 outputs with different PKH: reset the block number of the new PKH only
10750+ test_diff_block_numbers ( & [ vti0, vti1] , & [ vto4, vto6] , & [ 999 , 1000 ] ) ;
10751+ }
10752+
1060810753#[ test]
1060910754fn validate_required_tally_not_found ( ) {
1061010755 let dr_pointer = Hash :: default ( ) ;
0 commit comments