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

Improving blob propagation post-PeerDAS with Decentralized Blob Building #6268

Open
wants to merge 24 commits into
base: unstable
Choose a base branch
from

Conversation

jimmygchen
Copy link
Member

@jimmygchen jimmygchen commented Aug 16, 2024

Issue Addressed

Built on top of #5829, an optimization came up by @michaelsproul, to fetches blobs from the EL to reduce the delay to block import.

This PR goes further to publish the blobs to the network, which helps improve the resiliency of the network, by having nodes with more resources contribute to blob propagation. This experimental solution is an attempt to solve the self building proposer bandwidth issue discussed on R&D Discord and described in @dankrad's post here.

The benefits of this proposals are:

  • Reduces block import latency: nodes can retrieve blobs from EL without waiting for them from gossip, hence making blocks attestable earlier.
  • Improves blob propagation and network resiliency: blob propagation work from is spread out from 1 node to the entire network, which reduces the likelihood of missed block due to delays in propagtion.
  • Allows scaling without sacrificing decentralization: nodes with more resources will participate in blob building and propagation, allowing nodes with limited bandwidth to continue to produce block post-PeerDAS.

Proposed Changes

  • Deneb: fetch_blobs_and_publish is triggered after a node has processed a gossip / rpc block and is still missing blob components. Once the node fetches the blob from EL, it then publishes the remaining blobs that hasn't seen on gossip to the network.
  • PeerDAS: Same trigger as above, however only supernodes will publish data columns that are unseen on gossip to the network.

Next steps:

  • To maintain low bandwidth for smaller stakers (single validator BN), we could allow some optimisation on block publish behaviour for these nodes only. There are some strategies proposed by @cskiraly to bring the outbound bandwidth requirements for a 32 blobs block to the same level as Deneb (6 blobs). However this wouldn't be recommended for nodes with enough bandwidth.
  • Collect some realistic metrics for a network with 32 blobs per block.

Challenges:

  • Current KZG libraries (c-kzg-4844 and rust-eth-kzg) may struggle with constructing large number of cells and proofs at once due to the current memory allocation approach.
  • Even if we are able reduce the bandwidth usage on the CL side, the bandwidth challenge remains on the EL side, as the node still need to pull the blob transactions into its mempool, to a lesser extent though, because:
    • it's dealing with raw blobs (4096kb for 32 blobs) rather than erasure coded blobs
    • it's pulled-based (eth/68) hence doesn't incur the same gossip amplification cost (8x) on the CL.

TODO before merging

Reference:

@jimmygchen jimmygchen added work-in-progress PR is a work-in-progress das Data Availability Sampling labels Aug 16, 2024
@jimmygchen jimmygchen marked this pull request as ready for review August 16, 2024 07:47
@jimmygchen jimmygchen added ready-for-review The code is ready for review and removed work-in-progress PR is a work-in-progress labels Aug 16, 2024
@jimmygchen
Copy link
Member Author

jimmygchen commented Aug 19, 2024

Some early testing results:

  • Proposers withholding all blobs propose blocks with blobs with 100% success rate
  • No outbound bandwidth spike for the full nodes with limited upload

Bandwidth-limited fullnode (cl-01) vs supernode (cl-02):

image
(Thanks to @KatyaRyazantseva for the dashboard above☺️ )

This shows EL inbound traffic (fetch blos from peers) isn't too bad for MAX 6 blobs
The outbound traffic for EL is less relevant here because it includes sending blobs to CL.

image

Next steps:

  • Add more metrics
    • Blocks made available via EL blobs
    • Number of blobs / data columns from EL blobs published
    • EL blob fetch timing
    • Compute cells and proof time
  • Make MAX_BLOBS_PER_BLOCK configurable
  • Try 32 blobs per block
    • EL gas constant update
    • Potential update on derived configs
    • Potential batching of KZG computation to avoid overflow
  • Add --limit-blob-publish (single validator only), which allows for lower mesh peers for data columns topics and withholding certain amount of data columns

@jimmygchen
Copy link
Member Author

This was originally intended experimental but it's been pretty stable, 800 epochs on devnet and 100% participation, and I think we can merge this.
I'll address the review comments, thanks @dapplion for the review 🙏

@dapplion
Copy link
Collaborator

Add --limit-blob-publish (single validator only), which allows for lower mesh peers for data columns topics and withholding certain amount of data columns

Bring the attack to prod

@kevaundray
Copy link
Contributor

@jimmygchen Any issues with the kzg libraries?

@jimmygchen
Copy link
Member Author

Bring the attack to prod

🙈 Trying to not mention the flag I use for testing. Luckily git blame on that line shows someone else's name haha

Just realized we need the execution-apis PR is merged before merge this - although there's probably no harm getting this one merged as soon as the inclusion is confirmed, as the fetch_blobs function handles this gracefully.

beacon_node/beacon_chain/src/fetch_blobs.rs Outdated Show resolved Hide resolved
beacon_node/beacon_chain/src/fetch_blobs.rs Outdated Show resolved Hide resolved
beacon_node/beacon_chain/src/fetch_blobs.rs Outdated Show resolved Hide resolved
beacon_node/beacon_chain/src/fetch_blobs.rs Show resolved Hide resolved
beacon_node/beacon_chain/src/beacon_chain.rs Outdated Show resolved Hide resolved
beacon_node/beacon_chain/src/fetch_blobs.rs Outdated Show resolved Hide resolved
beacon_node/beacon_chain/src/fetch_blobs.rs Outdated Show resolved Hide resolved
beacon_node/network/src/network_beacon_processor/mod.rs Outdated Show resolved Hide resolved
consensus/types/src/beacon_block_body.rs Outdated Show resolved Hide resolved
@jimmygchen
Copy link
Member Author

@jimmygchen Any issues with the kzg libraries?

Nope all good so far! I was just flagging the potential challenges that I could imagine when we increase blob count, but I haven't actually run into any issues yet. Will keep you updated, thanks ☺️

@jimmygchen jimmygchen added spec_change A change related to the Eth2 spec optimization Something to make Lighthouse run more efficiently. labels Aug 20, 2024
@jimmygchen jimmygchen mentioned this pull request Aug 21, 2024
52 tasks
@jimmygchen jimmygchen added waiting-on-author The reviewer has suggested changes and awaits thier implementation. and removed ready-for-review The code is ready for review labels Aug 22, 2024
@mergify mergify bot deleted the branch sigp:unstable August 27, 2024 04:10
@mergify mergify bot closed this Aug 27, 2024
@michaelsproul michaelsproul reopened this Aug 27, 2024
@michaelsproul michaelsproul changed the base branch from das to unstable August 27, 2024 04:21
@jimmygchen
Copy link
Member Author

engine_getBlobsV1 now implemented in

@jimmygchen jimmygchen added waiting-on-author The reviewer has suggested changes and awaits thier implementation. and removed ready-for-review The code is ready for review labels Sep 19, 2024
@jimmygchen
Copy link
Member Author

jimmygchen commented Oct 1, 2024

I think we should review blob publishing before merging this to avoid adding excessive bandwidth usage for Deneb.

@michaelsproul michaelsproul added the v6.0.0 New major release for hierarchical state diffs label Oct 7, 2024
@jimmygchen
Copy link
Member Author

Be great to have #6403 merged first, as there will be some more conflicts that needs to be resolved, and a bit easier in this order. We also need to prioritise block publishing, could do it in this PR.

# Conflicts:
#	beacon_node/beacon_chain/src/data_availability_checker.rs
#	beacon_node/beacon_chain/src/data_availability_checker/overflow_lru_cache.rs
#	beacon_node/execution_layer/src/engine_api.rs
#	beacon_node/execution_layer/src/engine_api/json_structures.rs
#	beacon_node/network/src/network_beacon_processor/gossip_methods.rs
#	beacon_node/network/src/network_beacon_processor/mod.rs
#	beacon_node/network/src/network_beacon_processor/sync_methods.rs
@jimmygchen
Copy link
Member Author

jimmygchen commented Oct 17, 2024

Remaining TODOs

@jimmygchen jimmygchen added ready-for-review The code is ready for review and removed waiting-on-author The reviewer has suggested changes and awaits thier implementation. labels Oct 18, 2024
.await
}

async fn check_engine_blob_availability_and_import(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should inline this function into process_engine_blobs?

// Store the block and its state, and execute the confirmation batch for the intermediate
// states, which will delete their temporary flags.
// If the write fails, revert fork choice to the version from disk, else we can
// end up with blocks in fork choice that are missing from disk.
// See https://github.com/sigp/lighthouse/issues/2028
let (_, signed_block, blobs, data_columns) = signed_block.deconstruct();
// TODO(das) we currently store all subnet sampled columns. Tracking issue to exclude non custody columns: https://github.com/sigp/lighthouse/issues/6465
Copy link
Collaborator

Choose a reason for hiding this comment

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

Exceeds max fmt width

Comment on lines +253 to +254
/// This DOES NOT perform KZG verification because the KZG proofs should have been constructed
/// immediately prior to calling this function so they are assumed to be valid.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not change this function and process_engine_blobs to take KzgVerifiedBlobList and make it correct by construction?

);
let all_blobs_received = block_kzg_commitments_count_opt
.map_or(false, |num_expected_blobs| {
num_expected_blobs == num_received_blobs
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it worth switching to >= in case there's some future bug?

Suggested change
num_expected_blobs == num_received_blobs
num_received_blobs >= num_expected_blobs

let Some(verified_blobs) = verified_blobs
.into_iter()
.map(|b| b.map(|b| b.to_blob()))
.take(num_blobs_expected)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is it necessary to take here? Do we consider the case where we have too many blobs?

Comment on lines +243 to +246
let is_supernode = chain_cloned
.data_availability_checker
.get_sampling_column_count()
== chain_cloned.spec.number_of_columns;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could add a function to DataAvailabilityChecker to not spread the notion of supernode-ness in multiple places

fn is_supernode(&self) -> bool

log,
"Publishing data columns from EL";
"count" => publishable.len()
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here we can compute the efficiency of this delay publish mechanism: track which columns were originally scheduled for publishing and became seen in this for loop. We can track that as a counter of "already_seen_before_publish" or something related. And maybe print a summary after the for loop summarizing how many we published in total, and how many we skipped publishing or how many we intended to publish at the beginning.

Also, do we log somewhere which specific column index we publish? Otherwise, it might be helpful to log in this line a vec of indices of which columns we are publishing.

*blob_mut = Some(Arc::new(blob));
} else {
return Err(FetchEngineBlobError::InternalError(
"Unreachable: Blobs from EL - out of bounds".to_string(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is reachable, the EL can send malformed blobs with a random index

tokio::time::sleep(supernode_data_column_publication_batch_interval).await;
}
},
"handle_data_columns_publish",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not a blocker to merging, but since reviews are slow maybe there's time to de-dup this bit

Comment on lines +89 to +104
.arg(
Arg::new("supernode-data-column-publication-batches")
.long("supernode-data-column-publication-batches")
.action(ArgAction::Set)
.help_heading(FLAG_HEADER)
.help("Number of batches that supernodes split data columns into during publishing by a non-proposer. For PeerDAS only.")
.display_order(0)
)
.arg(
Arg::new("supernode-data-column-publication-batch-interval")
.long("supernode-data-column-publication-batch-interval")
.action(ArgAction::Set)
.help_heading(FLAG_HEADER)
.help("The delay in milliseconds applied by supernodes between the sending of each data column batch. For PeerDAS only.")
.display_order(0)
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we hide these?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
das Data Availability Sampling optimization Something to make Lighthouse run more efficiently. ready-for-review The code is ready for review spec_change A change related to the Eth2 spec v6.0.0 New major release for hierarchical state diffs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants