@@ -61,7 +61,7 @@ type AbortReason = String;
6161type ComputeSpend = u64 ;
6262/// An intermediary speculation artifact indicating whether a transaction should
6363/// be aborted or finalized with a certain compute_spend.
64- enum PrepareSpeculateResult {
64+ enum ShouldAbortResult {
6565 Abort ( AbortReason ) ,
6666 Finalize ( ComputeSpend ) ,
6767}
@@ -402,7 +402,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
402402 // Accumulate per-block uniqueness checks.
403403 let mut candidate_transaction_details = CandidateTransactionDetails :: <N >:: default ( ) ;
404404 // Accumulate per-block spend.
405- let mut block_spend = 0 ;
405+ let mut block_spend = 0u64 ;
406406 // Determine the transaction spend limit. These unwraps are safe, see tests in consensus_heights.rs
407407 let consensus_version = N :: CONSENSUS_VERSION ( state. block_height( ) ) . unwrap( ) ;
408408 let transaction_spend_limit =
@@ -425,19 +425,29 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
425425 match self . should_abort_transaction(
426426 & transaction,
427427 & candidate_transaction_details,
428- block_spend,
429428 transaction_spend_limit,
430- block_spend_limit,
431429 consensus_version,
432430 ) {
433- PrepareSpeculateResult :: Abort ( abort_reason) => {
431+ ShouldAbortResult :: Abort ( abort_reason) => {
434432 // Store the aborted transaction.
435433 aborted. push( ( transaction. clone( ) , abort_reason) ) ;
436434 // Continue to the next transaction.
437435 continue ' outer;
438436 }
439- PrepareSpeculateResult :: Finalize ( compute_spend) => {
437+ ShouldAbortResult :: Finalize ( compute_spend) => {
438+ // If the consensus version is >= V15, ensure that the
439+ // transaction is not exceeding block spend limits.
440440 if consensus_version >= ConsensusVersion :: V15 {
441+ if let Some ( block_spend_limit) = block_spend_limit {
442+ if block_spend. saturating_add( compute_spend) > block_spend_limit {
443+ aborted. push( (
444+ transaction. clone( ) ,
445+ format!( "Exceeds the block spend limit with compute_spend: '{compute_spend}'" ) ,
446+ ) ) ;
447+ // Continue to the next transaction.
448+ continue ' outer;
449+ }
450+ }
441451 // Track the compute_spend used so far.
442452 block_spend = block_spend. saturating_add( compute_spend) ;
443453 }
@@ -937,7 +947,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
937947 finalize_result
938948 }
939949
940- /// Returns PrepareSpeculateResult .
950+ /// Returns ShouldAbortResult .
941951 ///
942952 /// The transaction will be aborted if any of the following conditions are met:
943953 /// - The transaction is producing a duplicate transition
@@ -954,14 +964,12 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
954964 & self ,
955965 transaction : & Transaction < N > ,
956966 candidate_transaction_details : & CandidateTransactionDetails < N > ,
957- block_spend : u64 ,
958967 transaction_spend_limit : u64 ,
959- block_spend_limit : Option < u64 > ,
960968 consensus_version : ConsensusVersion ,
961- ) -> PrepareSpeculateResult {
969+ ) -> ShouldAbortResult {
962970 // Ensure that the transaction is not a fee transaction.
963971 if let Transaction :: Fee ( ..) = transaction {
964- return PrepareSpeculateResult :: Abort ( "Fee transactions are not allowed in speculate" . to_string ( ) ) ;
972+ return ShouldAbortResult :: Abort ( "Fee transactions are not allowed in speculate" . to_string ( ) ) ;
965973 }
966974
967975 // Ensure that:
@@ -974,11 +982,11 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
974982 if candidate_transaction_details. transition_ids . contains ( transition_id)
975983 || self . transition_store ( ) . contains_transition_id ( transition_id) . unwrap_or ( true )
976984 {
977- return PrepareSpeculateResult :: Abort ( format ! ( "Duplicate transition {transition_id}" ) ) ;
985+ return ShouldAbortResult :: Abort ( format ! ( "Duplicate transition {transition_id}" ) ) ;
978986 }
979987 // If the transition's program is being deployed or redeployed in this block, abort the transaction.
980988 if candidate_transaction_details. deployments . contains ( transition. program_id ( ) ) {
981- return PrepareSpeculateResult :: Abort ( format ! (
989+ return ShouldAbortResult :: Abort ( format ! (
982990 "Program {} is being deployed or redeployed in this block" ,
983991 transition. program_id( )
984992 ) ) ;
@@ -991,7 +999,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
991999 if candidate_transaction_details. input_ids . contains ( input_id)
9921000 || self . transition_store ( ) . contains_input_id ( input_id) . unwrap_or ( true )
9931001 {
994- return PrepareSpeculateResult :: Abort ( format ! ( "Double-spending input {input_id}" ) ) ;
1002+ return ShouldAbortResult :: Abort ( format ! ( "Double-spending input {input_id}" ) ) ;
9951003 }
9961004 }
9971005
@@ -1001,7 +1009,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10011009 if candidate_transaction_details. output_ids . contains ( output_id)
10021010 || self . transition_store ( ) . contains_output_id ( output_id) . unwrap_or ( true )
10031011 {
1004- return PrepareSpeculateResult :: Abort ( format ! ( "Duplicate output {output_id}" ) ) ;
1012+ return ShouldAbortResult :: Abort ( format ! ( "Duplicate output {output_id}" ) ) ;
10051013 }
10061014 }
10071015
@@ -1012,7 +1020,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10121020 if candidate_transaction_details. tpks . contains ( tpk)
10131021 || self . transition_store ( ) . contains_tpk ( tpk) . unwrap_or ( true )
10141022 {
1015- return PrepareSpeculateResult :: Abort ( format ! ( "Duplicate transition public key {tpk}" ) ) ;
1023+ return ShouldAbortResult :: Abort ( format ! ( "Duplicate transition public key {tpk}" ) ) ;
10161024 }
10171025 }
10181026
@@ -1021,7 +1029,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10211029 // If any public deployment payer has already deployed in this block, abort the transaction.
10221030 if let Some ( payer) = fee. payer ( ) {
10231031 if candidate_transaction_details. deployment_payers . contains ( & payer) {
1024- return PrepareSpeculateResult :: Abort ( format ! (
1032+ return ShouldAbortResult :: Abort ( format ! (
10251033 "Another deployment in the block from the same public fee payer {payer}"
10261034 ) ) ;
10271035 }
@@ -1030,7 +1038,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10301038
10311039 // Before V15, we return without tracking any compute spend.
10321040 if consensus_version < ConsensusVersion :: V15 {
1033- PrepareSpeculateResult :: Finalize ( 0 )
1041+ ShouldAbortResult :: Finalize ( 0 )
10341042 // If the consensus version is >= V15, ensure that the transaction is not exceeding spend limits.
10351043 } else {
10361044 // Compute microcredit spend from deployment or execution cost details.
@@ -1039,37 +1047,28 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10391047 match deployment_cost ( self . process ( ) , deployment, consensus_version) {
10401048 Ok ( ( _, cost_details) ) => deploy_compute_cost_in_microcredits ( cost_details, consensus_version) ,
10411049 Err ( e) => {
1042- return PrepareSpeculateResult :: Abort ( format ! (
1043- "Failed to compute the deployment cost: {e}"
1044- ) ) ;
1050+ return ShouldAbortResult :: Abort ( format ! ( "Failed to compute the deployment cost: {e}" ) ) ;
10451051 }
10461052 }
10471053 }
10481054 Transaction :: Execute ( _, _, execution, _) => {
10491055 match execution_cost ( self . process ( ) , execution, consensus_version) {
10501056 Ok ( ( _, cost_details) ) => execute_compute_cost_in_microcredits ( cost_details, consensus_version) ,
10511057 Err ( e) => {
1052- return PrepareSpeculateResult :: Abort ( format ! ( "Failed to compute the execution cost: {e}" ) ) ;
1058+ return ShouldAbortResult :: Abort ( format ! ( "Failed to compute the execution cost: {e}" ) ) ;
10531059 }
10541060 }
10551061 }
10561062 Transaction :: Fee ( ..) => 0 , // Fee transactions are already aborted above and don't contribute compute spend.
10571063 } ;
10581064
10591065 if compute_spend > transaction_spend_limit {
1060- return PrepareSpeculateResult :: Abort ( format ! (
1066+ return ShouldAbortResult :: Abort ( format ! (
10611067 "Exceeds the transaction spend limit with compute_spend: '{compute_spend}'"
10621068 ) ) ;
10631069 }
1064- if let Some ( block_spend_limit) = block_spend_limit {
1065- if block_spend. saturating_add ( compute_spend) > block_spend_limit {
1066- return PrepareSpeculateResult :: Abort ( format ! (
1067- "Exceeds the block spend limit with compute_spend: '{compute_spend}'"
1068- ) ) ;
1069- }
1070- }
10711070
1072- PrepareSpeculateResult :: Finalize ( compute_spend)
1071+ ShouldAbortResult :: Finalize ( compute_spend)
10731072 }
10741073 }
10751074
@@ -1092,34 +1091,26 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10921091
10931092 // Accumulate per-block uniqueness checks.
10941093 let mut candidate_transaction_details = CandidateTransactionDetails :: < N > :: default ( ) ;
1095- // Accumulate per-block spend.
1096- let mut block_spend = 0 ;
10971094 // Determine the transaction spend limit. These unwraps are safe, see tests in consensus_heights.rs
10981095 let consensus_version = N :: CONSENSUS_VERSION ( state. block_height ( ) ) . unwrap ( ) ;
10991096 let transaction_spend_limit =
11001097 consensus_config_value_by_version ! ( N , TRANSACTION_SPEND_LIMIT , consensus_version) . unwrap ( ) ;
1101- // Determine the block spend limit.
1102- let block_spend_limit = state. block_spend_limit ( ) ;
11031098
11041099 // Abort duplicate, overspending, invalid, or disallowed transactions before verification.
11051100 for transaction in transactions. iter ( ) {
11061101 match self . should_abort_transaction (
11071102 transaction,
11081103 & candidate_transaction_details,
1109- block_spend,
11101104 transaction_spend_limit,
1111- block_spend_limit,
11121105 consensus_version,
11131106 ) {
1114- PrepareSpeculateResult :: Abort ( abort_reason) => {
1107+ ShouldAbortResult :: Abort ( abort_reason) => {
11151108 // Store the aborted transaction.
11161109 aborted_transactions. push ( ( * transaction, abort_reason) ) ;
11171110 }
1118- PrepareSpeculateResult :: Finalize ( compute_spend) => {
1119- if consensus_version >= ConsensusVersion :: V15 {
1120- // Track the compute_spend used so far.
1121- block_spend = block_spend. saturating_add ( compute_spend) ;
1122- }
1111+ // We do not further track the compute spend here, to not count
1112+ // aborted transactions towards the block spend limit.
1113+ ShouldAbortResult :: Finalize ( _compute_spend) => {
11231114 // Track the accepted transaction details.
11241115 candidate_transaction_details. record_accepted_transaction ( transaction) ;
11251116 // Mark the transaction ready to verify.
0 commit comments