Skip to content

Commit

Permalink
Bug/fix gas price metadata sync (#2056)
Browse files Browse the repository at this point in the history
- [x] Have gas price metadata start from latest block if there is no
record
- [x] Fix bug in view lookups that creates a new view for every
historical lookup :P


## Checklist
- [x] Breaking changes are clearly marked as such in the PR description
and changelog
- [x] New behavior is reflected in tests
- [x] [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
- [x] I have created follow-up issues caused by this PR and linked them
here
#2057

### 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?
  • Loading branch information
MitchTurner committed Aug 6, 2024
1 parent 982270f commit 38cbc38
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 25 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 23 additions & 24 deletions crates/fuel-core/src/service/sub_services/algorithm_updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use fuel_core_storage::{
FuelBlocks,
Transactions,
},
transactional::HistoricalView,
transactional::AtomicView,
StorageAsRef,
};
use fuel_core_types::{
Expand Down Expand Up @@ -142,38 +142,45 @@ pub fn get_synced_gas_price_updater(
on_chain_db: Database<OnChain, RegularStage<OnChain>>,
block_stream: BoxStream<SharedImportResult>,
) -> anyhow::Result<Updater> {
let mut metadata_height: u32 = gas_price_db
.latest_height()?
.unwrap_or(genesis_block_height)
.into();
let mut first_run = false;
let latest_block_height: u32 = on_chain_db
.latest_height()?
.unwrap_or(genesis_block_height)
.into();

let genesis_metadata = UpdaterMetadata::V0(V0Metadata {
let maybe_metadata_height = gas_price_db.latest_height()?;
let mut metadata_height = if let Some(metadata_height) = maybe_metadata_height {
metadata_height.into()
} else {
first_run = true;
latest_block_height
};

let first_metadata = UpdaterMetadata::V0(V0Metadata {
new_exec_price: config.starting_gas_price,
min_exec_gas_price: config.min_gas_price,
exec_gas_price_change_percent: config.gas_price_change_percent,
l2_block_height: genesis_block_height.into(),
l2_block_height: latest_block_height,
l2_block_fullness_threshold_percent: config.gas_price_threshold_percent,
});

if metadata_height > latest_block_height {
revert_gas_price_db_to_height(&mut gas_price_db, latest_block_height.into())?;
metadata_height = gas_price_db
.latest_height()?
.unwrap_or(genesis_block_height)
.ok_or(anyhow::anyhow!(
"Metadata DB height should match the latest block height"
))?
.into();
}

let mut metadata_storage = StructuredStorage::new(gas_price_db);
let l2_block_source =
FuelL2BlockSource::new(genesis_block_height, settings.clone(), block_stream);

if BlockHeight::from(latest_block_height) == genesis_block_height {
if BlockHeight::from(latest_block_height) == genesis_block_height || first_run {
let updater = FuelGasPriceUpdater::new(
genesis_metadata.into(),
first_metadata.into(),
l2_block_source,
metadata_storage,
);
Expand All @@ -186,8 +193,6 @@ pub fn get_synced_gas_price_updater(
on_chain_db,
metadata_height,
latest_block_height,
genesis_metadata,
genesis_block_height.into(),
)?;
}

Expand All @@ -208,18 +213,12 @@ fn sync_metadata_storage_with_on_chain_storage(
on_chain_db: Database<OnChain, RegularStage<OnChain>>,
metadata_height: u32,
latest_block_height: u32,
genesis_metadata: UpdaterMetadata,
genesis_block_height: u32,
) -> anyhow::Result<()> {
let metadata = if metadata_height == genesis_block_height {
genesis_metadata
} else {
metadata_storage
.get_metadata(&metadata_height.into())?
.ok_or(anyhow::anyhow!(
"Expected metadata to exist for height: {metadata_height}"
))?
};
let metadata = metadata_storage
.get_metadata(&metadata_height.into())?
.ok_or(anyhow::anyhow!(
"Expected metadata to exist for height: {metadata_height}"
))?;
let mut inner: AlgorithmUpdater = metadata.into();
match &mut inner {
AlgorithmUpdater::V0(ref mut updater) => {
Expand Down Expand Up @@ -247,8 +246,8 @@ fn sync_v0_metadata(
>,
) -> anyhow::Result<()> {
let first = metadata_height.saturating_add(1);
let view = on_chain_db.latest_view()?;
for height in first..=latest_block_height {
let view = on_chain_db.view_at(&height.into())?;
let block = view
.storage::<FuelBlocks>()
.get(&height.into())?
Expand Down
1 change: 1 addition & 0 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fuel-core-benches = { path = "../benches" }
fuel-core-bin = { path = "../bin/fuel-core", features = ["parquet", "p2p"] }
fuel-core-client = { path = "../crates/client", features = ["test-helpers"] }
fuel-core-executor = { workspace = true }
fuel-core-gas-price-service = { path = "../crates/services/gas_price_service" }
fuel-core-p2p = { path = "../crates/services/p2p", features = [
"test-helpers",
], optional = true }
Expand Down
75 changes: 74 additions & 1 deletion tests/tests/recovery.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#![allow(non_snake_case)]

use fuel_core_gas_price_service::fuel_gas_price_updater::{
fuel_core_storage_adapter::storage::GasPriceMetadata,
};
use fuel_core_storage::{
transactional::AtomicView,
StorageAsRef,
};
use fuel_core_types::fuel_types::BlockHeight;
use proptest::{
prelude::{
Expand Down Expand Up @@ -64,7 +71,7 @@ async fn off_chain_worker_can_recover_on_start_up_when_is_behind() -> anyhow::Re
}

prop_compose! {
fn height_and_lower_height()(height in 1..100u32)(height in Just(height), lower_height in 0..height) -> (u32, u32) {
fn height_and_lower_height()(height in 2..100u32)(height in Just(height), lower_height in 1..height) -> (u32, u32) {
(height, lower_height)
}
}
Expand Down Expand Up @@ -203,6 +210,72 @@ proptest! {
}
}

#[tokio::test(flavor = "multi_thread")]
async fn gas_price_updater__if_no_metadata_history_start_from_current_block(
) -> anyhow::Result<()> {
let driver = FuelCoreDriver::spawn(&[
"--debug",
"--poa-instant",
"true",
"--state-rewind-duration",
"7d",
])
.await?;

// Given
let height = 100;
let lower_height = 0;
driver.client.produce_blocks(height, None).await?;
let database = &driver.node.shared.database;
assert_eq!(
database.on_chain().latest_height()?,
Some(BlockHeight::new(height))
);

let diff = height - lower_height;
for _ in 0..diff {
let _ = database.gas_price().rollback_last_block();
}
assert!(database.on_chain().latest_height()? > database.gas_price().latest_height()?);
let temp_dir = driver.kill().await;

// When
let recovered_driver = FuelCoreDriver::spawn_with_directory(
temp_dir,
&[
"--debug",
"--poa-instant",
"true",
"--state-rewind-duration",
"7d",
],
)
.await?;

// Then
// advance the block height to the next block to add the metadata to db
recovered_driver.client.produce_blocks(1, None).await?;
let recovered_database = &recovered_driver.node.shared.database;
let next_height = height + 1;
assert_eq!(
recovered_database.on_chain().latest_height()?,
Some(BlockHeight::new(next_height))
);
assert_eq!(
recovered_database.gas_price().latest_height()?,
Some(BlockHeight::new(next_height))
);
let view = recovered_database.gas_price().latest_view().unwrap();
let previous_metadata = view
.storage::<GasPriceMetadata>()
.get(&height.into())
.unwrap()
.clone();
assert!(previous_metadata.is_none());

Ok(())
}

fn multithreaded_runtime() -> tokio::runtime::Runtime {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
Expand Down

0 comments on commit 38cbc38

Please sign in to comment.