From 8e46b6097ac53e91214a3378d8f13a9f451f24d5 Mon Sep 17 00:00:00 2001 From: NC Date: Fri, 14 Jun 2024 14:11:23 +0300 Subject: [PATCH] feat: move attestation committee at the end of attestation (#6883) --- .../src/chain/validation/attestation.ts | 2 +- packages/beacon-node/src/util/sszBytes.ts | 26 ++++++++++--------- .../test/unit/util/sszBytes.test.ts | 8 +++--- packages/types/src/electra/sszTypes.ts | 2 +- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/beacon-node/src/chain/validation/attestation.ts b/packages/beacon-node/src/chain/validation/attestation.ts index 0141eaafbb06..c44a8b7913c9 100644 --- a/packages/beacon-node/src/chain/validation/attestation.ts +++ b/packages/beacon-node/src/chain/validation/attestation.ts @@ -456,7 +456,7 @@ async function validateGossipAttestationNoSignatureCheck( let attDataRootHex: RootHex; const signature = attestationOrCache.attestation ? attestationOrCache.attestation.signature - : getSignatureFromAttestationSerialized(fork, attestationOrCache.serializedData); + : getSignatureFromAttestationSerialized(attestationOrCache.serializedData); if (signature === null) { throw new AttestationError(GossipAction.REJECT, { code: AttestationErrorCode.INVALID_SERIALIZED_BYTES, diff --git a/packages/beacon-node/src/util/sszBytes.ts b/packages/beacon-node/src/util/sszBytes.ts index c2675670daf2..1e505e83c977 100644 --- a/packages/beacon-node/src/util/sszBytes.ts +++ b/packages/beacon-node/src/util/sszBytes.ts @@ -26,8 +26,8 @@ export type AttDataCommitteeBitsBase64 = string; // class Attestation(Container): // aggregation_bits: BitList[MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT] - offset 4 // data: AttestationData - target data - 128 -// committee_bits: BitVector[MAX_COMMITTEES_PER_SLOT] // signature: BLSSignature - 96 +// committee_bits: BitVector[MAX_COMMITTEES_PER_SLOT] // // for all forks // class AttestationData(Container): 128 bytes fixed size @@ -82,14 +82,19 @@ export function getSeenAttDataKey(forkSeq: ForkSeq, data: Uint8Array): SeenAttDa * Return null if data is not long enough to extract attestation data. */ export function getSeenAttDataKeyElectra(electraAttestationBytes: Uint8Array): AttDataCommitteeBitsBase64 | null { - const startIndex = VARIABLE_FIELD_OFFSET; - const seenKeyLength = ATTESTATION_DATA_SIZE + COMMITTEE_BITS_SIZE; + const attestationData = getSeenAttDataKeyPhase0(electraAttestationBytes); - if (electraAttestationBytes.length < startIndex + seenKeyLength) { + if (attestationData === null) { return null; } - return toBase64(electraAttestationBytes.subarray(startIndex, startIndex + seenKeyLength)); + const committeeBits = getCommitteeBitsFromAttestationSerialized(electraAttestationBytes); + + if (committeeBits === null) { + return null; + } + + return attestationData + toBase64(committeeBits.uint8Array); } /** @@ -112,7 +117,7 @@ export function getSeenAttDataKeyPhase0(data: Uint8Array): AttDataBase64 | null export function getAggregationBitsFromAttestationSerialized(fork: ForkName, data: Uint8Array): BitArray | null { const aggregationBitsStartIndex = ForkSeq[fork] >= ForkSeq.electra - ? VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE + COMMITTEE_BITS_SIZE + SIGNATURE_SIZE + ? VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE + SIGNATURE_SIZE + COMMITTEE_BITS_SIZE : VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE + SIGNATURE_SIZE; if (data.length < aggregationBitsStartIndex) { @@ -127,11 +132,8 @@ export function getAggregationBitsFromAttestationSerialized(fork: ForkName, data * Extract signature from attestation serialized bytes. * Return null if data is not long enough to extract signature. */ -export function getSignatureFromAttestationSerialized(fork: ForkName, data: Uint8Array): BLSSignature | null { - const signatureStartIndex = - ForkSeq[fork] >= ForkSeq.electra - ? VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE + COMMITTEE_BITS_SIZE - : VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE; +export function getSignatureFromAttestationSerialized(data: Uint8Array): BLSSignature | null { + const signatureStartIndex = VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE; if (data.length < signatureStartIndex + SIGNATURE_SIZE) { return null; @@ -145,7 +147,7 @@ export function getSignatureFromAttestationSerialized(fork: ForkName, data: Uint * Return null if data is not long enough to extract committee bits. */ export function getCommitteeBitsFromAttestationSerialized(data: Uint8Array): BitArray | null { - const committeeBitsStartIndex = VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE; + const committeeBitsStartIndex = VARIABLE_FIELD_OFFSET + ATTESTATION_DATA_SIZE + SIGNATURE_SIZE; if (data.length < committeeBitsStartIndex + COMMITTEE_BITS_SIZE) { return null; diff --git a/packages/beacon-node/test/unit/util/sszBytes.test.ts b/packages/beacon-node/test/unit/util/sszBytes.test.ts index 03e4a7f7a71d..5edd9fb96fb1 100644 --- a/packages/beacon-node/test/unit/util/sszBytes.test.ts +++ b/packages/beacon-node/test/unit/util/sszBytes.test.ts @@ -54,12 +54,12 @@ describe("attestation SSZ serialized picking", () => { attestation.aggregationBits.toBoolArray() ); expect(getCommitteeBitsFromAttestationSerialized(bytes)).toEqual(attestation.committeeBits); - expect(getSignatureFromAttestationSerialized(ForkName.electra, bytes)).toEqual(attestation.signature); + expect(getSignatureFromAttestationSerialized(bytes)).toEqual(attestation.signature); } else { expect(getAggregationBitsFromAttestationSerialized(ForkName.phase0, bytes)?.toBoolArray()).toEqual( attestation.aggregationBits.toBoolArray() ); - expect(getSignatureFromAttestationSerialized(ForkName.phase0, bytes)).toEqual(attestation.signature); + expect(getSignatureFromAttestationSerialized(bytes)).toEqual(attestation.signature); } const attDataBase64 = ssz.phase0.AttestationData.serialize(attestation.data); @@ -99,8 +99,8 @@ describe("attestation SSZ serialized picking", () => { it("getSignatureFromAttestationSerialized - invalid data", () => { const invalidSignatureDataSizes = [0, 4, 100, 128, 227]; for (const size of invalidSignatureDataSizes) { - expect(getSignatureFromAttestationSerialized(ForkName.phase0, Buffer.alloc(size))).toBeNull(); - expect(getSignatureFromAttestationSerialized(ForkName.electra, Buffer.alloc(size))).toBeNull(); + expect(getSignatureFromAttestationSerialized(Buffer.alloc(size))).toBeNull(); + expect(getSignatureFromAttestationSerialized(Buffer.alloc(size))).toBeNull(); } }); }); diff --git a/packages/types/src/electra/sszTypes.ts b/packages/types/src/electra/sszTypes.ts index b03be1697fd1..ab9cbbaacd80 100644 --- a/packages/types/src/electra/sszTypes.ts +++ b/packages/types/src/electra/sszTypes.ts @@ -62,8 +62,8 @@ export const Attestation = new ContainerType( { aggregationBits: AggregationBits, // Modified in ELECTRA data: phase0Ssz.AttestationData, - committeeBits: CommitteeBits, // New in ELECTRA signature: BLSSignature, + committeeBits: CommitteeBits, // New in ELECTRA }, {typeName: "Attestation", jsonCase: "eth2"} );