@@ -428,6 +428,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
428428 block_spend,
429429 transaction_spend_limit,
430430 block_spend_limit,
431+ None ,
431432 consensus_version,
432433 ) {
433434 PrepareSpeculateResult :: Abort ( abort_reason) => {
@@ -957,6 +958,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
957958 block_spend : u64 ,
958959 transaction_spend_limit : u64 ,
959960 block_spend_limit : Option < u64 > ,
961+ block_combined_density : Option < u64 > ,
960962 consensus_version : ConsensusVersion ,
961963 ) -> PrepareSpeculateResult {
962964 // Ensure that the transaction is not a fee transaction.
@@ -1028,10 +1030,10 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10281030 }
10291031 }
10301032
1031- // Before V15, we return without tracking any compute spend.
1033+ // Before V15, we return without tracking any compute spend and checking deployment limits .
10321034 if consensus_version < ConsensusVersion :: V15 {
10331035 PrepareSpeculateResult :: Finalize ( 0 )
1034- // If the consensus version is >= V15, ensure that the transaction is not exceeding spend limits.
1036+ // If the consensus version is >= V15, ensure that the transaction is not exceeding spend or deployment limits.
10351037 } else {
10361038 // Compute microcredit spend from deployment or execution cost details.
10371039 let compute_spend = match transaction {
@@ -1068,6 +1070,18 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
10681070 ) ) ;
10691071 }
10701072 }
1073+ // If we are keeping track of block-wide circuit density and this transaction contains a deployment, make sure its
1074+ // density does not make the running total exceed the limit.
1075+ if let Some ( combined_density) = block_combined_density && let Transaction :: Deploy ( _, _, _, deployment, _) = transaction {
1076+ if combined_density. saturating_add ( deployment. combined_density ( ) ) > N :: MAX_DEPLOY_DENSITY_PER_PROPOSAL {
1077+ return PrepareSpeculateResult :: Abort ( format ! (
1078+ "Deployment density '{}' added to current accumulated block-wide density '{}' exceeds the limit '{}'" ,
1079+ deployment. combined_density( ) ,
1080+ combined_density,
1081+ N :: MAX_DEPLOY_DENSITY_PER_PROPOSAL
1082+ ) ) ;
1083+ }
1084+ }
10711085
10721086 PrepareSpeculateResult :: Finalize ( compute_spend)
10731087 }
@@ -1100,6 +1114,8 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
11001114 consensus_config_value_by_version ! ( N , TRANSACTION_SPEND_LIMIT , consensus_version) . unwrap ( ) ;
11011115 // Determine the block spend limit.
11021116 let block_spend_limit = state. block_spend_limit ( ) ;
1117+ // Initialize a block-wide total of the combined density of all circuits in all deployments.
1118+ let mut block_combined_density = 0u64 ;
11031119
11041120 // Abort duplicate, overspending, invalid, or disallowed transactions before verification.
11051121 for transaction in transactions. iter ( ) {
@@ -1109,6 +1125,7 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
11091125 block_spend,
11101126 transaction_spend_limit,
11111127 block_spend_limit,
1128+ Some ( block_combined_density) ,
11121129 consensus_version,
11131130 ) {
11141131 PrepareSpeculateResult :: Abort ( abort_reason) => {
@@ -1119,6 +1136,14 @@ impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
11191136 if consensus_version >= ConsensusVersion :: V15 {
11201137 // Track the compute_spend used so far.
11211138 block_spend = block_spend. saturating_add ( compute_spend) ;
1139+
1140+ // If the transaction contains a deployment, add its combined density to the running total.
1141+ match transaction {
1142+ Transaction :: Deploy ( _, _, _, deployment, _) => {
1143+ block_combined_density = block_combined_density. saturating_add ( deployment. combined_density ( ) ) ;
1144+ } ,
1145+ _ => { }
1146+ }
11221147 }
11231148 // Track the accepted transaction details.
11241149 candidate_transaction_details. record_accepted_transaction ( transaction) ;
0 commit comments