Skip to content
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

Shared sequencer integration #1922

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open

Conversation

Dentosal
Copy link
Member

@Dentosal Dentosal commented May 30, 2024

Related #1621

As part of the feature, we created a new crate https://github.com/FuelLabs/sequencer-rs-sdk with protobuf types from the SS.

The PR doesn't have any testing currently. The fuel-core was tested with enabled SS functionality on the local node created from https://github.com/FuelLabs/fuel-rollup/blob/main/docker/docker-compose.yml, and on the SS testnet using data from https://github.com/fuel-infrastructure/networks/tree/main/seq-testnet-1.

We need to add integration tests and unit tests in the follow-up PR.

Checklist

  • Breaking changes are clearly marked as such in the PR description and changelog
  • New behavior is reflected in tests
  • The specification 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

@Dentosal Dentosal self-assigned this May 30, 2024
xgreenx added a commit that referenced this pull request Nov 23, 2024
xgreenx added a commit that referenced this pull request Nov 23, 2024
xgreenx added a commit that referenced this pull request Nov 23, 2024
xgreenx added a commit that referenced this pull request Nov 25, 2024
## Description

This PR duplicates #1922, but
on top of the `fuel-core 0.40.0`.
Since the current `master` is not ready to be released, but we want this
feature in the testnet, we will create a minor release with added
off-chain logic that posts data to the SS.

All changes are the same as in the original PR, except `reqwest` is
bumped to `0.12`, because it has a fix important for SS.

### Before requesting review
- [x] I have reviewed the code myself

---------

Co-authored-by: Mårten Blankfors <[email protected]>
@xgreenx
Copy link
Collaborator

xgreenx commented Nov 27, 2024

@Dentosal Could you apply latest changes from the #2451 and #2452 please?=)

@Dentosal Dentosal marked this pull request as ready for review December 11, 2024 02:37
@Dentosal Dentosal requested a review from xgreenx as a code owner December 11, 2024 02:37
xgreenx
xgreenx previously approved these changes Dec 31, 2024
xgreenx
xgreenx previously approved these changes Dec 31, 2024
AurelienFT
AurelienFT previously approved these changes Jan 3, 2025
Copy link
Contributor

@AurelienFT AurelienFT left a comment

Choose a reason for hiding this comment

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

I already reviewed when it was a PR for 0.40.x version. Seems similar LGTM with a little question

@@ -31,7 +31,7 @@ cargo make check --all-features --locked &&
cargo make check --locked &&
OVERRIDE_CHAIN_CONFIGS=true cargo test --test integration_tests local_node &&
cargo nextest run --workspace &&
FUEL_ALWAYS_USE_WASM=true cargo nextest run --all-features --workspace &&
cargo nextest run --all-features --workspace &&
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the rationale behind this change on this PR ?

Copy link
Member Author

Choose a reason for hiding this comment

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

A mistake. Removed in b3ea605.

Comment on lines +522 to +525
#[cfg(feature = "shared-sequencer")]
{
expected_services += 1;
}
Copy link
Contributor

@acerone85 acerone85 Jan 3, 2025

Choose a reason for hiding this comment

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

not for this PR, but maybe it's better here to have an enum that lists all the expected services, with feature-specific variants, and then use strum_enum::count to retrieve the number of expected services.

@acerone85
Copy link
Contributor

I have reviewed the whole code.
My understanding is that the shared sequencer service keeps monitoring for new ImportedBlocks from the BlockImporter and posts the corresponding blobs to the sequencer node.

From the architectural point of view I would like to understand the following (note that my questions probably spill into the shared sequencer domain):

  1. What's the high level architecture of the shared sequencer? I understand that nodes with shared sequencer integration enabled will connect and post imported blocks to a ss node, and then these will be responsible to agree that they imported the same blocks using tendermint. But I'm trying connect dots and making assumptions here. Is my understanding correct?
  2. What is validated by the consensus layer? Is it just the block content?
  3. How is the result of the consensus used? In particular, I'd expect each tendermint iterations to produce a quorum certificate: how is it used? Is it posted to L1?

acerone85
acerone85 previously approved these changes Jan 3, 2025
@Dentosal
Copy link
Member Author

Dentosal commented Jan 3, 2025

My understanding is rather imperfect here, so these answers might not be 100% correct.

  1. What's the high level architecture of the shared sequencer? I understand that nodes with shared sequencer integration enabled will connect and post imported blocks to a ss node, and then these will be responsible to agree that they imported the same blocks using tendermint. But I'm trying connect dots and making assumptions here. Is my understanding correct?

It's shared sequencer is tendermint, with a sidecar that implements Fuel-specific logic. I don't think we verify that the blocks are correct, we just post them there.

  1. What is validated by the consensus layer? Is it just the block content?

Nothing is validated. The data we send is included as-is.

  1. How is the result of the consensus used? In particular, I'd expect each tendermint iterations to produce a quorum certificate: how is it used? Is it posted to L1?

That's the plan, yes. I'm not sure if they do that already.

@Dentosal Dentosal dismissed stale reviews from acerone85, AurelienFT, and xgreenx via b3ea605 January 3, 2025 13:49
@Dentosal Dentosal requested review from AurelienFT, xgreenx, acerone85 and a team January 3, 2025 14:23
_: &StateWatcher,
_: Self::TaskParams,
) -> anyhow::Result<Self::Task> {
let shared_sequencer_client = if let Some(endpoints) = &self.config.endpoints {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason we (try to) create the client even though the self.config.enabled could be false?

};

let mut account = self.account_metadata.take().expect("Account metadata is not set");
let next_order = self.prev_order.map(|prev| prev.wrapping_add(1)).unwrap_or(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems that ensure_prev_order doesn't really ensure that we have the "prev_order", because the http_api::get_topic can still return None.

It's probably fine to start at 0 in this case, but I'm just leaving the comment for others to double-check :)

return TaskNextAction::ErrorContinue(err);
}

tracing::info!("Posted block to shared sequencer {blobs:?}");
Copy link
Contributor

Choose a reason for hiding this comment

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

How many blobs we can potentially have in the collection? Asking because we may risk clogging the log with super long messages on info level. Maybe logging the .len() would suffice? Or something like range: "blobs.first().height, blobs.last().height"?

// We don't want our transactions to be stay in the mempool for a long time,
// so we set the timeout height to be 64 blocks ahead of the latest block height.
// The 64 is an arbitrary number.
latest_height.saturating_add(64),
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we know at what pace the sequencer chain produces blocks?

Comment on lines +258 to +260
// Convert the signature to non-normalized form
let mut signature_bytes = *signature;
signature_bytes[32] &= 0x7f;
Copy link
Contributor

Choose a reason for hiding this comment

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

A nit: It could be a little bit more clear if we have the fn non_normalized() added to impl Signature.

Comment on lines +72 to +77
if let Some(index) = minimum_gas_price.find('.') {
minimum_gas_price.truncate(index);
}
let gas_price: u128 = minimum_gas_price.parse()?;
// Ceil the gas price to the next integer.
let gas_price = gas_price.saturating_add(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have a rationale for this piece of code. I was wondering:

  1. why we truncate? (and how can we be sure that dot will be used as decimal separator)?
  2. why we ceil to the next integer?

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.

5 participants