Skip to content

Conversation

@mehdi-aouadi
Copy link
Contributor

@mehdi-aouadi mehdi-aouadi commented Dec 2, 2025

PR Description

Add Gloas execution_payload_bid gossip rules

Fixed Issue(s)

#10175

Documentation

  • I thought about documentation and added the doc-change-required label to this PR if updates are required.

Changelog

  • I thought about adding a changelog entry, and added one if I deemed necessary.

Note

Adds Gloas execution_payload_bid gossip validation with helper utilities and integrates it into the bid manager and node, plus constants, test utilities, and updated tests/fixtures.

  • Gloas Bid Gossip Validation:
    • Add ExecutionPayloadBidGossipValidator with checks (slot window, parent hash/root known, builder validity/credentials/balance, non-zero execution_payment reject, signature, highest-bid tracking) using LRU caches (SEEN_EXECUTION_PAYLOAD_BID_SET_SIZE, HIGHEST_BID_SET_SIZE).
    • Hook validator into DefaultExecutionPayloadBidManager.validateAndAddBid.
  • Node Integration:
    • Instantiate and wire bid validator in BeaconChainController.initExecutionPayloadBidManager().
  • Helpers & Config:
    • Extend GossipValidationHelper (current/next slot, builder index/credentials/balance, block-hash known, signature helpers).
    • Expose MiscHelpersGloas.hasBuilderWithdrawalCredential.
    • Add constants: SEEN_EXECUTION_PAYLOAD_BID_SET_SIZE, HIGHEST_BID_SET_SIZE in Constants.
  • Test Utilities:
    • Enhance DataStructureUtil to generate ExecutionPayloadBid/SignedExecutionPayloadBid with explicit fields/variants.
  • Tests:
    • New tests for bid gossip validation and helper behaviors; update bid manager test and signer expected signature.
  • Fixtures:
    • Update Gloas block JSONs with new signed_execution_payload_bid values to match changes.

Written by Cursor Bugbot for commit 100dec8. This will update automatically on new commits. Configure here.

@mehdi-aouadi mehdi-aouadi self-assigned this Dec 2, 2025
@mehdi-aouadi mehdi-aouadi force-pushed the 10175-execution-payload-bid-gloas-gossip branch from 44d6922 to c590df1 Compare December 3, 2025 14:31
@mehdi-aouadi mehdi-aouadi force-pushed the 10175-execution-payload-bid-gloas-gossip branch from 2d10e2d to f006907 Compare December 4, 2025 10:10
@mehdi-aouadi mehdi-aouadi marked this pull request as draft December 4, 2025 17:31
@mehdi-aouadi mehdi-aouadi marked this pull request as ready for review December 4, 2025 17:48
public boolean isValidBuilderIndex(
final UInt64 builderIndex, final BeaconState state, final UInt64 slot) {
if (builderIndex.isGreaterThanOrEqualTo(state.getValidators().size())
|| builderIndex.longValue() < 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

intValue, as we use it as int right after that?

final int index = builderIndex.intValue();
final Validator builder = state.getValidators().get(index);
final boolean isActiveBuilder =
spec.getActiveValidatorIndices(state, spec.computeEpochAtSlot(slot)).contains(index);
Copy link
Contributor

Choose a reason for hiding this comment

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

Look heavy for this, we already have Validator structure for this specific state. Can we use predicates.isActiveValidator for the check?

}

public boolean isBlockHashKnown(final Bytes32 blockHash, final Bytes32 blockRoot) {
// TODO-GLOAS check this logic. We might need to check the block hash existence in the store
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we have the same in Store, we use both ForkChoiceStrategy and Store for such checks in validation helpers like it's interchangeable.
Spec is literally saying for this check: bid.parent_block_hash is the block hash of a known execution payload in fork choice., so you could remove TODO

public static final int VALID_PAYLOAD_ATTESTATION_SET_SIZE = 512 * 2;
// Target holding two slots worth of aggregators (16 aggregators, 64 committees and 2 slots)
public static final int VALID_AGGREGATE_SET_SIZE = 16 * 64 * 2;
// Target 2 different attestation data (aggregators normally agree) for two slots
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment is from VALID_ATTESTATION_DATA_SET_SIZE probably, you've inserted in the middle

final SigningRootUtil signingRootUtil;

private final Set<BuilderIndexAndSlot> seenExecutionPayloadBids =
LimitedSet.createSynchronized(SEEN_EXECUTION_PAYLOAD_BID_SET_SIZE);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's better to base this one number of slots rather than some random big number always occupying memory. Maybe Map<Slot, Set<UInt64>> for 10 slots could be a better for memory? You will also need synchronized internal sets.
What do you think?

final Optional<UInt64> maybeParentBlockSlot =
gossipValidationHelper.getSlotForBlockRoot(bid.getParentBlockRoot());
if (maybeParentBlockSlot.isEmpty()) {
LOG.trace("Bid's parent block does not exist. It will be saved for future processing");
Copy link
Contributor

Choose a reason for hiding this comment

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

we don't expect this with previous check passed, but anyway, let's add blockRoot to the log string

LOG.trace(
"State for block root {} and slot {} is unavailable.",
bid.getParentBlockRoot(),
bid.getSlot());
Copy link
Contributor

Choose a reason for hiding this comment

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

parentBlockSlot?

* [REJECT] bid.builder_index is a valid, active, and non-slashed builder index.
*/

final UInt64 buildrIndex = bid.getBuilderIndex();
Copy link
Contributor

Choose a reason for hiding this comment

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

builderIndex

LOG.trace("Invalid payload execution bid signature");
return reject("Invalid payload execution bid signature");
}
highestBids.merge(bidValueKey, bid.getValue(), UInt64::max);
Copy link
Contributor

Choose a reason for hiding this comment

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

why? I don't understand. If it's really needed, we need a comment here

assertThatSafeFuture(bidValidator.validate(signedBid)).isCompletedWithValue(ACCEPT);

// a same value bid from a different builder with the same parent block hash and slot
final SignedExecutionPayloadBid lowerValueBid =
Copy link
Contributor

Choose a reason for hiding this comment

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

sameValueBid?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants