Skip to content

Commit d822904

Browse files
authored
fault_proving(compression): implement compression in compression service (#2844)
## Linked Issues/PRs <!-- List of related issues/PRs --> - part of #2775 ## Description <!-- List of detailed changes --> ai generated desc: This pull request introduces significant updates to the `fuel-core-compression-service`, including the implementation of DA compression, configuration enhancements, error handling improvements, and new features for block and storage management. The most important changes are summarized below: ### Implementation and Configuration Enhancements: * Implemented DA compression in `fuel-core-compression-service`. * Added new dependencies and features in `Cargo.toml` for `fuel-core-chain-config`, `futures`, and `paste`. [[1]](diffhunk://#diff-3b348e1ded89f349afd45656ad5c57ebbab5e690f2bf64e059dd5d7c32de228dR15-R23) [[2]](diffhunk://#diff-3b348e1ded89f349afd45656ad5c57ebbab5e690f2bf64e059dd5d7c32de228dR34-R42) * Introduced `CompressionConfig` with `temporal_registry_retention` and methods for configuration management. ### Error Handling Improvements: * Enhanced error handling in `CompressionError` by replacing string errors with `StorageError` and adding a new error variant for block compression failures. [[1]](diffhunk://#diff-4e1e8a438c26f0ee9cde7ff8e033cb1ab58ffd3f5fad9dd5f39a74269a4a971cR1) [[2]](diffhunk://#diff-4e1e8a438c26f0ee9cde7ff8e033cb1ab58ffd3f5fad9dd5f39a74269a4a971cL13-R21) ### Block and Storage Management: * Introduced `BlockWithMetadata` struct to encapsulate block data and associated events. * Updated `CompressionStorage` trait to include methods for reading and writing compressed blocks, and getting the latest height. ### Service Enhancements: * Refactored `CompressionService` to use the new configuration and block structures. [[1]](diffhunk://#diff-9fc61045febb6284fa8e01c5c33172787228fe21b8b813c62c8f03d2fec55fe8L1-R124) [[2]](diffhunk://#diff-9fc61045febb6284fa8e01c5c33172787228fe21b8b813c62c8f03d2fec55fe8L78-L82) [[3]](diffhunk://#diff-9fc61045febb6284fa8e01c5c33172787228fe21b8b813c62c8f03d2fec55fe8L105-R167) [[4]](diffhunk://#diff-9fc61045febb6284fa8e01c5c33172787228fe21b8b813c62c8f03d2fec55fe8L124-R191) [[5]](diffhunk://#diff-9fc61045febb6284fa8e01c5c33172787228fe21b8b813c62c8f03d2fec55fe8L143-R276) * Added new tests for `CompressionService` to verify its functionality with different block sources and configurations. ### Miscellaneous: * Added new module for `temporal_registry` implementations. * Introduced `timestamps` module and corresponding type alias in `storage.rs`. [[1]](diffhunk://#diff-6354c3b240b9d7af0841032b5051a86cf313008738ca64e678a1783912dd0640R22-R23) [[2]](diffhunk://#diff-6354c3b240b9d7af0841032b5051a86cf313008738ca64e678a1783912dd0640R46-R48) * Added `Timestamps` to `CompressionColumn` enum. ## Checklist - [ ] Breaking changes are clearly marked as such in the PR description and changelog - [ ] New behavior is reflected in tests - [ ] [The specification](https://github.com/FuelLabs/fuel-specs/) matches the implemented behavior (link update PR if changes are needed) ### Before requesting review - [ ] I have reviewed the code myself - [ ] I have created follow-up issues caused by this PR and linked them here ### After merging, notify other teams [Add or remove entries as needed] - [ ] [Rust SDK](https://github.com/FuelLabs/fuels-rs/) - [ ] [Sway compiler](https://github.com/FuelLabs/sway/) - [ ] [Platform documentation](https://github.com/FuelLabs/devrel-requests/issues/new?assignees=&labels=new+request&projects=&template=NEW-REQUEST.yml&title=%5BRequest%5D%3A+) (for out-of-organization contributors, the person merging the PR will do this) - [ ] Someone else?
1 parent aef46bc commit d822904

21 files changed

+851
-128
lines changed

.changes/added/2844.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Implement DA compression in `fuel-core-compression-service`.

Cargo.lock

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/services/compression/Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@ repository = { workspace = true }
1212
anyhow = { workspace = true }
1313
async-trait = { workspace = true }
1414
enum-iterator = { workspace = true }
15+
fuel-core-chain-config = { workspace = true, features = [
16+
"test-helpers",
17+
], optional = true }
1518
fuel-core-compression = { workspace = true }
1619
fuel-core-services = { workspace = true }
1720
fuel-core-storage = { workspace = true, features = ["std"] }
1821
fuel-core-types = { workspace = true }
22+
futures = { workspace = true }
23+
paste = { workspace = true }
1924
rand = { workspace = true, optional = true }
2025
serde = { workspace = true, features = ["derive"] }
2126
strum = { workspace = true, features = ["derive"] }
@@ -26,11 +31,14 @@ tracing = { workspace = true }
2631

2732
[dev-dependencies]
2833
fuel-core-compression-service = { path = ".", features = ["test-helpers"] }
34+
tokio-stream = { workspace = true }
2935

3036
[features]
3137
test-helpers = [
38+
"fuel-core-services/test-helpers",
3239
"fuel-core-types/test-helpers",
3340
"fuel-core-storage/test-helpers",
3441
"fuel-core-compression/test-helpers",
3542
"dep:rand",
43+
"dep:fuel-core-chain-config",
3644
]
+28-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
use std::time::Duration;
2+
13
/// Compression configuration
2-
#[derive(Debug, Clone)]
3-
pub struct CompressionConfig {}
4+
#[derive(Debug, Clone, Copy)]
5+
pub struct CompressionConfig {
6+
temporal_registry_retention: Duration,
7+
}
8+
9+
impl CompressionConfig {
10+
/// Create a new compression configuration
11+
pub fn new(temporal_registry_retention: Duration) -> Self {
12+
Self {
13+
temporal_registry_retention,
14+
}
15+
}
16+
17+
/// Get the temporal registry retention
18+
pub fn temporal_registry_retention(&self) -> Duration {
19+
self.temporal_registry_retention
20+
}
21+
}
22+
23+
impl From<CompressionConfig> for fuel_core_compression::Config {
24+
fn from(config: CompressionConfig) -> Self {
25+
Self {
26+
temporal_registry_retention: config.temporal_registry_retention(),
27+
}
28+
}
29+
}

crates/services/compression/src/errors.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use fuel_core_storage::Error as StorageError;
12
use thiserror::Error;
23

34
/// Errors that can occur during compression
@@ -10,11 +11,24 @@ pub enum CompressionError {
1011
// Compression storage Errors
1112
/// Failed to read compressed block from storage
1213
#[error("failed to write compressed block to storage: `{0}`")]
13-
FailedToWriteCompressedBlock(String),
14+
FailedToWriteCompressedBlock(StorageError),
15+
/// Failed to commit storage transaction
16+
#[error("failed to commit transaction: `{0}`")]
17+
FailedToCommitTransaction(StorageError),
18+
/// Failed to get latest height from storage
19+
#[error("failed to get latest height from storage: `{0}`")]
20+
FailedToGetLatestHeight(StorageError),
21+
// Configuration Errors
22+
/// Failed to get config
23+
#[error("failed to get configuration: `{0}`")]
24+
FailedToGetConfig(String),
1425
// Service errors
1526
/// Failed to create service
1627
#[error("failed to create service: `{0}`")]
1728
FailedToCreateService(String),
29+
/// Failed to compress block
30+
#[error("failed to compress block: `{0}`")]
31+
FailedToCompressBlock(anyhow::Error),
1832
/// Failed to handle new block
1933
#[error("failed to handle new block: `{0}`")]
2034
FailedToHandleNewBlock(String),

crates/services/compression/src/lib.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
#![deny(unused_crate_dependencies)]
66
#![deny(missing_docs)]
77
#![deny(warnings)]
8-
// we allow unused for now while incrementally creating this service.
9-
#![allow(unused)]
108

119
/// Configuration for the compression service
1210
pub mod config;
@@ -16,9 +14,10 @@ pub mod errors;
1614
pub mod ports;
1715
/// Service definition for the compression service
1816
pub mod service;
19-
2017
/// Storage traits for the compression service
2118
pub mod storage;
19+
/// Temporal Registry implementations
20+
pub mod temporal_registry;
2221

2322
/// Result type for compression operations
2423
pub type Result<T> = core::result::Result<T, errors::CompressionError>;
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
1-
/// Type alias for fuel_core_types::blockchain::block::Block
2-
pub type Block = fuel_core_types::blockchain::block::Block;
1+
use fuel_core_services::stream::BoxStream;
2+
3+
/// Block with metadata needed for compression
4+
#[cfg_attr(feature = "test-helpers", derive(Default))]
5+
#[derive(Clone, Debug)]
6+
pub struct BlockWithMetadata {
7+
block: fuel_core_types::blockchain::block::Block,
8+
// todo: perhaps slice with lifetime? (https://github.com/FuelLabs/fuel-core/issues/2870)
9+
events: Vec<fuel_core_types::services::executor::Event>,
10+
}
11+
12+
impl BlockWithMetadata {
13+
/// Create a new block with metadata
14+
pub fn new(
15+
block: fuel_core_types::blockchain::block::Block,
16+
events: Vec<fuel_core_types::services::executor::Event>,
17+
) -> Self {
18+
Self { block, events }
19+
}
20+
21+
pub(crate) fn height(&self) -> u32 {
22+
(*self.block.header().height()).into()
23+
}
24+
25+
pub(crate) fn events(&self) -> &[fuel_core_types::services::executor::Event] {
26+
&self.events
27+
}
28+
29+
pub(crate) fn block(&self) -> &fuel_core_types::blockchain::block::Block {
30+
&self.block
31+
}
32+
}
33+
34+
/// Type alias for returned value by .subscribe() method on `BlockSource`
35+
pub type BlockStream = BoxStream<BlockWithMetadata>;
336

437
/// Port for L2 blocks source
5-
/// Each time `.next()` is called, the service expects the same behaviour as an iterator.
638
pub trait BlockSource {
7-
/// Get the next block from the source
8-
fn next(
9-
&self,
10-
) -> impl core::future::Future<Output = crate::Result<Option<Block>>> + Send + Sync;
39+
/// Should provide a stream of blocks with metadata
40+
fn subscribe(&self) -> BoxStream<BlockWithMetadata>;
1141
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,50 @@
1+
use crate::storage;
2+
use fuel_core_storage::{
3+
kv_store::KeyValueInspect,
4+
merkle::column::MerkleizedColumn,
5+
transactional::{
6+
Modifiable,
7+
StorageTransaction,
8+
},
9+
StorageAsMut,
10+
};
11+
112
/// Compressed block type alias
213
pub type CompressedBlock = fuel_core_compression::VersionedCompressedBlock;
314

415
/// Trait for interacting with storage that supports compression
5-
pub trait CompressionStorage {
6-
/// Write a compressed block to storage
16+
pub trait CompressionStorage:
17+
KeyValueInspect<Column = MerkleizedColumn<storage::column::CompressionColumn>>
18+
+ Modifiable
19+
{
20+
}
21+
22+
impl<T> CompressionStorage for T where
23+
T: KeyValueInspect<Column = MerkleizedColumn<storage::column::CompressionColumn>>
24+
+ Modifiable
25+
{
26+
}
27+
28+
pub(crate) trait WriteCompressedBlock {
729
fn write_compressed_block(
830
&mut self,
9-
compressed_block: &CompressedBlock,
31+
height: &u32,
32+
compressed_block: &crate::ports::compression_storage::CompressedBlock,
1033
) -> crate::Result<()>;
1134
}
35+
36+
impl<Storage> WriteCompressedBlock for StorageTransaction<Storage>
37+
where
38+
Storage:
39+
KeyValueInspect<Column = MerkleizedColumn<storage::column::CompressionColumn>>,
40+
{
41+
fn write_compressed_block(
42+
&mut self,
43+
height: &u32,
44+
compressed_block: &crate::ports::compression_storage::CompressedBlock,
45+
) -> crate::Result<()> {
46+
self.storage_as_mut::<storage::CompressedBlocks>()
47+
.insert(&(*height).into(), compressed_block)
48+
.map_err(crate::errors::CompressionError::FailedToWriteCompressedBlock)
49+
}
50+
}

0 commit comments

Comments
 (0)