Skip to content

Conversation

@greged93
Copy link
Contributor

@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
Contributor 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
Contributor 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
Contributor 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
Contributor 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
Contributor 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.

3 participants