Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions core-processor/src/precharge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use core::marker::PhantomData;
use gear_core::{
code::{CodeMetadata, InstantiatedSectionSizes, SectionName},
costs::{BytesAmount, ProcessCosts},
gas::{ChargeResult, GasAllowanceCounter, GasCounter},
gas::{GasAllowanceCounter, GasCounter},
ids::ActorId,
message::IncomingDispatch,
};
Expand Down Expand Up @@ -61,6 +61,27 @@ pub enum PreChargeGasOperation {
/// Obtain program allocations.
#[display("obtain program allocations")]
Allocations,
/// Other operations.
#[display("{description}")]
Other {
/// Operation description.
description: &'static str,

/// Whether the operation affects block gas allowance.
affects_allowance: bool,
},
}

impl PreChargeGasOperation {
/// Checks whether the operation affects block gas allowance.
pub const fn affects_allowance(&self) -> bool {
Comment thread
liferooter marked this conversation as resolved.
match self {
&Self::Other {
affects_allowance, ..
} => affects_allowance,
_ => true,
}
}
}

/// Defines result variants of the precharge functions.
Expand Down Expand Up @@ -142,13 +163,34 @@ impl<T> ContextCharged<T> {
self.gas_counter.left()
}

/// Charges gas for a non-standard operation.
pub fn charge_extra_fee(
self,
description: &'static str,
affects_allowance: bool,
amount: u64,
) -> PrechargeResult<Self> {
self.charge_gas(
PreChargeGasOperation::Other {
description,
affects_allowance,
},
amount,
)
}

/// Charges gas for the operation.
fn charge_gas<For>(
mut self,
operation: PreChargeGasOperation,
amount: u64,
) -> PrechargeResult<ContextCharged<For>> {
if self.gas_allowance_counter.charge_if_enough(amount) != ChargeResult::Enough {
if operation.affects_allowance()
&& self
.gas_allowance_counter
.charge_if_enough(amount)
.is_not_enough()
{
let gas_burned = self.gas_counter.burned();

return Err(process_allowance_exceed(
Expand All @@ -158,7 +200,7 @@ impl<T> ContextCharged<T> {
));
}

if self.gas_counter.charge_if_enough(amount) != ChargeResult::Enough {
if self.gas_counter.charge_if_enough(amount).is_not_enough() {
let gas_burned = self.gas_counter.burned();
let system_reservation_ctx = SystemReservationContext::from_dispatch(&self.dispatch);

Expand Down
27 changes: 26 additions & 1 deletion ethexe/processor/src/handling/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ use ethexe_runtime_common::{
use gear_core::gas::GasAllowanceCounter;
use gprimitives::{ActorId, H256};
use itertools::Itertools;
use std::collections::HashSet;

#[derive(Debug, Clone)]
pub struct RunnerConfig {
Expand Down Expand Up @@ -163,11 +164,16 @@ pub async fn run(
let mut allowance_counter = GasAllowanceCounter::new(config.block_gas_limit);
let chunk_size = config.chunk_processing_threads;

// Set of programs which has already processed
// their queue. Used to charge first message fee.
let mut processed_first_queue = HashSet::new();

// Start with injected queues processing.
let is_out_of_gas_for_block = run_inner(
&mut run_ctx,
db.clone(),
instance_creator.clone(),
&mut processed_first_queue,
&mut allowance_counter,
chunk_size,
MessageType::Injected,
Expand All @@ -180,6 +186,7 @@ pub async fn run(
&mut run_ctx,
db,
instance_creator,
&mut processed_first_queue,
&mut allowance_counter,
chunk_size,
MessageType::Canonical,
Expand All @@ -203,6 +210,7 @@ pub async fn run_overlaid(
&mut run_ctx,
db,
instance_creator,
&mut HashSet::new(),
&mut allowance_counter,
chunk_size,
MessageType::Canonical,
Expand All @@ -217,6 +225,7 @@ async fn run_inner<C: RunContext>(
run_ctx: &mut C,
db: Database,
instance_creator: InstanceCreator,
processed_first_queue: &mut HashSet<ActorId>,
allowance_counter: &mut GasAllowanceCounter,
chunk_size: usize,
processing_queue_type: MessageType,
Expand Down Expand Up @@ -246,6 +255,7 @@ async fn run_inner<C: RunContext>(
chunk,
db.clone(),
instance_creator.clone(),
processed_first_queue,
allowance_counter.left().min(CHUNK_PROCESSING_GAS_LIMIT),
processing_queue_type,
)
Expand Down Expand Up @@ -591,13 +601,25 @@ mod chunk_execution_spawn {
chunk: Vec<(ActorId, H256)>,
db: Database,
instance_creator: InstanceCreator,
processed_first_queue: &mut HashSet<ActorId>,
gas_allowance_for_chunk: u64,
processing_queue_type: MessageType,
) -> Vec<ChunkItemOutput> {
let chunk = chunk
.into_iter()
.map(|(program_id, state_hash)| {
(
program_id,
state_hash,
processed_first_queue.insert(program_id),
)
})
.collect::<Vec<_>>();
Comment thread
liferooter marked this conversation as resolved.
Outdated

tokio::task::spawn_blocking(move || {
chunk
.into_par_iter()
.map(|(program_id, state_hash)| {
.map(|(program_id, state_hash, is_first_queue)| {
let db = db.clone();
let mut executor = instance_creator
.instantiate()
Expand All @@ -609,6 +631,7 @@ mod chunk_execution_spawn {
program_id,
state_hash,
processing_queue_type,
is_first_queue,
gas_allowance_for_chunk,
);
(program_id, new_state_hash, jn, gas_spent)
Expand All @@ -625,6 +648,7 @@ mod chunk_execution_spawn {
program_id: ActorId,
state_hash: H256,
queue_type: MessageType,
is_first_queue: bool,
gas_allowance: u64,
) -> (ProgramJournals, H256, u64) {
let code_id = db.program_code_id(program_id).expect("Code ID must be set");
Expand All @@ -640,6 +664,7 @@ mod chunk_execution_spawn {
queue_type,
instrumented_code,
code_metadata,
is_first_queue,
gas_allowance,
)
.expect("Some error occurs while running program in instance")
Expand Down
2 changes: 2 additions & 0 deletions ethexe/processor/src/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ impl InstanceWrapper {
queue_type: MessageType,
maybe_instrumented_code: Option<InstrumentedCode>,
maybe_code_metadata: Option<CodeMetadata>,
is_first_queue: bool,
gas_allowance: u64,
) -> Result<(ProgramJournals, H256, u64)> {
let chain_head = self.chain_head.expect("chain head must be set before run");
Expand All @@ -171,6 +172,7 @@ impl InstanceWrapper {
queue_type,
maybe_instrumented_code,
maybe_code_metadata,
is_first_queue,
gas_allowance,
);

Expand Down
Loading
Loading