-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Replace Class Hash issue resolved, gas fees bug resolved, cap removed for pending tick #409
Changes from 16 commits
4afd4fe
d059615
ae70f76
d54da43
1e62ba1
66cedbe
73b7a91
1c3ccc1
a5d4d61
b22e9af
d0ee79d
d4fe5aa
24e537e
182cf00
60af04c
8517cee
cbd5770
35e0285
11a9b7a
28aea87
11ec8ff
d216c63
68b4837
de8c0bf
752b5af
9c53e2d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ | |
use crate::close_block::close_block; | ||
use crate::metrics::BlockProductionMetrics; | ||
use blockifier::blockifier::transaction_executor::{TransactionExecutor, BLOCK_STATE_ACCESS_ERR}; | ||
use blockifier::bouncer::{BouncerWeights, BuiltinCount}; | ||
use blockifier::bouncer::BouncerWeights; | ||
use blockifier::transaction::errors::TransactionExecutionError; | ||
use finalize_execution_state::StateDiffToStateMapError; | ||
use mc_block_import::{BlockImportError, BlockImporter}; | ||
|
@@ -77,6 +77,15 @@ pub enum Error { | |
#[error("State diff error when continuing the pending block: {0:#}")] | ||
PendingStateDiff(#[from] StateDiffToStateMapError), | ||
} | ||
|
||
struct ContinueBlockResult { | ||
state_diff: StateDiff, | ||
visited_segments: VisitedSegments, | ||
bouncer_weights: BouncerWeights, | ||
stats: ContinueBlockStats, | ||
block_now_full: bool, | ||
} | ||
|
||
/// The block production task consumes transactions from the mempool in batches. | ||
/// This is to allow optimistic concurrency. However, the block may get full during batch execution, | ||
/// and we need to re-add the transactions back into the mempool. | ||
|
@@ -165,11 +174,9 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> { | |
} | ||
|
||
#[tracing::instrument(skip(self), fields(module = "BlockProductionTask"))] | ||
fn continue_block( | ||
&mut self, | ||
bouncer_cap: BouncerWeights, | ||
) -> Result<(StateDiff, VisitedSegments, BouncerWeights, ContinueBlockStats), Error> { | ||
fn continue_block(&mut self, bouncer_cap: BouncerWeights) -> Result<ContinueBlockResult, Error> { | ||
let mut stats = ContinueBlockStats::default(); | ||
let mut block_now_full = false; | ||
|
||
self.executor.bouncer.bouncer_config.block_max_capacity = bouncer_cap; | ||
let batch_size = self.backend.chain_config().execution_batch_size; | ||
|
@@ -201,7 +208,7 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> { | |
// Execute the transactions. | ||
let all_results = self.executor.execute_txs(&txs_to_process_blockifier); | ||
// When the bouncer cap is reached, blockifier will return fewer results than what we asked for. | ||
let block_now_full = all_results.len() < txs_to_process_blockifier.len(); | ||
block_now_full = all_results.len() < txs_to_process_blockifier.len(); | ||
|
||
txs_to_process_blockifier.drain(..all_results.len()); // remove the used txs | ||
|
||
|
@@ -273,54 +280,24 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> { | |
stats.n_re_added_to_mempool | ||
); | ||
|
||
Ok((state_diff, visited_segments, bouncer_weights, stats)) | ||
Ok(ContinueBlockResult { state_diff, visited_segments, bouncer_weights, stats, block_now_full }) | ||
} | ||
|
||
/// Each "tick" of the block time updates the pending block but only with the appropriate fraction of the total bouncer capacity. | ||
#[tracing::instrument(skip(self), fields(module = "BlockProductionTask"))] | ||
pub fn on_pending_time_tick(&mut self) -> Result<(), Error> { | ||
pub async fn on_pending_time_tick(&mut self) -> Result<(), Error> { | ||
let current_pending_tick = self.current_pending_tick; | ||
let n_pending_ticks_per_block = self.backend.chain_config().n_pending_ticks_per_block(); | ||
let config_bouncer = self.backend.chain_config().bouncer_config.block_max_capacity; | ||
if current_pending_tick == 0 { | ||
return Ok(()); | ||
} | ||
|
||
// Reduced bouncer capacity for the current pending tick | ||
|
||
// reduced_gas = gas * current_pending_tick/n_pending_ticks_per_block | ||
// - we're dealing with integers here so prefer having the division last | ||
// - use u128 here because the multiplication would overflow | ||
// - div by zero: see [`ChainConfig::precheck_block_production`] | ||
let reduced_cap = | ||
|v: usize| (v as u128 * current_pending_tick as u128 / n_pending_ticks_per_block as u128) as usize; | ||
|
||
let gas = reduced_cap(config_bouncer.gas); | ||
let frac = current_pending_tick as f64 / n_pending_ticks_per_block as f64; | ||
tracing::debug!("begin pending tick {current_pending_tick}/{n_pending_ticks_per_block}, proportion for this tick: {frac:.2}, gas limit: {gas}/{}", config_bouncer.gas); | ||
|
||
let bouncer_cap = BouncerWeights { | ||
builtin_count: BuiltinCount { | ||
add_mod: reduced_cap(config_bouncer.builtin_count.add_mod), | ||
bitwise: reduced_cap(config_bouncer.builtin_count.bitwise), | ||
ecdsa: reduced_cap(config_bouncer.builtin_count.ecdsa), | ||
ec_op: reduced_cap(config_bouncer.builtin_count.ec_op), | ||
keccak: reduced_cap(config_bouncer.builtin_count.keccak), | ||
mul_mod: reduced_cap(config_bouncer.builtin_count.mul_mod), | ||
pedersen: reduced_cap(config_bouncer.builtin_count.pedersen), | ||
poseidon: reduced_cap(config_bouncer.builtin_count.poseidon), | ||
range_check: reduced_cap(config_bouncer.builtin_count.range_check), | ||
range_check96: reduced_cap(config_bouncer.builtin_count.range_check96), | ||
}, | ||
gas, | ||
message_segment_length: reduced_cap(config_bouncer.message_segment_length), | ||
n_events: reduced_cap(config_bouncer.n_events), | ||
n_steps: reduced_cap(config_bouncer.n_steps), | ||
state_diff_size: reduced_cap(config_bouncer.state_diff_size), | ||
}; | ||
// Use full bouncer capacity | ||
let bouncer_cap = self.backend.chain_config().bouncer_config.block_max_capacity; | ||
|
||
let start_time = Instant::now(); | ||
let (state_diff, visited_segments, bouncer_weights, stats) = self.continue_block(bouncer_cap)?; | ||
|
||
let ContinueBlockResult { state_diff, visited_segments, bouncer_weights, stats, block_now_full } = | ||
self.continue_block(bouncer_cap)?; | ||
if stats.n_added_to_block > 0 { | ||
tracing::info!( | ||
"🧮 Executed and added {} transaction(s) to the pending block at height {} - {:?}", | ||
|
@@ -330,6 +307,13 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> { | |
); | ||
} | ||
|
||
// Check if block is full | ||
if block_now_full { | ||
tracing::info!("Resource limits reached, closing block early"); | ||
self.on_block_time().await?; | ||
return Ok(()); | ||
} | ||
|
||
// Store pending block | ||
// todo, prefer using the block import pipeline? | ||
self.backend.store_block( | ||
|
@@ -353,8 +337,13 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> { | |
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think you should split the on_block_time function in two: on_block_time and close_block and on_pending_block_tick should call close_block instead of on_block_time There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did something very similar, lmk wdyt? |
||
// Complete the block with full bouncer capacity. | ||
let start_time = Instant::now(); | ||
let (mut new_state_diff, visited_segments, _weights, _stats) = | ||
self.continue_block(self.backend.chain_config().bouncer_config.block_max_capacity)?; | ||
let ContinueBlockResult { | ||
state_diff: mut new_state_diff, | ||
visited_segments, | ||
bouncer_weights: _weights, | ||
stats: _stats, | ||
block_now_full: _block_now_full, | ||
} = self.continue_block(self.backend.chain_config().bouncer_config.block_max_capacity)?; | ||
|
||
// SNOS requirement: For blocks >= 10, the hash of the block 10 blocks prior | ||
// at address 0x1 with the block number as the key | ||
|
@@ -473,7 +462,7 @@ impl<Mempool: MempoolProvider> BlockProductionTask<Mempool> { | |
continue | ||
} | ||
|
||
if let Err(err) = self.on_pending_time_tick() { | ||
if let Err(err) = self.on_pending_time_tick().await { | ||
tracing::error!("Pending block update task has errored: {err:#}"); | ||
} | ||
self.current_pending_tick += 1; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you document this struct for rust doc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added