Skip to content

Commit

Permalink
Add syncronization for Gas Price Database and On Chain Database on st…
Browse files Browse the repository at this point in the history
…artup (#2041)

Closes #2030

In the unlikely situation that the metadata db is behind the on chain
database, we should apply the values from each block to the algorithm
updater to produce reasonable values.

For now, we should be able to use the updater deterministically, but
this might become more difficult as we include the DA values in the
updater.

We also define the behavior for when the gas price db is beyond the
on-chain db. For now, we are assuming that the blocks produced with the
gas prices in the db were either reverted or not properly committed to
the on_chain db, and we just revert the gas price db to the height of
the on chain db. i.e. **the on chain db is the source of truth.**

## 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?
  • Loading branch information
MitchTurner authored Jul 26, 2024
1 parent 25f269e commit b7e89e9
Show file tree
Hide file tree
Showing 19 changed files with 558 additions and 82 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- "gas-price-threshold-percent" - the threshold percent for determining if the gas price will be increase or decreased
And the following CLI flags are serving a new purpose
- "min-gas-price" - the minimum gas price that the gas price algorithm will return
- [2041](https://github.com/FuelLabs/fuel-core/pull/2041): Add code for startup of the gas price algorithm updater so
the gas price db on startup is always in sync with the on chain db

## [Version 0.31.0]

### Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/fuel-core/src/graphql_api/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ pub trait P2pPort: Send + Sync {
#[async_trait::async_trait]
pub trait GasPriceEstimate: Send + Sync {
/// The worst case scenario for gas price at a given horizon
async fn worst_case_gas_price(&self, height: BlockHeight) -> u64;
async fn worst_case_gas_price(&self, height: BlockHeight) -> Option<u64>;
}

/// Trait for getting VM memory.
Expand Down
5 changes: 4 additions & 1 deletion crates/fuel-core/src/schema/gas_price.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ impl EstimateGasPriceQuery {
let gas_price_provider = ctx.data_unchecked::<GasPriceProvider>();
let gas_price = gas_price_provider
.worst_case_gas_price(target_block.into())
.await;
.await
.ok_or(async_graphql::Error::new(format!(
"Failed to estimate gas price for block, algorithm not yet set: {target_block:?}"
)))?;

Ok(EstimateGasPrice {
gas_price: gas_price.into(),
Expand Down
19 changes: 14 additions & 5 deletions crates/fuel-core/src/service/adapters/fuel_gas_price_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use fuel_core_producer::block_producer::gas_price::GasPriceProvider as ProducerG
use fuel_core_txpool::ports::GasPriceProvider as TxPoolGasPriceProvider;
use fuel_core_types::{
fuel_types::BlockHeight,
services::txpool::Result as TxPoolResult,
services::txpool::{
Error as TxPoolError,
Result as TxPoolResult,
},
};

pub type Result<T, E = Error> = std::result::Result<T, E>;
Expand Down Expand Up @@ -53,7 +56,7 @@ impl<A> FuelGasPriceProvider<A>
where
A: GasPriceAlgorithm + Send + Sync,
{
async fn next_gas_price(&self) -> u64 {
async fn next_gas_price(&self) -> Option<u64> {
self.algorithm.next_gas_price().await
}
}
Expand All @@ -64,7 +67,9 @@ where
A: GasPriceAlgorithm + Send + Sync,
{
async fn next_gas_price(&self) -> anyhow::Result<u64> {
Ok(self.next_gas_price().await)
self.next_gas_price()
.await
.ok_or(anyhow::anyhow!("No gas price available"))
}
}

Expand All @@ -74,7 +79,11 @@ where
A: GasPriceAlgorithm + Send + Sync,
{
async fn next_gas_price(&self) -> TxPoolResult<u64> {
Ok(self.next_gas_price().await)
self.next_gas_price()
.await
.ok_or(TxPoolError::GasPriceNotFound(
"Gas price not set yet".to_string(),
))
}
}

Expand All @@ -83,7 +92,7 @@ impl<A> GraphqlGasPriceEstimate for FuelGasPriceProvider<A>
where
A: GasPriceAlgorithm + Send + Sync,
{
async fn worst_case_gas_price(&self, height: BlockHeight) -> u64 {
async fn worst_case_gas_price(&self, height: BlockHeight) -> Option<u64> {
self.algorithm.worst_case_gas_price(height).await
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn build_provider<A>(algorithm: A) -> FuelGasPriceProvider<A>
where
A: Send + Sync,
{
let algorithm = SharedGasPriceAlgo::new(algorithm);
let algorithm = SharedGasPriceAlgo::new_with_algorithm(algorithm);
FuelGasPriceProvider::new(algorithm)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ async fn estimate_gas_price__happy_path() {

// when
let expected_price = algo.worst_case_gas_price(next_height);
let actual_price = gas_price_provider.worst_case_gas_price(next_height).await;
let actual_price = gas_price_provider
.worst_case_gas_price(next_height)
.await
.unwrap();

// then
assert_eq!(expected_price, actual_price);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async fn gas_price__if_requested_block_height_is_latest_return_gas_price() {

// when
let expected_price = algo.next_gas_price();
let actual_price = gas_price_provider.next_gas_price().await;
let actual_price = gas_price_provider.next_gas_price().await.unwrap();

// then
assert_eq!(expected_price, actual_price);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async fn gas_price__if_requested_block_height_is_latest_return_gas_price() {

// when
let expected_price = algo.next_gas_price();
let actual_price = gas_price_provider.next_gas_price().await;
let actual_price = gas_price_provider.next_gas_price().await.unwrap();

// then
assert_eq!(expected_price, actual_price);
Expand Down
4 changes: 2 additions & 2 deletions crates/fuel-core/src/service/adapters/graphql_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ impl worker::TxPool for TxPoolAdapter {

#[async_trait::async_trait]
impl GasPriceEstimate for StaticGasPrice {
async fn worst_case_gas_price(&self, _height: BlockHeight) -> u64 {
self.gas_price
async fn worst_case_gas_price(&self, _height: BlockHeight) -> Option<u64> {
Some(self.gas_price)
}
}

Expand Down
37 changes: 21 additions & 16 deletions crates/fuel-core/src/service/sub_services.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(clippy::let_unit_value)]

use super::{
adapters::P2PAdapter,
genesis::create_genesis_block,
Expand Down Expand Up @@ -32,23 +33,31 @@ use crate::{
SubServices,
},
};
#[allow(unused_imports)]
use fuel_core_gas_price_service::fuel_gas_price_updater::{
fuel_core_storage_adapter::FuelL2BlockSource,
Algorithm,
AlgorithmV0,
FuelGasPriceUpdater,
UpdaterMetadata,
V0Metadata,
};
use fuel_core_poa::Trigger;
use fuel_core_services::{
RunnableService,
ServiceRunner,
};
use fuel_core_storage::{
structured_storage::StructuredStorage,
self,
transactional::AtomicView,
};
#[cfg(feature = "relayer")]
use fuel_core_types::blockchain::primitives::DaBlockHeight;
use std::sync::Arc;
use tokio::sync::Mutex;

mod algorithm_updater;

pub type PoAService =
fuel_core_poa::Service<TxPoolAdapter, BlockProducerAdapter, BlockImporterAdapter>;
#[cfg(feature = "p2p")]
Expand Down Expand Up @@ -176,24 +185,20 @@ pub fn init_sub_services(
#[cfg(not(feature = "p2p"))]
let p2p_adapter = P2PAdapter::new();

let updater_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: last_height.into(),
l2_block_fullness_threshold_percent: config.gas_price_threshold_percent,
});
let genesis_block_height = *genesis_block.header().height();
let settings = consensus_parameters_provider.clone();
let block_stream = importer_adapter.events_shared_result();
let l2_block_source =
FuelL2BlockSource::new(genesis_block_height, settings, block_stream);
let metadata_storage = StructuredStorage::new(database.gas_price().clone());
let update_algo =
FuelGasPriceUpdater::init(updater_metadata, l2_block_source, metadata_storage)?;
let gas_price_service =
fuel_core_gas_price_service::new_service(last_height, update_algo)?;
let next_algo = gas_price_service.shared.clone();

let gas_price_init = algorithm_updater::InitializeTask::new(
config.clone(),
genesis_block_height,
settings,
block_stream,
database.gas_price().clone(),
database.on_chain().clone(),
)?;
let next_algo = gas_price_init.shared_data();
let gas_price_service = ServiceRunner::new(gas_price_init);

let gas_price_provider = FuelGasPriceProvider::new(next_algo);
let txpool = fuel_core_txpool::new_service(
Expand Down
Loading

0 comments on commit b7e89e9

Please sign in to comment.