Skip to content

feat: integrate derivation pipeline #49

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

Merged
merged 17 commits into from
Apr 9, 2025

Conversation

greged93
Copy link
Collaborator

@greged93 greged93 commented Apr 3, 2025

Integrates the derivation pipeline in the RNM. Adds a DerivationPipeline stateful structure, which implements the Future trait and yields a Stream<Item = Result<ScrollPayloadAttributes, DerivationPipelineError>.

@greged93 greged93 marked this pull request as draft April 3, 2025 20:08
@greged93 greged93 marked this pull request as ready for review April 7, 2025 09:15
@greged93 greged93 requested a review from frisitano April 7, 2025 09:15
Comment on lines 135 to 138
// if the futures can still grow, handle the next batch.
if this.pipeline_futures.len() < MAX_CONCURRENT_DERIVATION_PIPELINE_FUTS {
this.handle_next_batch(|queue, fut| queue.push_back(fut));
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this limitation mechanism could be removed: even we if have up to 1000 pending futures, which all fetch blobs, this would still represent only ~ 128 MB of data.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future we should replace the constant with a value from config so we can modify it at runtime.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done #50

Comment on lines 147 to 152
Err((index, err)) => {
tracing::error!(target: "scroll::node::derivation_pipeline", ?index, ?err, "failed to derive payload attributes for batch");
// retry polling the same batch index.
this.batch_index_queue.push_front(index);
this.handle_next_batch(|queue, fut| queue.push_front(fut));
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented a sort of retry mechanism here, but maybe this is more suited to be moved to the various providers?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as is for now and then replace with provider rety in the future. Lets open an issue to track it for milestone 5.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done #50

@greged93 greged93 force-pushed the feat/integrate-derivation-pipeline branch from 2719b60 to e281745 Compare April 8, 2025 07:18
@greged93 greged93 force-pushed the feat/integrate-derivation-pipeline branch from e281745 to 5666c83 Compare April 8, 2025 07:57
Copy link
Collaborator

@frisitano frisitano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, left a few small nits inline. Let me know what you think. CI checks failing.

Comment on lines 135 to 138
// if the futures can still grow, handle the next batch.
if this.pipeline_futures.len() < MAX_CONCURRENT_DERIVATION_PIPELINE_FUTS {
this.handle_next_batch(|queue, fut| queue.push_back(fut));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future we should replace the constant with a value from config so we can modify it at runtime.

Comment on lines 147 to 152
Err((index, err)) => {
tracing::error!(target: "scroll::node::derivation_pipeline", ?index, ?err, "failed to derive payload attributes for batch");
// retry polling the same batch index.
this.batch_index_queue.push_front(index);
this.handle_next_batch(|queue, fut| queue.push_front(fut));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as is for now and then replace with provider rety in the future. Lets open an issue to track it for milestone 5.

Comment on lines 87 to 110
/// Handles the next batch index in the batch index queue, pushing the future in the pipeline
/// futures.
fn handle_next_batch<
F: FnMut(&mut FuturesOrdered<DerivationPipelineFuture>, DerivationPipelineFuture),
>(
&mut self,
mut queue_fut: F,
) {
let database = self.database.clone();
let provider = self.l1_provider.clone();

if let Some(index) = self.batch_index_queue.pop_front() {
let fut = Box::pin(async move {
let batch = database
.get_batch_by_index(index)
.await
.map_err(|err| (index, err.into()))?
.ok_or((index, DerivationPipelineError::UnknownBatch(index)))?;

derive(batch, provider).await.map_err(|err| (index, err))
});
queue_fut(&mut self.pipeline_futures, fut);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think that this function should return a future instead of executing queue_fut. When the caller receives the future they can add it to the back/front of the queue as required. I think queue_fut argument makes the code harder to parse. However, not strongly opinionated if you would prefer to keep as is.

Comment on lines 120 to 131
pub fn new(
network: NetworkManager,
engine: EngineDriver<EC, P>,
l1_provider: L1P,
l1_notification_rx: Option<Receiver<Arc<L1Notification>>>,
indexer: Indexer,
forkchoice_state: ForkchoiceState,
consensus: C,
new_block_rx: Option<UnboundedReceiver<NewBlockWithPeer>>,
) -> Self {
let database = indexer.database();
let derivation_pipeline = DerivationPipeline::new(l1_provider, database);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should remove the indexer as argument and provide database: Database and we can then instantiate the indexer and pipeline here. What do you think?

Comment on lines 336 to 347
// if the log is missing the block timestamp, we need to fetch it.
// the block timestamp is necessary in order to derive the beacon
// slot and query the blobs.
let block_timestamp = if log_timestamp.is_none() {
self.execution_provider
.get_block(block_number.into())
.await?
.map(|b| b.header.timestamp)
.ok_or(FilterLogError::MissingBlockTimestamp)?
} else {
log_timestamp.expect("checked for Some(...)")
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@frisitano wanted to have your opinion on this as well

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. I have a slight preference to use if let (so we avoid the expect) but am not strongly opinionated.

@greged93 greged93 force-pushed the feat/integrate-derivation-pipeline branch from af0364a to 38ea6cf Compare April 9, 2025 07:38
@greged93 greged93 merged commit bfda5c6 into main Apr 9, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants