Skip to content

Commit

Permalink
feat: Preserve message proofs post-regenesis (#1891)
Browse files Browse the repository at this point in the history
Related tickets:
- Closes #1877

This PR adds block Merkle data and metadata to the list of migrated
tables during regenesis. Creating a snapshot now inlcudes the
`FuelBlockMerkleData` and `FuelBlockMerkleMetadata` tables. Loading the
snapshot writes the `FuelBlockMerkleData` and `FuelBlockMerkleMetadata`
snapshot tables to the `OldFuelBlockMerkleData` and
`OldFuelBlockMerkleMetadata` database tables respectively (2 new tables
added to the off-chain database).

When querying for a message proof, we check the block height of the
query. If the requested message proof is for block height at or above
the regenesis block height, we continue to use the on-chain database for
data lookups. If it is instead lower than the regenesis block height, we
then check the off-chain database for the `Old` tables.

This PR also refactors the block proof logic to rely on a new trait
called `DatabaseMerklizedBlocks` which provides an interface for
querying block related Merkle data. Specifically, this includes
retrieving Merkle block data and metadata, and loading the block Merkle
tree. The `DatabaseMessageProof` is now implemented by default for any
type that implements this trait, which include the on-chain and
off-chain databases that define the corresponding tables.

This PR is intended to not be a breaking change.

## Checklist
- [ ] Breaking changes are clearly marked as such in the PR description
and changelog
- [x] 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
- [x] 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?

---------

Co-authored-by: xgreenx <xgreenx9999@gmail.com>
  • Loading branch information
Brandon Vrooman and xgreenx authored May 15, 2024
1 parent 5b427eb commit 31d0741
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 33 deletions.
8 changes: 2 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- [#1891](https://github.com/FuelLabs/fuel-core/pull/1891): Regenesis now preserves `FuelBlockMerkleData` and `FuelBlockMerkleMetadata` in the off-chain table. These tables are checked when querying message proofs.
- [#1886](https://github.com/FuelLabs/fuel-core/pull/1886): Use ref to `Block` in validation code
- [#1876](https://github.com/FuelLabs/fuel-core/pull/1876): Updated benchmark to include the worst scenario for `CROO` opcode. Also include consensus parameters in bench output.

### Changed

- [#1879](https://github.com/FuelLabs/fuel-core/pull/1879): Return the old behaviour for the `discovery_works` test.
- [#1848](https://github.com/FuelLabs/fuel-core/pull/1848): Added `version` field to the `Block` and `BlockHeader` GraphQL entities. Added corresponding `version` field to the `Block` and `BlockHeader` client types in `fuel-core-client`.

### Changed

- [#1873](https://github.com/FuelLabs/fuel-core/pull/1873/): Separate dry runs from block production in executor code, remove `ExecutionKind` and `ExecutionType`, remove `thread_block_transaction` concept, remove `PartialBlockComponent` type, refactor away `inner` functions.

## [Version 0.26.0]
Expand Down
25 changes: 19 additions & 6 deletions bin/fuel-core/src/cli/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,18 @@ mod tests {

use std::iter::repeat_with;

use fuel_core::fuel_core_graphql_api::storage::transactions::{
OwnedTransactionIndexKey,
OwnedTransactions,
TransactionStatuses,
use fuel_core::{
fuel_core_graphql_api::storage::transactions::{
OwnedTransactionIndexKey,
OwnedTransactions,
TransactionStatuses,
},
producer::ports::BlockProducerDatabase,
};
use fuel_core_chain_config::{
AddTable,
AsTable,
LastBlockConfig,
SnapshotMetadata,
SnapshotReader,
StateConfig,
Expand Down Expand Up @@ -316,7 +320,10 @@ mod tests {
builder.add(self.common.contract_balance);

builder
.build(Some(self.common.block.value.header().into()))
.build(Some(LastBlockConfig::from_header(
self.common.block.value.header(),
Default::default(),
)))
.unwrap()
}

Expand Down Expand Up @@ -761,6 +768,12 @@ mod tests {
.unwrap()
.clone();
let contract_id = randomly_chosen_contract.contract_id;
let mut latest_block = original_state.last_block.unwrap();
latest_block.blocks_root = db
.db
.on_chain()
.block_header_merkle_root(&latest_block.block_height)
.unwrap();
db.flush();

// when
Expand All @@ -782,7 +795,7 @@ mod tests {
coins: vec![],
messages: vec![],
contracts: vec![randomly_chosen_contract],
last_block: original_state.last_block,
last_block: Some(latest_block),
}
);

Expand Down
46 changes: 36 additions & 10 deletions crates/chain-config/src/config/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ use fuel_core_storage::{
use fuel_core_types::{
blockchain::primitives::DaBlockHeight,
entities::contract::ContractUtxoInfo,
fuel_types::BlockHeight,
fuel_types::{
BlockHeight,
Bytes32,
},
};
use itertools::Itertools;
use serde::{
Expand All @@ -49,6 +52,10 @@ use bech32::{
};
#[cfg(feature = "test-helpers")]
use core::str::FromStr;
use fuel_core_storage::tables::merkle::{
FuelBlockMerkleData,
FuelBlockMerkleMetadata,
};
use fuel_core_types::blockchain::header::{
BlockHeader,
ConsensusParametersVersion,
Expand All @@ -57,7 +64,6 @@ use fuel_core_types::blockchain::header::{
#[cfg(feature = "test-helpers")]
use fuel_core_types::{
fuel_types::Address,
fuel_types::Bytes32,
fuel_vm::SecretKey,
};

Expand Down Expand Up @@ -89,16 +95,12 @@ pub struct LastBlockConfig {
pub consensus_parameters_version: ConsensusParametersVersion,
/// The version of state transition function used to produce last block.
pub state_transition_version: StateTransitionBytecodeVersion,
/// The Merkle root of all blocks before regenesis.
pub blocks_root: Bytes32,
}

impl From<BlockHeader> for LastBlockConfig {
fn from(header: BlockHeader) -> Self {
Self::from(&header)
}
}

impl From<&BlockHeader> for LastBlockConfig {
fn from(header: &BlockHeader) -> Self {
impl LastBlockConfig {
pub fn from_header(header: &BlockHeader, blocks_root: Bytes32) -> Self {
Self {
block_height: *header.height(),
da_block_height: header.application().da_height,
Expand All @@ -108,6 +110,7 @@ impl From<&BlockHeader> for LastBlockConfig {
state_transition_version: header
.application()
.state_transition_bytecode_version,
blocks_root,
}
}
}
Expand Down Expand Up @@ -288,6 +291,7 @@ impl crate::Randomize for StateConfig {
da_block_height: rng.gen(),
consensus_parameters_version: rng.gen(),
state_transition_version: rng.gen(),
blocks_root: rng.gen(),
}),
}
}
Expand Down Expand Up @@ -434,6 +438,26 @@ impl AddTable<SealedBlockConsensus> for StateConfigBuilder {
fn add(&mut self, _entries: Vec<TableEntry<SealedBlockConsensus>>) {}
}

impl AsTable<FuelBlockMerkleData> for StateConfig {
fn as_table(&self) -> Vec<TableEntry<FuelBlockMerkleData>> {
Vec::new() // Do not include these for now
}
}

impl AddTable<FuelBlockMerkleData> for StateConfigBuilder {
fn add(&mut self, _entries: Vec<TableEntry<FuelBlockMerkleData>>) {}
}

impl AsTable<FuelBlockMerkleMetadata> for StateConfig {
fn as_table(&self) -> Vec<TableEntry<FuelBlockMerkleMetadata>> {
Vec::new() // Do not include these for now
}
}

impl AddTable<FuelBlockMerkleMetadata> for StateConfigBuilder {
fn add(&mut self, _entries: Vec<TableEntry<FuelBlockMerkleMetadata>>) {}
}

impl AddTable<ProcessedTransactions> for StateConfigBuilder {
fn add(&mut self, _: Vec<TableEntry<ProcessedTransactions>>) {}
}
Expand Down Expand Up @@ -759,11 +783,13 @@ mod tests {
let da_block_height = 14u64.into();
let consensus_parameters_version = 321u32;
let state_transition_version = 123u32;
let blocks_root = Bytes32::from([123; 32]);
let block_config = LastBlockConfig {
block_height,
da_block_height,
consensus_parameters_version,
state_transition_version,
blocks_root,
};
let writer = writer(temp_dir.path());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ expression: encoded_json
"block_height": 2346951900,
"da_block_height": 14074420184374977699,
"consensus_parameters_version": 2019076799,
"state_transition_version": 1670454246
"state_transition_version": 1670454246,
"blocks_root": "dfa3ac8a57ea08860870fd515cf7ca6afb887dd1e09be8e451cd3c364076623c"
}
}
10 changes: 9 additions & 1 deletion crates/fuel-core/src/combined_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ impl CombinedDatabase {
#[cfg(feature = "test-helpers")]
pub fn read_state_config(&self) -> StorageResult<StateConfig> {
use fuel_core_chain_config::AddTable;
use fuel_core_producer::ports::BlockProducerDatabase;
use itertools::Itertools;
let mut builder = StateConfigBuilder::default();

Expand All @@ -180,7 +181,14 @@ impl CombinedDatabase {
);

let latest_block = self.on_chain().latest_block()?;
let state_config = builder.build(Some(latest_block.header().into()))?;
let blocks_root = self
.on_chain()
.block_header_merkle_root(latest_block.header().height())?;
let state_config =
builder.build(Some(fuel_core_chain_config::LastBlockConfig::from_header(
latest_block.header(),
blocks_root,
)))?;

Ok(state_config)
}
Expand Down
10 changes: 6 additions & 4 deletions crates/fuel-core/src/service/adapters/graphql_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use super::{
StaticGasPrice,
};
use crate::{
database::Database,
fuel_core_graphql_api::ports::{
worker,
BlockProducerPort,
Expand All @@ -15,9 +14,12 @@ use crate::{
P2pPort,
TxPoolPort,
},
service::adapters::{
P2PAdapter,
TxPoolAdapter,
service::{
adapters::{
P2PAdapter,
TxPoolAdapter,
},
Database,
},
};
use async_trait::async_trait;
Expand Down
17 changes: 13 additions & 4 deletions crates/fuel-core/src/service/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ pub fn create_genesis_block(config: &Config) -> Block {
let da_height;
let consensus_parameters_version;
let state_transition_bytecode_version;
let prev_root;

// If the rollup continues the old rollup, the height of the new block should
// be higher than that of the old chain by one to make it continuous.
Expand All @@ -196,8 +197,8 @@ pub fn create_genesis_block(config: &Config) -> Block {
.state_transition_version
.checked_add(1)
.expect("State transition bytecode version overflow");

da_height = latest_block.da_block_height;
prev_root = latest_block.blocks_root;
} else {
height = 0u32.into();
#[cfg(feature = "relayer")]
Expand All @@ -214,6 +215,7 @@ pub fn create_genesis_block(config: &Config) -> Block {
}
consensus_parameters_version = ConsensusParametersVersion::MIN;
state_transition_bytecode_version = StateTransitionBytecodeVersion::MIN;
prev_root = Bytes32::zeroed();
}

let transactions_ids = vec![];
Expand All @@ -228,7 +230,7 @@ pub fn create_genesis_block(config: &Config) -> Block {
generated: Empty,
},
consensus: ConsensusHeader::<Empty> {
prev_root: Bytes32::zeroed(),
prev_root,
height,
time: fuel_core_types::tai64::Tai64::UNIX_EPOCH,
generated: Empty,
Expand Down Expand Up @@ -262,6 +264,7 @@ mod tests {
Randomize,
StateConfig,
};
use fuel_core_producer::ports::BlockProducerDatabase;
use fuel_core_services::RunnableService;
use fuel_core_storage::{
tables::{
Expand Down Expand Up @@ -291,7 +294,7 @@ mod tests {
use std::vec;

#[tokio::test]
async fn config_initializes_block_height_of_genesic_block() {
async fn config_initializes_block_height_of_genesis_block() {
let block_height = BlockHeight::from(99u32);
let service_config = Config::local_node_with_state_config(StateConfig {
last_block: Some(LastBlockConfig {
Expand Down Expand Up @@ -641,7 +644,13 @@ mod tests {

let actual_state = db.read_state_config().unwrap();
let mut expected_state = initial_state;
expected_state.last_block = Some(Default::default());
let mut last_block = LastBlockConfig::default();
last_block.block_height = db.on_chain().latest_height().unwrap().unwrap();
last_block.blocks_root = db
.on_chain()
.block_header_merkle_root(&last_block.block_height)
.unwrap();
expected_state.last_block = Some(last_block);
assert_eq!(expected_state, actual_state);
}
}
16 changes: 15 additions & 1 deletion crates/fuel-core/src/service/genesis/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,24 @@ use crate::{
use fuel_core_chain_config::{
AddTable,
ChainConfig,
LastBlockConfig,
SnapshotFragment,
SnapshotMetadata,
SnapshotWriter,
StateConfigBuilder,
TableEntry,
};
use fuel_core_poa::ports::Database as DatabaseTrait;
use fuel_core_storage::{
blueprint::BlueprintInspect,
iter::IterDirection,
kv_store::StorageColumn,
structured_storage::TableWithBlueprint,
tables::{
merkle::{
FuelBlockMerkleData,
FuelBlockMerkleMetadata,
},
Coins,
ContractsAssets,
ContractsLatestUtxo,
Expand Down Expand Up @@ -101,6 +107,8 @@ where
ContractsState,
ContractsAssets,
FuelBlocks,
FuelBlockMerkleData,
FuelBlockMerkleMetadata,
Transactions,
SealedBlockConsensus,
ProcessedTransactions
Expand Down Expand Up @@ -145,6 +153,12 @@ where
async fn finalize(self) -> anyhow::Result<SnapshotMetadata> {
let writer = self.create_writer()?;
let latest_block = self.db.on_chain().latest_block()?;
let blocks_root = self
.db
.on_chain()
.block_header_merkle_root(latest_block.header().height())?;
let latest_block =
LastBlockConfig::from_header(latest_block.header(), blocks_root);

let writer_fragment = writer.partial_close()?;
self.task_manager
Expand All @@ -154,7 +168,7 @@ where
.try_fold(writer_fragment, |fragment, next_fragment| {
fragment.merge(next_fragment)
})?
.finalize(Some(latest_block.header().into()), &self.prev_chain_config)
.finalize(Some(latest_block), &self.prev_chain_config)
}

fn create_writer(&self) -> anyhow::Result<SnapshotWriter> {
Expand Down
6 changes: 6 additions & 0 deletions crates/fuel-core/src/service/genesis/importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ use fuel_core_storage::{
kv_store::StorageColumn,
structured_storage::TableWithBlueprint,
tables::{
merkle::{
FuelBlockMerkleData,
FuelBlockMerkleMetadata,
},
Coins,
ContractsAssets,
ContractsLatestUtxo,
Expand Down Expand Up @@ -113,6 +117,8 @@ impl SnapshotImporter {
self.spawn_worker_on_chain::<ContractsState>()?;
self.spawn_worker_on_chain::<ContractsAssets>()?;
self.spawn_worker_on_chain::<ProcessedTransactions>()?;
self.spawn_worker_on_chain::<FuelBlockMerkleData>()?;
self.spawn_worker_on_chain::<FuelBlockMerkleMetadata>()?;

self.spawn_worker_off_chain::<TransactionStatuses, TransactionStatuses>()?;
self.spawn_worker_off_chain::<OwnedTransactions, OwnedTransactions>()?;
Expand Down
Loading

0 comments on commit 31d0741

Please sign in to comment.