Skip to content
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

Feature/gas limits #141

Closed
wants to merge 10 commits into from
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions collator/src/collator/build_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ impl CollatorStdImpl {
end_lt: collation_data.next_lt,
gen_validator_list_hash_short: self.collation_session.collators().short_hash,
gen_catchain_seqno: self.collation_session.seqno(),
min_ref_mc_seqno: collation_data.min_ref_mc_seqno()?,
min_ref_mc_seqno: collation_data.min_ref_mc_seqno,
prev_key_block_seqno: mc_data.prev_key_block_seqno(),
master_ref: master_ref.as_ref().map(Lazy::new).transpose()?,
..Default::default()
Expand Down Expand Up @@ -236,7 +236,8 @@ impl CollatorStdImpl {
processed_upto: Lazy::new(&collation_data.processed_upto)?,
before_split: new_block_info.before_split,
accounts: Lazy::new(&shard_accounts)?,
overload_history: 0,
overload_history: prev_shard_data.gas_used()
+ collation_data.block_limit.gas_used as u64,
underload_history: 0,
total_balance: value_flow.to_next_block.clone(),
total_validator_fees: prev_shard_data.total_validator_fees().clone(),
Expand Down
149 changes: 90 additions & 59 deletions collator/src/collator/do_collate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use tycho_util::metrics::HistogramGuard;
use tycho_util::time::now_millis;
use tycho_util::FastHashMap;

use super::types::{CachedMempoolAnchor, SpecialOrigin};
use super::types::{
BlockCollationDataBuilder, BlockLimitsLevel, CachedMempoolAnchor, SpecialOrigin,
};
use super::CollatorStdImpl;
use crate::collator::execution_manager::ExecutionManager;
use crate::collator::types::{
Expand Down Expand Up @@ -59,41 +61,33 @@ impl CollatorStdImpl {
let rand_seed = HashBytes::from_slice(hash_bytes.as_slice());
tracing::trace!(target: tracing_targets::COLLATOR, "rand_seed from chain time: {}", rand_seed);

let is_masterchain = self.shard_id.is_masterchain();
// prepare block collation data
// STUB: consider split/merge in future for taking prev_block_id
let prev_block_id = prev_shard_data.blocks_ids()[0];
let mut collation_data = Box::new(BlockCollationData::default());
collation_data.block_id_short = BlockIdShort {
let block_id_short = BlockIdShort {
shard: prev_block_id.shard,
seqno: prev_block_id.seqno + 1,
};
collation_data.rand_seed = rand_seed;
collation_data.update_ref_min_mc_seqno(mc_data.mc_state_stuff().state().seqno);
collation_data.gen_utime = (next_chain_time / 1000) as u32;
collation_data.gen_utime_ms = (next_chain_time % 1000) as u16;
collation_data.start_lt = Self::calc_start_lt(mc_data, prev_shard_data, &collation_data)?;
collation_data.next_lt = collation_data.start_lt + 1;

collation_data.processed_upto = prev_shard_data.processed_upto().clone();
tracing::debug!(target: tracing_targets::COLLATOR, "initial processed_upto.externals = {:?}",
collation_data.processed_upto.externals,
let block_limits = mc_data.config().get_block_limits(is_masterchain)?;
tracing::debug!(target: tracing_targets::COLLATOR,
"Block limits: {:?}",
block_limits
);

// show intenals proccessed upto
collation_data
.processed_upto
.internals
.iter()
.for_each(|result| {
let (shard_ident, processed_upto) = result.unwrap();
tracing::debug!(target: tracing_targets::COLLATOR,
"initial processed_upto.internals for shard {:?}: {:?}",
shard_ident, processed_upto,
);
});
// TODO: get from anchor
let created_by = HashBytes::default();
let mut collation_data_builder = BlockCollationDataBuilder::new(
block_id_short,
rand_seed,
mc_data.mc_state_stuff().state().seqno,
next_chain_time,
prev_shard_data.processed_upto().clone(),
created_by,
);

// init ShardHashes descriptions for master
if self.shard_id.is_masterchain() {
if is_masterchain {
let shards = prev_shard_data.observable_states()[0]
.shards()?
.iter()
Expand All @@ -104,17 +98,43 @@ impl CollatorStdImpl {
})
.collect::<FastHashMap<_, _>>();

collation_data.set_shards(shards);
collation_data_builder.set_shards(shards);

if let Some(top_shard_blocks_info) = top_shard_blocks_info {
self.import_new_shard_top_blocks_for_masterchain(
mc_data.config(),
&mut collation_data,
&mut collation_data_builder,
top_shard_blocks_info,
)?;
}
}

let start_lt = Self::calc_start_lt(
mc_data,
prev_shard_data,
is_masterchain,
collation_data_builder.shards_max_end_lt,
)?;

let mut collation_data = Box::new(collation_data_builder.build(start_lt, block_limits));

tracing::debug!(target: tracing_targets::COLLATOR, "initial processed_upto.externals = {:?}",
collation_data.processed_upto.externals,
);

// show intenals proccessed upto
collation_data
.processed_upto
.internals
.iter()
.for_each(|result| {
let (shard_ident, processed_upto) = result.unwrap();
tracing::debug!(target: tracing_targets::COLLATOR,
"initial processed_upto.internals for shard {:?}: {:?}",
shard_ident, processed_upto,
);
});

// compute created / minted / recovered / from_prev_block
self.update_value_flow(mc_data, prev_shard_data, &mut collation_data)?;

Expand Down Expand Up @@ -167,7 +187,7 @@ impl CollatorStdImpl {

// execute tick transaction and special transactions (mint, recover)
let execute_tick_elapsed;
if self.shard_id.is_masterchain() {
if is_masterchain {
let histogram =
HistogramGuard::begin_with_labels("tycho_do_collate_execute_tick_time", labels);

Expand Down Expand Up @@ -204,13 +224,21 @@ impl CollatorStdImpl {
loop {
let mut timer = Instant::now();

let soft_level_reached = collation_data.block_limit.reached(BlockLimitsLevel::Soft);
if soft_level_reached {
tracing::debug!(target: tracing_targets::COLLATOR,
"STUB: soft block limit reached: {:?}",
collation_data.block_limit,
);
}
let mut executed_internal_messages = vec![];
let mut internal_messages_sources = FastHashMap::default();
// build messages set
let mut msgs_set: Vec<Box<ParsedMessage>> = vec![];

// 1. First try to read min externals amount
let mut ext_msgs = if self.has_pending_externals {

let mut ext_msgs = if !soft_level_reached && self.has_pending_externals {
self.read_next_externals(min_externals_per_set, &mut collation_data)?
} else {
vec![]
Expand Down Expand Up @@ -260,7 +288,7 @@ impl CollatorStdImpl {
// If not enough existing internals to fill the set then try read more externals
msgs_set.append(&mut ext_msgs);
remaining_capacity = max_messages_per_set - msgs_set.len();
if remaining_capacity > 0 && self.has_pending_externals {
if remaining_capacity > 0 && self.has_pending_externals && !soft_level_reached {
ext_msgs = self.read_next_externals(remaining_capacity, &mut collation_data)?;
tracing::debug!(target: tracing_targets::COLLATOR,
ext_count = ext_msgs.len(),
Expand Down Expand Up @@ -388,6 +416,7 @@ impl CollatorStdImpl {
}

collation_data.next_lt = exec_manager.min_next_lt();
collation_data.block_limit.lt_current = collation_data.next_lt;
}

msgs_set_offset = tick.new_offset;
Expand All @@ -409,22 +438,22 @@ impl CollatorStdImpl {
if msgs_set_offset == msgs_set_len {
msgs_set_full_processed = true;
}

if collation_data.block_limit.reached(BlockLimitsLevel::Hard) {
tracing::debug!(target: tracing_targets::COLLATOR,
"STUB: block limit reached: {:?}",
collation_data.block_limit,
);
block_limits_reached = true;
break;
}
}

metrics::gauge!("tycho_do_collate_exec_ticks_per_msgs_set", labels)
.set(exec_ticks_count as f64);

timer = std::time::Instant::now();

// HACK: temporary always full process msgs set and check block limits after
if collation_data.tx_count >= self.config.block_txs_limit as u64 {
tracing::debug!(target: tracing_targets::COLLATOR,
"STUB: block limit reached: {}/{}",
collation_data.tx_count, self.config.block_txs_limit,
);
block_limits_reached = true;
}

// commit messages to iterator only if set was fully processed
if msgs_set_full_processed {
self.mq_adapter.commit_messages_to_iterator(
Expand Down Expand Up @@ -469,7 +498,7 @@ impl CollatorStdImpl {

// execute tock transaction
let execute_tock_elapsed;
if self.shard_id.is_masterchain() {
if is_masterchain {
let histogram =
HistogramGuard::begin_with_labels("tycho_do_collate_execute_tock_time", labels);
self.create_ticktock_transactions(
Expand Down Expand Up @@ -918,20 +947,18 @@ impl CollatorStdImpl {
fn calc_start_lt(
mc_data: &McData,
prev_shard_data: &PrevData,
collation_data: &BlockCollationData,
is_masterchain: bool,
shards_max_end_lt: u64,
) -> Result<u64> {
tracing::trace!(target: tracing_targets::COLLATOR, "calc_start_lt()");

let mut start_lt = if !collation_data.block_id_short.shard.is_masterchain() {
let mut start_lt = if !is_masterchain {
std::cmp::max(
mc_data.mc_state_stuff().state().gen_lt,
prev_shard_data.gen_lt(),
)
} else {
std::cmp::max(
mc_data.mc_state_stuff().state().gen_lt,
collation_data.shards_max_end_lt(),
)
std::cmp::max(mc_data.mc_state_stuff().state().gen_lt, shards_max_end_lt)
};

let align = mc_data.get_lt_align();
Expand Down Expand Up @@ -1227,14 +1254,14 @@ impl CollatorStdImpl {
fn import_new_shard_top_blocks_for_masterchain(
&self,
config: &BlockchainConfig,
collation_data: &mut BlockCollationData,
collation_data_builder: &mut BlockCollationDataBuilder,
top_shard_blocks_info: Vec<TopBlockDescription>,
) -> Result<()> {
tracing::trace!(target: tracing_targets::COLLATOR,
"import_new_shard_top_blocks_for_masterchain()",
);

let gen_utime = collation_data.gen_utime;
let gen_utime = collation_data_builder.gen_utime;
for TopBlockDescription {
block_id,
block_info,
Expand All @@ -1248,13 +1275,13 @@ impl CollatorStdImpl {
&block_info,
&value_flow,
));
shard_descr.reg_mc_seqno = collation_data.block_id_short.seqno;
shard_descr.reg_mc_seqno = collation_data_builder.block_id_short.seqno;

collation_data.update_shards_max_end_lt(shard_descr.end_lt);
collation_data_builder.update_shards_max_end_lt(shard_descr.end_lt);

let shard_id = block_id.shard;

collation_data.top_shard_blocks_ids.push(block_id);
collation_data_builder.top_shard_blocks_ids.push(block_id);

if shard_descr.gen_utime > gen_utime {
tracing::debug!(target: tracing_targets::COLLATOR,
Expand All @@ -1275,19 +1302,23 @@ impl CollatorStdImpl {
// TODO: Check may update shard block info
// TODO: Implement merge algorithm in future

self.update_shard_block_info(collation_data.shards_mut()?, shard_id, shard_descr)?;
self.update_shard_block_info(
collation_data_builder.shards_mut()?,
shard_id,
shard_descr,
)?;

collation_data.store_shard_fees(shard_id, proof_funds)?;
collation_data.register_shard_block_creators(creators)?;
collation_data_builder.store_shard_fees(shard_id, proof_funds)?;
collation_data_builder.register_shard_block_creators(creators)?;
}

let shard_fees = collation_data.shard_fees.root_extra().clone();
let shard_fees = collation_data_builder.shard_fees.root_extra().clone();

collation_data
collation_data_builder
.value_flow
.fees_collected
.checked_add(&shard_fees.fees)?;
collation_data.value_flow.fees_imported = shard_fees.fees;
collation_data_builder.value_flow.fees_imported = shard_fees.fees;

Ok(())
}
Expand Down Expand Up @@ -1338,6 +1369,7 @@ fn new_transaction(
);

collation_data.execute_count_all += 1;
collation_data.block_limit.gas_used += executor_output.gas_used as u32;

let import_fees;
let in_msg_hash = *in_msg.cell.repr_hash();
Expand Down Expand Up @@ -1481,7 +1513,6 @@ fn new_transaction(
info = ?out_msg_info,
"adding out message to out_msgs",
);

match &out_msg_info {
MsgInfo::Int(IntMsgInfo { fwd_fee, dst, .. }) => {
collation_data.int_enqueue_count += 1;
Expand Down
20 changes: 13 additions & 7 deletions collator/src/collator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@ impl CollatorStdImpl {
.expect("should `init` collator before calling `working_state`")
}

fn working_state_mut(&mut self) -> &mut WorkingState {
self.working_state
.as_mut()
.expect("should `init` collator before calling `working_state`")
}

fn set_working_state(&mut self, working_state: WorkingState) {
self.working_state = Some(working_state);
}
Expand Down Expand Up @@ -730,11 +736,10 @@ impl CollatorStdImpl {
let force_mc_block_by_uncommitted_chain =
uncommitted_chain_length >= self.config.max_uncommitted_chain_length;

// should import anchor every fixed interval in uncommitted blocks chain
let force_import_anchor_by_uncommitted_chain = uncommitted_chain_length
/ self.config.uncommitted_chain_to_import_next_anchor
> 0
&& uncommitted_chain_length % self.config.uncommitted_chain_to_import_next_anchor == 0;
// should import anchor after fixed gas used by shard blocks in uncommitted blocks chain
let gas_used = self.working_state().prev_shard_data.gas_used();
let force_import_anchor_by_uncommitted_chain =
uncommitted_chain_length > 0 && gas_used > self.config.gas_used_to_import_next_anchor;

// check if has pending internals or externals
let no_pending_msgs = !has_internals && !has_externals;
Expand All @@ -755,8 +760,8 @@ impl CollatorStdImpl {
);
} else if force_import_anchor_by_uncommitted_chain {
tracing::info!(target: tracing_targets::COLLATOR,
"uncommitted chain interval to import anchor {} reached on length {}, will import next anchor",
self.config.uncommitted_chain_to_import_next_anchor, uncommitted_chain_length,
"uncommitted chain interval to import anchor gas {} with limit {} reached on length {}, will import next anchor",
gas_used, self.config.gas_used_to_import_next_anchor, uncommitted_chain_length,
);
}
let (next_anchor, next_anchor_has_externals) = self.import_next_anchor().await?;
Expand All @@ -766,6 +771,7 @@ impl CollatorStdImpl {
"just imported anchor has externals, will collate next block",
);
}
self.working_state_mut().prev_shard_data.clear_gas_used();
Some((next_anchor, next_anchor_has_externals))
} else {
None
Expand Down
Loading
Loading