Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 5 additions & 1 deletion ethexe/processor/src/handling/overlaid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ impl RunContext for OverlaidRunContext {
}

fn states(&self, processing_queue_type: MessageType) -> Vec<ActorStateHashWithQueueSize> {
run::states(&self.inner.transitions, processing_queue_type)
run::states(
&self.inner.db,
&self.inner.transitions,
processing_queue_type,
)
}

fn handle_chunk_data(
Expand Down
149 changes: 147 additions & 2 deletions ethexe/processor/src/handling/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ use ethexe_common::{
use ethexe_db::{CASDatabase, Database};
use ethexe_runtime_common::{
BlockInfo, InBlockTransitions, JournalHandler, ProgramJournals, TransitionController,
state::Storage as _,
};
use futures::prelude::*;
use gear_core::{
Expand Down Expand Up @@ -438,7 +439,7 @@ impl RunContext for CommonRunContext {
}

fn states(&self, processing_queue_type: MessageType) -> Vec<ActorStateHashWithQueueSize> {
states(&self.transitions, processing_queue_type)
states(&self.db, &self.transitions, processing_queue_type)
}

fn inner(&self) -> &CommonRunContext {
Expand Down Expand Up @@ -526,6 +527,7 @@ pub(super) fn instrumented_code_and_metadata(
}

pub(super) fn states(
db: &Database,
in_block_transitions: &InBlockTransitions,
processing_queue_type: MessageType,
) -> Vec<ActorStateHashWithQueueSize> {
Expand All @@ -540,6 +542,14 @@ pub(super) fn states(
if queue_size == 0 {
return None;
}

let program_state = db
.program_state(state.hash)
.expect("program state from transitions must exist in storage");
Comment thread
playX18 marked this conversation as resolved.
if program_state.executable_balance == 0 {
return None;
}

let actor_state = ActorStateHashWithQueueSize::new(actor_id, state);

Some(actor_state)
Expand Down Expand Up @@ -567,13 +577,17 @@ mod tests {
const CHUNK_PROCESSING_THREADS: usize = 16;
const MAX_QUEUE_SIZE: u8 = 20;

let db = Database::memory();
let mut i = 0;
let mut states_to_queue_size = HashMap::new();

let states = std::iter::repeat_with(|| {
i += 1;
let hash = H256::from_low_u64_le(i);
let canonical_queue_size = rand::random::<u8>() % MAX_QUEUE_SIZE + 1;
let mut program_state = ProgramState::zero();
program_state.balance = i as u128;
program_state.executable_balance = 1;
let hash = db.write_program_state(program_state);
states_to_queue_size.insert(hash, canonical_queue_size as usize);

(
Expand Down Expand Up @@ -630,6 +644,137 @@ mod tests {
}
}

#[test]
fn chunk_partitioning_skips_zero_executable_balance_programs() {
let db = Database::memory();
let skipped = ActorId::from(1);
let executable_without_owned_balance = ActorId::from(2);
let executable_with_owned_balance = ActorId::from(3);

let write_program_state = |balance, executable_balance| {
let mut state = ProgramState::zero();
state.balance = balance;
state.executable_balance = executable_balance;
db.write_program_state(state)
};

let skipped_hash = write_program_state(1_000, 0);
let executable_without_owned_balance_hash = write_program_state(0, 1_000);
let executable_with_owned_balance_hash = write_program_state(1_000, 1_000);

let states = BTreeMap::from([
(
skipped,
StateHashWithQueueSize {
hash: skipped_hash,
canonical_queue_size: 1,
injected_queue_size: 0,
},
),
(
executable_without_owned_balance,
StateHashWithQueueSize {
hash: executable_without_owned_balance_hash,
canonical_queue_size: 1,
injected_queue_size: 0,
},
),
(
executable_with_owned_balance,
StateHashWithQueueSize {
hash: executable_with_owned_balance_hash,
canonical_queue_size: 1,
injected_queue_size: 0,
},
),
]);
let transitions =
InBlockTransitions::new(TransitionsConfig::default(), states, Default::default());
let mut ctx = CommonRunContext::new(
db.clone(),
InstanceCreator::new(db.clone(), host::runtime()).unwrap(),
transitions,
1_000_000,
2,
3,
3,
None,
);

let chunks = chunks_splitting::prepare_execution_chunks(&mut ctx, MessageType::Canonical);

assert_eq!(chunks.len(), 1);
let chunk = chunks.first().expect("one chunk must be prepared");
assert_eq!(chunk.len(), 2);
assert!(chunk.iter().all(|(program_id, _)| *program_id != skipped));
assert!(chunk.iter().any(|(program_id, state_hash)| {
*program_id == executable_without_owned_balance
&& *state_hash == executable_without_owned_balance_hash
}));
assert!(chunk.iter().any(|(program_id, state_hash)| {
*program_id == executable_with_owned_balance
&& *state_hash == executable_with_owned_balance_hash
}));
}

#[test]
fn chunk_partitioning_skips_zero_executable_balance_programs_injected_queue() {
let db = Database::memory();
let skipped = ActorId::from(1);
let executable = ActorId::from(2);

let write_program_state = |balance, executable_balance| {
let mut state = ProgramState::zero();
state.balance = balance;
state.executable_balance = executable_balance;
db.write_program_state(state)
};

let skipped_hash = write_program_state(1_000, 0);
let executable_hash = write_program_state(1_000, 1_000);

let states = BTreeMap::from([
(
skipped,
StateHashWithQueueSize {
hash: skipped_hash,
canonical_queue_size: 0,
injected_queue_size: 1,
},
),
(
executable,
StateHashWithQueueSize {
hash: executable_hash,
canonical_queue_size: 0,
injected_queue_size: 1,
},
),
]);
let transitions =
InBlockTransitions::new(TransitionsConfig::default(), states, Default::default());
let mut ctx = CommonRunContext::new(
db.clone(),
InstanceCreator::new(db.clone(), host::runtime()).unwrap(),
transitions,
1_000_000,
2,
3,
3,
None,
);

let chunks = chunks_splitting::prepare_execution_chunks(&mut ctx, MessageType::Injected);

assert_eq!(chunks.len(), 1);
let chunk = chunks.first().expect("one chunk must be prepared");
assert_eq!(chunk.len(), 1);
assert!(chunk.iter().all(|(program_id, _)| *program_id != skipped));
assert!(chunk.iter().any(|(program_id, state_hash)| {
*program_id == executable && *state_hash == executable_hash
}));
}

#[test]
fn nullification() {
let db = Database::memory();
Expand Down
Loading