-
Notifications
You must be signed in to change notification settings - Fork 975
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
EIP-7549: Append new committee_bits
field to end of Attestation
#3768
Conversation
Introducing new fields in the middle of an existing `Container` pointlessly breaks merkleization of all subsequent fields. In the case of `committee_bits`, it is also misleading, as `signature` only covers `data` inside `Attestation`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds quite reasonable to me! I’d wait for more approvals from CL client devs and then merge it
The other open question is, that, technically, changing If we want to stop breaking smart contract verifiers randomly, we have to consider using theoretical limits as the With Electra, we get a clean slate and could revisit data types and update limits accordingly. Especially with EIP-7495 StableContainer in mind. |
In Lodestar we cache seen attestations by extracting (attestation data + committee bits). Currently it is a convenient one-time slice from the ssz bytes since attestation data and committee bits are together. This proposal would mean we do slicing twice. Minor annoyance but doable. |
We should also consider renaming # [Modified in Electra:EIP7549]
assert data.index == 0
committee_indices = get_committee_indices(attestation.committee_bits)
participants_count = 0
for index in committee_indices:
assert index < get_committee_count_per_slot(state, data.target.epoch)
committee = get_beacon_committee(state, data.slot, index)
participants_count += len(committee)
assert len(attestation.aggregation_bits) == participants_count Note that with EIP-7688 based forward compatibility ( |
As for naming, one suggestion how it could look: Attestation(Profile[StableAttestation]):
data: AttestationData
signature: BLSSignature
participant_bits: Bitvector[
MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] # [New in Electra:EIP7549]
committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT] # [New in Electra:EIP7549]
IndexedAttestation(Profile[StableIndexedAttestation]):
data: AttestationData
signature: ValidatorSig
participant_indices*: List[uint64,
MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] # [New in Electra:EIP7549] Rationale:
|
Switching to a bitfield in this case would require to obtain the state in order to process attester slashing which i don’t think is desirable. Do I understand correctly that if we use |
My comment on the naming was independent of Existing field names cannot be easily renamed, because JSON is used on the builder API, so, it is not possible to suddenly transition existing You are correct that if we already had I cannot recall a past fork, though, where a field retained its name across type changes (except when inner containers got extended, which is also still allowed as today in a If people don't like renaming to
How would an attester slashing be processed without access to the state? You are right, though, |
|
OK, let's keep the indices as is then. Only remaining question then is whether the lists that changed capacities should be renamed to |
Aren’t implementations introduce a new type whenever the struct is changing? Wouldn’t this mean that they also check where the old version is used and change the logic of those places accordingly? If the new type would name the bitfield differently it doesn’t allow to avoid checking where the old one is used in the code. |
Yes, they have to be aware of the change though and make sure to actually update all of the logic. That extends beyond CL full node implementations to any clients of beacon-API or smart contract.
It forces more oversights to be compilation errors instead of runtime errors, as the entire category of bugs where someone accidentally uses parts of the phase0 logic post Electra is ruled out. It also discourages shortcut-taking. For example, an implementation may switch logic depending on the capacity of
Ultimately, implementations have to adjust logic everywhere to be correct / compliant. Forcing new field names when the type / semantics change reveals oversights sooner, but the overall work required is obviously still the same. One aspect to keep in mind is that this also affects non-CL implementations. For example, validator reward smoothing pools may track attestation performance of each validator for computing their share of the pooled funds. If they continue consuming the existing How highly to prioritize these aspects I'm not sure. Generally, forward / backward compatibility issues have a tendency of only getting attention once something blew up. Personally I'd accept both 'keeping names as is' and 'rename the fields that got new semantics', with slight preference for the latter but also no strong opposition for the former. |
Does this have any practical consequences?
Actually, if we are to change the field's position, then the type definition would be the most readable to me if both bits fields are next to each other. And I like readability 😄 |
Not for Ethereum CL and EL core implemenations themselves, but it affects smart contracts that verify beacon state proofs using EIP-4788.
Yes, the order is misleading, it's this way for historical reasons, and incorrectly suggests that the signature signs over them.
True, but field order determines the "shape" of the Merkle proofs. While appending new fields is fine to some extent (it doens't move existing fields), inserting things in the middle is breaking. As for readability, that could be solved by implementations. e.g., you could implement it by semantically grouping the field accessors (while still keeping the memory layout append-only). The order in which fields are pushed to the network / into Merkle proofs does not necessarily have to be linked to the semantic groups. |
I don't feel strongly about |
To clarify, namings have to be aligned on, as they appear in JSON builder API (mevboost) and in beacon API (for developers only, real tools should use SSZ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we are going to change this, I do have a preference to put committee_bits
next to aggregation_bits
, with a slight preference to have it first
the status quo already breaks the generalized indices so this would be no-change on that front; however, it would prevent the "have data after the signature in some Container" issue
Introducing new fields in the middle of an existing
Container
pointlessly breaks merkleization of all subsequent fields. In the case ofcommittee_bits
, it is also misleading, assignature
only coversdata
insideAttestation
.