Skip to content
Draft
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
3 changes: 1 addition & 2 deletions ethexe/cli/src/commands/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use ethexe_db::{
};
use ethexe_processor::{Processor, ProcessorConfig};
use ethexe_runtime_common::FinalizedBlockTransitions;
use gprimitives::H256;
use indicatif::{ProgressBar, ProgressStyle};
use std::{collections::HashSet, path::PathBuf};

Expand Down Expand Up @@ -337,7 +336,7 @@ impl Checker {
pb.inc(1);
};

if current_compact_mb.parent == H256::zero() {
if current_compact_mb.parent.is_zero() {
break;
}
current_mb = current_compact_mb.parent;
Expand Down
21 changes: 13 additions & 8 deletions ethexe/cli/src/commands/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::params::{MergeParams, Params};
use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use ethexe_common::db::GlobalsStorageRO;
use ethexe_common::{EB, HashOf, db::GlobalsStorageRO};
use ethexe_db::{Database, RawDatabase, RocksDatabase, dump::StateDump};
use gprimitives::H256;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -75,13 +75,18 @@ impl DumpCommand {
let raw_db = RawDatabase::from_one(&rocks_db);
let db = Database::try_from_raw(raw_db)?;

let block_hash = block_hash.unwrap_or_else(|| {
let latest_prepared_block = db.globals().latest_prepared_eb_hash;
log::info!(
"No block hash provided, using latest committed block: {latest_prepared_block:?}"
);
latest_prepared_block
});
let block_hash = block_hash
.map(|raw| {
// SAFETY: CLI-supplied EB hash; treat verbatim.
unsafe { HashOf::<EB>::new(raw) }
})
.unwrap_or_else(|| {
let latest_prepared_block = db.globals().latest_prepared_eb_hash;
log::info!(
"No block hash provided, using latest committed block: {latest_prepared_block:?}"
);
latest_prepared_block
});

log::info!("Collecting state dump for block {block_hash:?}...");
let dump = StateDump::collect_from_storage(&db, block_hash)?;
Expand Down
2 changes: 1 addition & 1 deletion ethexe/cli/src/commands/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ impl TxCommand {
Ok(SendMessageResult::Injected {
tx_hash,
reference_block_number,
reference_block_hash,
reference_block_hash: reference_block_hash.inner(),
payload: SendMessagePayload {
message_id,
actor_id,
Expand Down
94 changes: 44 additions & 50 deletions ethexe/common/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
//! Common db types and traits.

use crate::{
Address, BlockHeader, CodeBlobInfo, Digest, HashOf, ProgramStates, ProtocolTimelines, Schedule,
SimpleBlockData, ValidatorsVec,
Address, BlockHeader, CodeBlobInfo, Digest, EB, HashOf, ProgramStates, ProtocolTimelines,
Schedule, ValidatorsVec,
events::BlockEvent,
gear::StateTransition,
injected::{InjectedTransaction, Promise, SignedInjectedTransaction, SignedTxReceipt},
malachite::Operations,
malachite::{MB, Operations},
};

// Re-export so existing `ethexe_common::db::CompactMb` imports keep working
// — the type itself now lives in `ethexe_common::malachite` alongside `MB`.
pub use crate::malachite::CompactMb;
use alloc::{
collections::{BTreeSet, VecDeque},
vec::Vec,
Expand All @@ -34,9 +38,9 @@ pub struct BlockMeta {
/// Last committed on-chain batch hash (digest).
pub last_committed_batch: Option<Digest>,
/// Last committed MB hash.
pub last_committed_mb: Option<H256>,
pub last_committed_mb: Option<HashOf<MB>>,
/// Last committed EB hash.
pub last_committed_eb: Option<H256>,
pub last_committed_eb: Option<HashOf<EB>>,
/// Latest era with committed validators.
pub latest_era_validators_committed: Option<u64>,
}
Expand All @@ -49,14 +53,14 @@ pub trait HashStorageRO {
#[auto_impl::auto_impl(&, Box)]
pub trait BlockMetaStorageRO {
/// NOTE: if `BlockMeta` doesn't exist in the database, it will return the default value.
fn block_meta(&self, block_hash: H256) -> BlockMeta;
fn block_meta(&self, block_hash: HashOf<EB>) -> BlockMeta;
}

#[auto_impl::auto_impl(&)]
pub trait BlockMetaStorageRW: BlockMetaStorageRO {
/// NOTE: if `BlockMeta` doesn't exist in the database,
/// it will be created with default values and then will be mutated.
fn mutate_block_meta(&self, block_hash: H256, f: impl FnOnce(&mut BlockMeta));
fn mutate_block_meta(&self, block_hash: HashOf<EB>, f: impl FnOnce(&mut BlockMeta));
}

#[auto_impl::auto_impl(&, Box)]
Expand Down Expand Up @@ -84,14 +88,14 @@ pub trait CodesStorageRW: CodesStorageRO {

#[auto_impl::auto_impl(&, Box)]
pub trait OnChainStorageRO {
fn block_header(&self, block_hash: H256) -> Option<BlockHeader>;
fn block_events(&self, block_hash: H256) -> Option<Vec<BlockEvent>>;
fn block_header(&self, block_hash: HashOf<EB>) -> Option<BlockHeader>;
fn block_events(&self, block_hash: HashOf<EB>) -> Option<Vec<BlockEvent>>;
fn code_blob_info(&self, code_id: CodeId) -> Option<CodeBlobInfo>;
fn block_synced(&self, block_hash: H256) -> bool;
fn block_synced(&self, block_hash: HashOf<EB>) -> bool;
fn validators(&self, era_index: u64) -> Option<ValidatorsVec>;

fn block_simple_data(&self, block_hash: H256) -> Option<SimpleBlockData> {
self.block_header(block_hash).map(|header| SimpleBlockData {
fn block_simple_data(&self, block_hash: HashOf<EB>) -> Option<EB> {
self.block_header(block_hash).map(|header| EB {
hash: block_hash,
header,
})
Expand All @@ -100,11 +104,11 @@ pub trait OnChainStorageRO {

#[auto_impl::auto_impl(&)]
pub trait OnChainStorageRW: OnChainStorageRO {
fn set_block_header(&self, block_hash: H256, header: BlockHeader);
fn set_block_events(&self, block_hash: H256, events: &[BlockEvent]);
fn set_block_header(&self, block_hash: HashOf<EB>, header: BlockHeader);
fn set_block_events(&self, block_hash: HashOf<EB>, events: &[BlockEvent]);
fn set_code_blob_info(&self, code_id: CodeId, code_info: CodeBlobInfo);
fn set_validators(&self, era_index: u64, validator_set: ValidatorsVec);
fn set_block_synced(&self, block_hash: H256);
fn set_block_synced(&self, block_hash: HashOf<EB>);
}

#[auto_impl::auto_impl(&)]
Expand All @@ -131,51 +135,38 @@ pub trait InjectedStorageRW: InjectedStorageRO {
fn set_receipt(&self, receipt: &SignedTxReceipt);
}

/// MB static identity. Keyed by the Blake2b envelope hash; existence implies
/// the matching `Operations` blob is in CAS at `operations_hash`.
#[derive(
Debug, Clone, Copy, Default, Encode, Decode, TypeInfo, PartialEq, Eq, Hash, derive_more::Display,
)]
#[display("MB(height {height}, parent {parent}, operations_hash {operations_hash})")]
pub struct CompactMb {
pub parent: H256,
pub height: u64,
pub operations_hash: H256,
}

/// MB dynamic state. `last_advanced_eb` is propagated forward at save time
/// (resets on `AdvanceTillEthereumBlock`); `synced` requires this MB and every
/// ancestor to be persisted.
/// (resets on `AdvanceTillEthereumBlock`).
#[derive(Debug, Clone, Default, Encode, Decode, TypeInfo, PartialEq, Eq, Hash)]
pub struct MbMeta {
pub computed: bool,
pub last_advanced_eb: H256,
pub last_advanced_eb: HashOf<EB>,
}

#[auto_impl::auto_impl(&, Box)]
pub trait MbStorageRO {
/// Static identity (parent + height + `operations_hash`).
/// Existence implies the matching [`Operations`] blob is in the
/// CAS at `operations_hash`.
fn mb_compact_block(&self, mb_hash: H256) -> Option<CompactMb>;
fn mb_compact_block(&self, mb_hash: HashOf<MB>) -> Option<CompactMb>;
/// Read the [`Operations`] blob from CAS by its content hash.
fn operations(&self, operations_hash: H256) -> Option<Operations>;
fn mb_program_states(&self, mb_hash: H256) -> Option<ProgramStates>;
fn mb_outcome(&self, mb_hash: H256) -> Option<Vec<StateTransition>>;
fn mb_schedule(&self, mb_hash: H256) -> Option<Schedule>;
fn mb_meta(&self, mb_hash: H256) -> MbMeta;
fn mb_program_states(&self, mb_hash: HashOf<MB>) -> Option<ProgramStates>;
fn mb_outcome(&self, mb_hash: HashOf<MB>) -> Option<Vec<StateTransition>>;
fn mb_schedule(&self, mb_hash: HashOf<MB>) -> Option<Schedule>;
fn mb_meta(&self, mb_hash: HashOf<MB>) -> MbMeta;
}

#[auto_impl::auto_impl(&)]
pub trait MbStorageRW: MbStorageRO {
fn set_mb_compact_block(&self, mb_hash: H256, compact: CompactMb);
fn set_mb_compact_block(&self, mb_hash: HashOf<MB>, compact: CompactMb);
/// Write an [`Operations`] blob into the CAS and return its hash
/// (the value stored in [`CompactMb::operations_hash`]).
fn set_operations(&self, operations: Operations) -> H256;
fn set_mb_program_states(&self, mb_hash: H256, program_states: ProgramStates);
fn set_mb_outcome(&self, mb_hash: H256, outcome: Vec<StateTransition>);
fn set_mb_schedule(&self, mb_hash: H256, schedule: Schedule);
fn mutate_mb_meta(&self, mb_hash: H256, f: impl FnOnce(&mut MbMeta));
fn set_mb_program_states(&self, mb_hash: HashOf<MB>, program_states: ProgramStates);
fn set_mb_outcome(&self, mb_hash: HashOf<MB>, outcome: Vec<StateTransition>);
fn set_mb_schedule(&self, mb_hash: HashOf<MB>, schedule: Schedule);
fn mutate_mb_meta(&self, mb_hash: HashOf<MB>, f: impl FnOnce(&mut MbMeta));
}

pub struct PreparedBlockData {
Expand All @@ -184,8 +175,8 @@ pub struct PreparedBlockData {
pub latest_era_with_committed_validators: u64,
pub codes_queue: VecDeque<CodeId>,
pub last_committed_batch: Digest,
pub last_committed_mb: H256,
pub last_committed_eb: H256,
pub last_committed_mb: HashOf<MB>,
pub last_committed_eb: HashOf<EB>,
}

#[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq)]
Expand All @@ -194,24 +185,24 @@ pub struct DBConfig {
pub chain_id: u64,
pub router_address: Address,
pub timelines: ProtocolTimelines,
pub genesis_block_hash: H256,
pub genesis_block_hash: HashOf<EB>,
pub max_validators: u16,
}

#[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq)]
pub struct DBGlobals {
pub start_block_hash: H256,
pub latest_synced_eb: SimpleBlockData,
pub latest_prepared_eb_hash: H256,
pub start_block_hash: HashOf<EB>,
pub latest_synced_eb: EB,
pub latest_prepared_eb_hash: HashOf<EB>,
/// Latest MB BFT-finalized by Malachite. Rows
/// (`mb_program_states`/`mb_outcome`/`mb_schedule`) may not yet
/// be persisted — use [`Self::latest_computed_mb_hash`] for any
/// read that depends on those rows existing.
pub latest_finalized_mb_hash: H256,
pub latest_finalized_mb_hash: HashOf<MB>,
/// Latest MB whose per-row state has been written by the compute
/// pipeline. Trails `latest_finalized_mb_hash` until compute
/// catches up.
pub latest_computed_mb_hash: H256,
pub latest_computed_mb_hash: HashOf<MB>,
}

#[cfg(feature = "std")]
Expand Down Expand Up @@ -259,15 +250,16 @@ pub use mock_interfaces::{SetConfig, SetGlobals};
#[cfg(test)]
mod tests {
use super::*;
use crate::malachite::Operations;
use crate::malachite::{BlockPayload, MB, Operations};
use indoc::formatdoc;
use scale_info::{PortableRegistry, Registry, meta_type};
use sha3::{Digest, Sha3_256};

#[test]
fn ensure_types_unchanged() {
// Recomputed after the typed-hash + MB move refactor (typed MB/EB hashes).
const EXPECTED_TYPE_INFO_HASH: &str =
"600c7b8ccc11ab8c87a94170473bad7cf7c1c87973f5f56f3734ff4ad7473a2a";
"40c73820b88e8c60899d573ec47cb02b332898a418205206c2b6597517ba3ea5";

let types = [
meta_type::<BlockMeta>(),
Expand All @@ -284,6 +276,8 @@ mod tests {
meta_type::<StateTransition>(),
meta_type::<Schedule>(),
meta_type::<MbMeta>(),
meta_type::<MB>(),
meta_type::<BlockPayload>(),
meta_type::<CompactMb>(),
// NOTE: `Operation` hand-rolls its `Encode`/`Decode` (fixed-width
// u32 tag), so this TypeInfo hash does NOT cover its wire format —
Expand Down
10 changes: 5 additions & 5 deletions ethexe/common/src/gear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

//! This is supposed to be an exact copy of Gear.sol library.

use crate::{Address, Digest, ToDigest, ValidatorsVec};
use crate::{Address, Digest, EB, HashOf, ToDigest, ValidatorsVec};
use alloc::vec::Vec;
use alloy_primitives::U256 as AlloyU256;
use gear_core::message::{ReplyCode, ReplyDetails, StoredMessage, SuccessReplyReason};
Expand Down Expand Up @@ -53,7 +53,7 @@ pub struct AddressBook {
pub struct ChainCommitment {
pub transitions: Vec<StateTransition>,
pub head: H256,
pub last_advanced_eth_block: H256,
pub last_advanced_eth_block: HashOf<EB>,
}

impl ToDigest for ChainCommitment {
Expand All @@ -66,7 +66,7 @@ impl ToDigest for ChainCommitment {

hasher.update(transitions.to_digest());
hasher.update(head.0);
hasher.update(last_advanced_eth_block.0);
hasher.update(last_advanced_eth_block.inner().0);
}
}

Expand Down Expand Up @@ -162,7 +162,7 @@ pub struct BatchCommitment {
// Hash of ethereum block for which this batch has been created
// This is used to identify whether router have to apply this batch,
// it can be a batch from another branch and after reorg it's not actual anymore (currently we have predecessorBlock for this)
pub block_hash: H256,
pub block_hash: HashOf<EB>,

/// Timestamp of ethereum block for which this batch has been created
/// This timestamp is used to identify validator set to verify commitment (current or previous era)
Expand Down Expand Up @@ -198,7 +198,7 @@ impl ToDigest for BatchCommitment {
rewards_commitment,
} = self;

hasher.update(block_hash);
hasher.update(block_hash.inner());
hasher.update(crate::u64_into_uint48_be_bytes_lossy(*timestamp));
hasher.update(previous_batch);
hasher.update(expiry.to_be_bytes());
Expand Down
13 changes: 10 additions & 3 deletions ethexe/common/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use core::{
marker::PhantomData,
};
use gprimitives::H256;
use parity_scale_codec::{Decode, Encode};
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;

fn option_string<T: ToString>(value: &Option<T>) -> String {
Expand All @@ -28,7 +28,7 @@ fn shortname<T: Any>() -> &'static str {
.expect("name is empty")
}

#[derive(Encode, Decode, TypeInfo, derive_more::Into, derive_more::Display)]
#[derive(Encode, Decode, TypeInfo, MaxEncodedLen, derive_more::Into, derive_more::Display)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "std", serde(transparent))]
#[display("{hash}")]
Expand Down Expand Up @@ -102,13 +102,20 @@ impl<T> HashOf<T> {
self.hash
}

pub fn zero() -> Self {
pub const fn zero() -> Self {
Self {
hash: H256::zero(),
_phantom: PhantomData,
}
}

/// True iff this is the zero-byte sentinel hash. Useful where a
/// caller treats `H256::zero()` as "no value yet" (genesis pre-MB,
/// uninitialised parent links, etc.).
pub fn is_zero(&self) -> bool {
self.hash.is_zero()
}

#[cfg(feature = "mock")]
pub fn random() -> Self {
Self {
Expand Down
Loading
Loading