@@ -374,12 +374,16 @@ impl Block {
374374 ///
375375 /// Includes the guesser-fee UTXOs which are not included by the
376376 /// `mutator_set_accumulator` field on the block body.
377- pub fn mutator_set_accumulator_after ( & self ) -> MutatorSetAccumulator {
377+ pub fn mutator_set_accumulator_after (
378+ & self ,
379+ ) -> Result < MutatorSetAccumulator , BlockValidationError > {
378380 let mut msa = self . kernel . body . mutator_set_accumulator . clone ( ) ;
379- let mutator_set_update = MutatorSetUpdate :: new ( vec ! [ ] , self . guesser_fee_addition_records ( ) ) ;
381+ let mutator_set_update =
382+ MutatorSetUpdate :: new ( vec ! [ ] , self . guesser_fee_addition_records ( ) ?) ;
380383 mutator_set_update. apply_to_accumulator ( & mut msa)
381384 . expect ( "mutator set update derived from guesser fees should be applicable to mutator set accumulator contained in body" ) ;
382- msa
385+
386+ Ok ( msa)
383387 }
384388
385389 #[ inline]
@@ -819,11 +823,9 @@ impl Block {
819823 }
820824
821825 // 2.a)
826+ let msa_before = previous_block. mutator_set_accumulator_after ( ) ?;
822827 for removal_record in & self . kernel . body . transaction_kernel . inputs {
823- if !previous_block
824- . mutator_set_accumulator_after ( )
825- . can_remove ( removal_record)
826- {
828+ if !msa_before. can_remove ( removal_record) {
827829 return Err ( BlockValidationError :: RemovalRecordsValid ) ;
828830 }
829831 }
@@ -847,7 +849,7 @@ impl Block {
847849 self . body ( ) . transaction_kernel . inputs . clone ( ) ,
848850 self . body ( ) . transaction_kernel . outputs . clone ( ) ,
849851 ) ;
850- let mut msa = previous_block . mutator_set_accumulator_after ( ) ;
852+ let mut msa = msa_before ;
851853 let ms_update_result = mutator_set_update. apply_to_accumulator ( & mut msa) ;
852854
853855 // 2.c)
@@ -1025,26 +1027,32 @@ impl Block {
10251027
10261028 /// The amount rewarded to the guesser who finds a valid nonce for this
10271029 /// block.
1028- pub ( crate ) fn total_guesser_reward ( & self ) -> NativeCurrencyAmount {
1029- self . body ( ) . transaction_kernel . fee
1030+ pub ( crate ) fn total_guesser_reward (
1031+ & self ,
1032+ ) -> Result < NativeCurrencyAmount , BlockValidationError > {
1033+ if self . body ( ) . transaction_kernel . fee . is_negative ( ) {
1034+ return Err ( BlockValidationError :: NegativeFee ) ;
1035+ }
1036+
1037+ Ok ( self . body ( ) . transaction_kernel . fee )
10301038 }
10311039
10321040 /// Get the block's guesser fee UTXOs.
10331041 ///
10341042 /// The amounts in the UTXOs are taken from the transaction fee.
10351043 ///
10361044 /// The genesis block does not have a guesser reward.
1037- pub ( crate ) fn guesser_fee_utxos ( & self ) -> Vec < Utxo > {
1045+ pub ( crate ) fn guesser_fee_utxos ( & self ) -> Result < Vec < Utxo > , BlockValidationError > {
10381046 const MINER_REWARD_TIME_LOCK_PERIOD : Timestamp = Timestamp :: years ( 3 ) ;
10391047
10401048 if self . header ( ) . height . is_genesis ( ) {
1041- return vec ! [ ] ;
1049+ return Ok ( vec ! [ ] ) ;
10421050 }
10431051
10441052 let lock = self . header ( ) . guesser_digest ;
10451053 let lock_script = HashLockKey :: lock_script_from_after_image ( lock) ;
10461054
1047- let total_guesser_reward = self . total_guesser_reward ( ) ;
1055+ let total_guesser_reward = self . total_guesser_reward ( ) ? ;
10481056 let mut value_locked = total_guesser_reward;
10491057 value_locked. div_two ( ) ;
10501058 let value_unlocked = total_guesser_reward. checked_sub ( & value_locked) . unwrap ( ) ;
@@ -1056,15 +1064,18 @@ impl Block {
10561064 let locked_utxo = Utxo :: new ( lock_script. clone ( ) , coins) ;
10571065 let unlocked_utxo = Utxo :: new_native_currency ( lock_script, value_unlocked) ;
10581066
1059- vec ! [ locked_utxo, unlocked_utxo]
1067+ Ok ( vec ! [ locked_utxo, unlocked_utxo] )
10601068 }
10611069
10621070 /// Compute the addition records that correspond to the UTXOs generated for
10631071 /// the block's guesser
10641072 ///
10651073 /// The genesis block does not have this addition record.
1066- pub ( crate ) fn guesser_fee_addition_records ( & self ) -> Vec < AdditionRecord > {
1067- self . guesser_fee_utxos ( )
1074+ pub ( crate ) fn guesser_fee_addition_records (
1075+ & self ,
1076+ ) -> Result < Vec < AdditionRecord > , BlockValidationError > {
1077+ Ok ( self
1078+ . guesser_fee_utxos ( ) ?
10681079 . into_iter ( )
10691080 . map ( |utxo| {
10701081 let item = Tip5 :: hash ( & utxo) ;
@@ -1078,21 +1089,22 @@ impl Block {
10781089
10791090 commit ( item, sender_randomness, receiver_digest)
10801091 } )
1081- . collect_vec ( )
1092+ . collect_vec ( ) )
10821093 }
10831094
10841095 /// Return the mutator set update corresponding to this block, which sends
10851096 /// the mutator set accumulator after the predecessor to the mutator set
10861097 /// accumulator after self.
1087- pub ( crate ) fn mutator_set_update ( & self ) -> MutatorSetUpdate {
1098+ pub ( crate ) fn mutator_set_update ( & self ) -> Result < MutatorSetUpdate , BlockValidationError > {
10881099 let mut mutator_set_update = MutatorSetUpdate :: new (
10891100 self . body ( ) . transaction_kernel . inputs . clone ( ) ,
10901101 self . body ( ) . transaction_kernel . outputs . clone ( ) ,
10911102 ) ;
10921103
1093- let extra_addition_records = self . guesser_fee_addition_records ( ) ;
1104+ let extra_addition_records = self . guesser_fee_addition_records ( ) ? ;
10941105 mutator_set_update. additions . extend ( extra_addition_records) ;
1095- mutator_set_update
1106+
1107+ Ok ( mutator_set_update)
10961108 }
10971109}
10981110
@@ -1245,7 +1257,7 @@ pub(crate) mod tests {
12451257 block_proof_witness. appendix ( ) ,
12461258 BlockProof :: Invalid ,
12471259 ) ;
1248- let total_guesser_reward = block1. total_guesser_reward ( ) ;
1260+ let total_guesser_reward = block1. total_guesser_reward ( ) . unwrap ( ) ;
12491261 let total_miner_reward = total_composer_reward + total_guesser_reward;
12501262 assert_eq ! ( NativeCurrencyAmount :: coins( 128 ) , total_miner_reward) ;
12511263
@@ -1385,7 +1397,7 @@ pub(crate) mod tests {
13851397 }
13861398 }
13871399
1388- #[ proptest( async = "tokio" ) ]
1400+ #[ proptest( async = "tokio" , cases = 5 ) ]
13891401 async fn can_prove_block_ancestry (
13901402 #[ strategy( collection:: vec( arb:: <Digest >( ) , 55 ) ) ] mut sender_randomness_vec : Vec < Digest > ,
13911403 #[ strategy( 0 ..54usize ) ] index : usize ,
@@ -1813,9 +1825,10 @@ pub(crate) mod tests {
18131825 ( 0.4 , guesser_preimage) ,
18141826 )
18151827 . await ;
1816- let ars = block1. guesser_fee_addition_records ( ) ;
1828+ let ars = block1. guesser_fee_addition_records ( ) . unwrap ( ) ;
18171829 let ars_from_wallet = block1
18181830 . guesser_fee_utxos ( )
1831+ . unwrap ( )
18191832 . iter ( )
18201833 . map ( |utxo| commit ( Tip5 :: hash ( utxo) , block1. hash ( ) , guesser_preimage. hash ( ) ) )
18211834 . collect_vec ( ) ;
@@ -1824,7 +1837,7 @@ pub(crate) mod tests {
18241837 let MutatorSetUpdate {
18251838 removals : _,
18261839 additions,
1827- } = block1. mutator_set_update ( ) ;
1840+ } = block1. mutator_set_update ( ) . unwrap ( ) ;
18281841 assert ! (
18291842 ars. iter( ) . all( |ar| additions. contains( ar) ) ,
18301843 "All addition records must be present in block's mutator set update"
@@ -1845,7 +1858,7 @@ pub(crate) mod tests {
18451858 let preimage = rand:: rng ( ) . random :: < Digest > ( ) ;
18461859 block. set_header_guesser_digest ( preimage. hash ( ) ) ;
18471860
1848- let guesser_fee_utxos = block. guesser_fee_utxos ( ) ;
1861+ let guesser_fee_utxos = block. guesser_fee_utxos ( ) . unwrap ( ) ;
18491862
18501863 let lock_script_and_witness =
18511864 HashLockKey :: from_preimage ( preimage) . lock_script_and_witness ( ) ;
@@ -1868,7 +1881,7 @@ pub(crate) mod tests {
18681881 let network = Network :: Main ;
18691882 let genesis_block = Block :: genesis ( network) ;
18701883 assert ! (
1871- genesis_block. guesser_fee_utxos( ) . is_empty( ) ,
1884+ genesis_block. guesser_fee_utxos( ) . unwrap ( ) . is_empty( ) ,
18721885 "Genesis block has no guesser fee UTXOs"
18731886 ) ;
18741887
@@ -1932,7 +1945,7 @@ pub(crate) mod tests {
19321945 let mut ms = block1. body ( ) . mutator_set_accumulator . clone ( ) ;
19331946
19341947 let mutator_set_update_guesser_fees =
1935- MutatorSetUpdate :: new ( vec ! [ ] , block1. guesser_fee_addition_records ( ) ) ;
1948+ MutatorSetUpdate :: new ( vec ! [ ] , block1. guesser_fee_addition_records ( ) . unwrap ( ) ) ;
19361949 let mut mutator_set_update_tx = MutatorSetUpdate :: new (
19371950 block2. body ( ) . transaction_kernel . inputs . clone ( ) ,
19381951 block2. body ( ) . transaction_kernel . outputs . clone ( ) ,
0 commit comments