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

fault_proving(compression): include block_id in da compressed block headers #2551

Merged
merged 18 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [2472](https://github.com/FuelLabs/fuel-core/pull/2472): Added the `amountU128` field to the `Balance` GraphQL schema, providing the total balance as a `U128`. The existing `amount` field clamps any balance exceeding `U64` to `u64::MAX`.
- [2526](https://github.com/FuelLabs/fuel-core/pull/2526): Add possibility to not have any cache set for RocksDB. Add an option to either load the RocksDB columns families on creation of the database or when the column is used.
- [2532](https://github.com/FuelLabs/fuel-core/pull/2532): Getters for inner rocksdb database handles.
- [2551](https://github.com/FuelLabs/fuel-core/pull/2551): Enhanced the DA compressed block header to include block id.

### Fixed
- [2365](https://github.com/FuelLabs/fuel-core/pull/2365): Fixed the error during dry run in the case of race condition.
Expand Down
1 change: 1 addition & 0 deletions bin/fuel-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,4 @@ production = [
"parquet",
"aws-kms",
]
fault-proving = ["fuel-core-compression/fault-proving"]
1 change: 1 addition & 0 deletions crates/compression/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ test-helpers = [
"fuel-core-types/random",
"fuel-core-types/std",
]
fault-proving = []
19 changes: 17 additions & 2 deletions crates/compression/src/compress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::{
RegistrationsPerTable,
TemporalRegistryAll,
},
CompressedBlockPayloadV0,
VersionedCompressedBlock,
};
use anyhow::Context;
Expand Down Expand Up @@ -42,6 +41,15 @@ use std::collections::{
HashSet,
};

#[cfg(feature = "fault-proving")]
use crate::{
CompressedBlockHeader,
CompressedBlockPayloadV1,
};

#[cfg(not(feature = "fault-proving"))]
use crate::CompressedBlockPayloadV0;

pub trait CompressDb: TemporalRegistryAll + EvictorDbAll + UtxoIdToPointer {}
impl<T> CompressDb for T where T: TemporalRegistryAll + EvictorDbAll + UtxoIdToPointer {}

Expand Down Expand Up @@ -70,10 +78,17 @@ where
let transactions = target.compress_with(&mut ctx).await?;
let registrations: RegistrationsPerTable = ctx.finalize()?;

Ok(VersionedCompressedBlock::V0(CompressedBlockPayloadV0 {
#[cfg(not(feature = "fault-proving"))]
return Ok(VersionedCompressedBlock::V0(CompressedBlockPayloadV0 {
registrations,
header: block.header().into(),
transactions,
}));
#[cfg(feature = "fault-proving")]
Ok(VersionedCompressedBlock::V1(CompressedBlockPayloadV1 {
registrations,
header: CompressedBlockHeader::from(block.header()),
transactions,
}))
}

Expand Down
14 changes: 6 additions & 8 deletions crates/compression/src/decompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,26 @@ pub async fn decompress<D>(
where
D: DecompressDb,
{
let VersionedCompressedBlock::V0(compressed) = block;

// TODO: merkle root verification: https://github.com/FuelLabs/fuel-core/issues/2232

compressed
.registrations
.write_to_registry(&mut db, compressed.header.consensus.time)?;
block
.registrations()
.write_to_registry(&mut db, block.consensus_header().time)?;

let ctx = DecompressCtx {
config,
timestamp: compressed.header.consensus.time,
timestamp: block.consensus_header().time,
db,
};

let transactions = <Vec<Transaction> as DecompressibleBy<_>>::decompress_with(
compressed.transactions,
block.transactions(),
&ctx,
)
.await?;

Ok(PartialFuelBlock {
header: compressed.header,
header: block.partial_block_header(),
transactions,
})
}
Expand Down
193 changes: 175 additions & 18 deletions crates/compression/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,19 @@ mod registry;
pub use config::Config;
pub use registry::RegistryKeyspace;

#[cfg(feature = "fault-proving")]
use fuel_core_types::blockchain::header::BlockHeader;
#[cfg(feature = "fault-proving")]
use fuel_core_types::blockchain::primitives::BlockId;
use fuel_core_types::{
blockchain::header::PartialBlockHeader,
blockchain::{
header::{
ApplicationHeader,
ConsensusHeader,
PartialBlockHeader,
},
primitives::Empty,
},
fuel_tx::CompressedTransaction,
fuel_types::BlockHeight,
};
Expand All @@ -31,10 +42,79 @@ pub struct CompressedBlockPayloadV0 {
pub transactions: Vec<CompressedTransaction>,
}

#[cfg(feature = "fault-proving")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(
feature = "fault-proving",
derive(serde::Serialize, serde::Deserialize)
)]
#[derive(Default)]
/// A partially complete fuel block header that does not
/// have any generated fields because it has not been executed yet.
pub struct CompressedBlockHeader {
/// The application header.
pub application: ApplicationHeader<Empty>,
/// The consensus header.
pub consensus: ConsensusHeader<Empty>,
// The block id.
pub block_id: BlockId,
}

#[cfg(feature = "fault-proving")]
impl From<&BlockHeader> for CompressedBlockHeader {
fn from(header: &BlockHeader) -> Self {
let ConsensusHeader {
prev_root,
height,
time,
..
} = *header.consensus();
CompressedBlockHeader {
application: ApplicationHeader {
da_height: header.da_height,
consensus_parameters_version: header.consensus_parameters_version,
state_transition_bytecode_version: header
.state_transition_bytecode_version,
generated: Empty {},
},
consensus: ConsensusHeader {
prev_root,
height,
time,
generated: Empty {},
},
block_id: header.id(),
}
}
}

#[cfg(feature = "fault-proving")]
impl From<&CompressedBlockHeader> for PartialBlockHeader {
fn from(value: &CompressedBlockHeader) -> Self {
PartialBlockHeader {
application: value.application,
consensus: value.consensus,
}
}
}

#[cfg(feature = "fault-proving")]
#[derive(Debug, Default, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct CompressedBlockPayloadV1 {
/// Temporal registry insertions
pub registrations: RegistrationsPerTable,
/// Compressed block header
pub header: CompressedBlockHeader,
/// Compressed transactions
pub transactions: Vec<CompressedTransaction>,
}
acerone85 marked this conversation as resolved.
Show resolved Hide resolved

/// Versioned compressed block.
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum VersionedCompressedBlock {
V0(CompressedBlockPayloadV0),
#[cfg(feature = "fault-proving")]
V1(CompressedBlockPayloadV1),
}

impl Default for VersionedCompressedBlock {
Expand All @@ -48,12 +128,62 @@ impl VersionedCompressedBlock {
pub fn height(&self) -> &BlockHeight {
match self {
VersionedCompressedBlock::V0(block) => block.header.height(),
#[cfg(feature = "fault-proving")]
VersionedCompressedBlock::V1(block) => &block.header.consensus.height,
}
}
acerone85 marked this conversation as resolved.
Show resolved Hide resolved

/// Returns the consensus header
pub fn consensus_header(&self) -> &ConsensusHeader<Empty> {
match self {
VersionedCompressedBlock::V0(block) => &block.header.consensus,
#[cfg(feature = "fault-proving")]
VersionedCompressedBlock::V1(block) => &block.header.consensus,
}
}

/// Returns the application header
pub fn application_header(&self) -> &ApplicationHeader<Empty> {
match self {
VersionedCompressedBlock::V0(block) => &block.header.application,
#[cfg(feature = "fault-proving")]
VersionedCompressedBlock::V1(block) => &block.header.application,
}
}

/// Returns the registrations table
pub fn registrations(&self) -> &RegistrationsPerTable {
match self {
VersionedCompressedBlock::V0(block) => &block.registrations,
#[cfg(feature = "fault-proving")]
VersionedCompressedBlock::V1(block) => &block.registrations,
}
}

/// Returns the transactions
pub fn transactions(&self) -> Vec<CompressedTransaction> {
match self {
VersionedCompressedBlock::V0(block) => block.transactions.clone(),
#[cfg(feature = "fault-proving")]
VersionedCompressedBlock::V1(block) => block.transactions.clone(),
}
}

/// Returns the partial block header
pub fn partial_block_header(&self) -> PartialBlockHeader {
match self {
VersionedCompressedBlock::V0(block) => block.header,
#[cfg(feature = "fault-proving")]
VersionedCompressedBlock::V1(block) => {
PartialBlockHeader::from(&block.header)
}
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use fuel_core_compression as _;
use fuel_core_types::{
blockchain::{
Expand All @@ -67,8 +197,8 @@ mod tests {
tai64::Tai64,
};
use proptest::prelude::*;

use super::*;
#[cfg(feature = "fault-proving")]
use std::str::FromStr;

fn keyspace() -> impl Strategy<Value = RegistryKeyspace> {
prop_oneof![
Expand Down Expand Up @@ -121,6 +251,7 @@ mod tests {
}
}

#[cfg(not(feature = "fault-proving"))]
let header = PartialBlockHeader {
application: ApplicationHeader {
da_height: da_height.into(),
Expand All @@ -135,31 +266,57 @@ mod tests {
generated: Empty
}
};
let original = CompressedBlockPayloadV0 {
#[cfg(feature = "fault-proving")]
let header = CompressedBlockHeader {
application: ApplicationHeader {
da_height: da_height.into(),
consensus_parameters_version,
state_transition_bytecode_version,
generated: Empty,
},
consensus: ConsensusHeader {
prev_root: prev_root.into(),
height: height.into(),
time: Tai64::UNIX_EPOCH,
generated: Empty,
},
block_id: BlockId::from_str("0xecea85c17070bc2e65f911310dbd01198f4436052ebba96cded9ddf30c58dd1a").unwrap(),
};

#[cfg(not(feature = "fault-proving"))]
let original = VersionedCompressedBlock::V0(CompressedBlockPayloadV0 {
registrations,
header,
transactions: vec![],
};
});
#[cfg(feature = "fault-proving")]
let original = VersionedCompressedBlock::V1(CompressedBlockPayloadV1 {
registrations,
header,
transactions: vec![]
});

let compressed = postcard::to_allocvec(&original).unwrap();
let decompressed: CompressedBlockPayloadV0 =
let decompressed: VersionedCompressedBlock =
postcard::from_bytes(&compressed).unwrap();

let CompressedBlockPayloadV0 {
registrations,
header,
transactions,
} = decompressed;
let consensus_header = decompressed.consensus_header();
let application_header = decompressed.application_header();

assert_eq!(registrations, original.registrations);
assert_eq!(decompressed.registrations(), original.registrations());

assert_eq!(header.da_height, da_height.into());
assert_eq!(*header.prev_root(), prev_root.into());
assert_eq!(*header.height(), height.into());
assert_eq!(header.consensus_parameters_version, consensus_parameters_version);
assert_eq!(header.state_transition_bytecode_version, state_transition_bytecode_version);
assert_eq!(application_header.da_height, da_height.into());
assert_eq!(consensus_header.prev_root, prev_root.into());
assert_eq!(consensus_header.height, height.into());
assert_eq!(application_header.consensus_parameters_version, consensus_parameters_version);
assert_eq!(application_header.state_transition_bytecode_version, state_transition_bytecode_version);

assert!(transactions.is_empty());
assert!(decompressed.transactions().is_empty());

#[cfg(feature = "fault-proving")]
if let VersionedCompressedBlock::V1(block) = decompressed {
assert_eq!(block.header.block_id, header.block_id);
}
}
}
}
1 change: 1 addition & 0 deletions crates/fuel-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,4 @@ test-helpers = [
# features to enable in production, but increase build times
rocksdb-production = ["rocksdb", "rocksdb/jemalloc"]
wasm-executor = ["fuel-core-upgradable-executor/wasm-executor"]
fault-proving = ["fuel-core-compression/fault-proving"]
Loading