-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Add unrecorded blocks abstraction to gas price algo #2468
base: master
Are you sure you want to change the base?
Conversation
…data_tests.rs Co-authored-by: Rafał Chabowski <[email protected]>
…-be-received-out-of-order
…to feature/init-task-for-v1-gas-price-service
fn set_metadata(&mut self, metadata: &UpdaterMetadata) -> GasPriceResult<()> { | ||
let block_height = metadata.l2_block_height(); | ||
let mut tx = self.write_transaction(); | ||
tx.storage_as_mut::<GasPriceMetadata>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we creating a tx for 1 insert ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like that's what we do most places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we constrained with KeyValueMutate
we could use put
directly, but that's not what we have access to.
|
||
impl Mappable for SequenceNumberTable { | ||
type Key = Self::OwnedKey; | ||
type OwnedKey = u32; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use BlockHeight type here to be more explicit ?
)?; | ||
|
||
self.set_metadata().await?; | ||
let metadata = self.algorithm_updater.clone().into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AlgorithmUpdater have algorithm()
method to get an algorithm. I find it strange to not have a metadata()
but a into()
to get metadata
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Metadata doesn't exist as a concept from the algorithm updater's perspective. We have the metadata at the service level to be able to reproduce the updater in the case the service stops.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far looks good, but I didn't finish the review yet, sorry. I'll do another pass ASAP. Currently leaving just a few minor comments.
crates/services/gas_price_service/src/v1/da_source_service/dummy_costs.rs
Outdated
Show resolved
Hide resolved
@@ -34,4 +34,8 @@ impl DaBlockCostsSource for DummyDaBlockCosts { | |||
} | |||
} | |||
} | |||
|
|||
async fn set_last_value(&mut self, sequence_number: u32) -> DaBlockCostsResult<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can DummyDaBlockCosts
be behind the test
flag?
|
||
async fn handle_normal_block( | ||
&mut self, | ||
async fn handle_normal_block<'a>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does "normal" mean in this context? Maybe "non_genesis" would be more clear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As opposed to genesis block. I know it's not a great name, but it's true that normally it will be this block. Haha. I'd be open to other names. "non-genesis" seems strange.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just "handle_block()"?
crates/services/gas_price_service/src/v1/da_source_service/block_committer_costs.rs
Outdated
Show resolved
Hide resolved
crates/services/gas_price_service/src/common/fuel_core_storage_adapter.rs
Outdated
Show resolved
Hide resolved
…add-unrecorded-blocks-trait
…add-unrecorded-blocks-trait
…add-unrecorded-blocks-trait
Generic comment, probably not related to this PR. It seems like some functions do not need to be |
#2483) Suggestions for the #2468 PR. --------- Co-authored-by: Mitchell Turner <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost done=) Some questions and suggestions
if let Some(sequence_number) = self | ||
.gas_price_db | ||
.get_sequence_number(&metadata_height.into())? | ||
{ | ||
self.da_source.set_last_value(sequence_number).await?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand how this part should work. You only set the sequencer number when you receive the bundle from the DA.
Let's say you received the bundle with sequencer number 10
at L2 block height X. After that, you processed the L2 block at height X + 1. After that, the node was restarted.
During start up the metadata_height
will be X + 1
, but the get_sequence_number
will return None
in this case. So you will not continue from the sequencer number 10
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. I see. So we need to set the most recent value again if it hasn't changed.
Or look for the most recent value... I think setting it every time would be better performance.
pub mod dummy_costs; | ||
pub mod service; | ||
|
||
#[derive(Debug, Default, Clone, Eq, Hash, PartialEq)] | ||
pub struct DaBlockCosts { | ||
pub sequence_number: u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better if it was bundle_id
or if we somehow connected it to the block committer(comment can help)=)
tx.set_metadata(&metadata).map_err(|err| anyhow!(err))?; | ||
AtomicStorage::commit_transaction(tx)?; | ||
let new_algo = self.algorithm_updater.algorithm(); | ||
// self.update(new_algo).await; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// self.update(new_algo).await; |
let capacity = Self::validate_block_gas_capacity(block_gas_capacity)?; | ||
let mut storage_tx = self.storage_tx_provider.begin_transaction()?; | ||
|
||
for da_block_costs in self.da_block_costs_buffer.drain(..) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of an error, you will lose da_block_costs_buffer
data. Maybe it is better just to iterate here and clear it later after you committed changes to the database.
Linked Issues/PRs
Closes #2454
Description
This PR:
TransactionableStorage
trait to gas price service to allow abstraction for atomic commits to storage (once per L2 blockGet
andSet
traits for service to specify which need a transaction to executeGetSequenceNumber
andSetSequence
number concept for tracking the DA sequence number the DA service should start on at startup (I can't remember why this got included in this PR, but it felt logical at the time...)We only need a key-value lookup for the unrecorded blocks. Instead of storing all the data in the metadata, we just moved it to its own abstraction that can be accessed directly from the algorithm. This will also help with historical view, since historical view doesn't have a way to iterate over all values for that height, just do KV lookups. We were iterating before this change.
Also added the
unrecorded_block_bytes
field to metadata so we can still track that in the case of historical view.This exposed a problem with the design, which is that we need changes to the algorithm to be atomic per l2 block, which is how our Fuel Storage is designed. This led us to introducing a
TransactionableStorage
trait for the service, which can be handed to the algorithm updater before being "commit"ed. The same applies to theMetadataStorage
, so the service was redesigned slightly to accomodate this change.Checklist
Before requesting review