mirror of
https://github.com/ChainSafe/lodestar.git
synced 2026-01-08 23:28:10 -05:00
Gossip validation
This commit is contained in:
@@ -10,7 +10,17 @@ import {
|
||||
getBlockHeaderProposerSignatureSetByHeaderSlot,
|
||||
getBlockHeaderProposerSignatureSetByParentStateSlot,
|
||||
} from "@lodestar/state-transition";
|
||||
import {DataColumnSidecar, DataColumnSidecars, Root, Slot, SubnetID, fulu, gloas, isGloasDataColumnSidecar, ssz} from "@lodestar/types";
|
||||
import {
|
||||
DataColumnSidecar,
|
||||
DataColumnSidecars,
|
||||
Root,
|
||||
Slot,
|
||||
SubnetID,
|
||||
fulu,
|
||||
gloas,
|
||||
isGloasDataColumnSidecar,
|
||||
ssz,
|
||||
} from "@lodestar/types";
|
||||
import {toRootHex, verifyMerkleBranch} from "@lodestar/utils";
|
||||
import {Metrics} from "../../metrics/metrics.js";
|
||||
import {kzg} from "../../util/kzg.js";
|
||||
@@ -23,16 +33,12 @@ import {GossipAction} from "../errors/gossipValidation.js";
|
||||
import {IBeaconChain} from "../interface.js";
|
||||
import {RegenCaller} from "../regen/interface.js";
|
||||
|
||||
// SPEC FUNCTION
|
||||
// https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.4/specs/fulu/p2p-interface.md#data_column_sidecar_subnet_id
|
||||
export async function validateGossipDataColumnSidecar(
|
||||
chain: IBeaconChain,
|
||||
dataColumnSidecar: DataColumnSidecar,
|
||||
gossipSubnet: SubnetID,
|
||||
metrics: Metrics | null
|
||||
): Promise<void> {
|
||||
const blockHeader = dataColumnSidecar.signedBlockHeader.message;
|
||||
const blockRootHex = toRootHex(ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader));
|
||||
|
||||
// 1) [REJECT] The sidecar is valid as verified by verify_data_column_sidecar
|
||||
verifyDataColumnSidecar(chain.config, dataColumnSidecar);
|
||||
@@ -46,6 +52,23 @@ export async function validateGossipDataColumnSidecar(
|
||||
});
|
||||
}
|
||||
|
||||
if (isGloasDataColumnSidecar(dataColumnSidecar)) {
|
||||
await validateGossipDataColumnSidecarGloas(chain, dataColumnSidecar, metrics);
|
||||
} else {
|
||||
await validateGossipDataColumnSidecarFulu(chain, dataColumnSidecar, metrics);
|
||||
}
|
||||
}
|
||||
|
||||
// SPEC FUNCTION
|
||||
// https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.4/specs/fulu/p2p-interface.md#data_column_sidecar_subnet_id
|
||||
export async function validateGossipDataColumnSidecarFulu(
|
||||
chain: IBeaconChain,
|
||||
dataColumnSidecar: fulu.DataColumnSidecar,
|
||||
metrics: Metrics | null
|
||||
): Promise<void> {
|
||||
const blockHeader = dataColumnSidecar.signedBlockHeader.message;
|
||||
const blockRootHex = toRootHex(ssz.phase0.BeaconBlockHeader.hashTreeRoot(blockHeader));
|
||||
|
||||
// 3) [IGNORE] The sidecar is not from a future slot (with a MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance)
|
||||
// -- i.e. validate that sidecar.slot <= current_slot (a client MAY queue future blocks
|
||||
// for processing at the appropriate slot).
|
||||
@@ -201,6 +224,60 @@ export async function validateGossipDataColumnSidecar(
|
||||
// -- Handled in seenGossipBlockInput
|
||||
}
|
||||
|
||||
export async function validateGossipDataColumnSidecarGloas(
|
||||
chain: IBeaconChain,
|
||||
dataColumnSidecar: gloas.DataColumnSidecar,
|
||||
metrics: Metrics | null
|
||||
): Promise<void> {
|
||||
const blockRootHex = toRootHex(dataColumnSidecar.beaconBlockRoot);
|
||||
const slot = dataColumnSidecar.slot;
|
||||
|
||||
// [IGNORE] The sidecar is the first sidecar for the tuple
|
||||
// `(sidecar.beacon_block_root, sidecar.index)` with valid kzg proof.
|
||||
// [IGNORE] The sidecar's `beacon_block_root` has been seen via a valid signed
|
||||
// execution payload bid. A client MAY queue the sidecar for processing once the
|
||||
// block is retrieved.
|
||||
// [REJECT] The hash of the sidecar's `kzg_commitments` matches the
|
||||
// `blob_kzg_commitments_root` in the corresponding builder's bid for
|
||||
// `sidecar.beacon_block_root`.
|
||||
// TODO GLOAS: Implement these
|
||||
|
||||
// TODO GLOAS: Validate data column sidecar against builder bid commitments root once available.
|
||||
// [REJECT]_The sidecars's `slot` matches the slot of the block with root
|
||||
// `beacon_block_root`.
|
||||
const block = chain.forkChoice.getBlockHex(blockRootHex);
|
||||
if (block !== null && block.slot !== slot) {
|
||||
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
||||
code: DataColumnSidecarErrorCode.INCORRECT_BLOCK,
|
||||
slot,
|
||||
columnIndex: dataColumnSidecar.index,
|
||||
expected: blockRootHex,
|
||||
actual: blockRootHex,
|
||||
});
|
||||
}
|
||||
|
||||
// [REJECT] The sidecar's column data is valid as verified by verify_data_column_sidecar_kzg_proofs
|
||||
const kzgProofTimer = metrics?.peerDas.dataColumnSidecarKzgProofsVerificationTime.startTimer();
|
||||
try {
|
||||
await verifyDataColumnSidecarKzgProofs(
|
||||
dataColumnSidecar.kzgCommitments,
|
||||
Array.from({length: dataColumnSidecar.column.length}, () => dataColumnSidecar.index),
|
||||
dataColumnSidecar.column,
|
||||
dataColumnSidecar.kzgProofs
|
||||
);
|
||||
} catch {
|
||||
throw new DataColumnSidecarGossipError(GossipAction.REJECT, {
|
||||
code: DataColumnSidecarErrorCode.INVALID_KZG_PROOF,
|
||||
slot,
|
||||
columnIndex: dataColumnSidecar.index,
|
||||
});
|
||||
} finally {
|
||||
kzgProofTimer?.();
|
||||
}
|
||||
|
||||
// TODO GLOAS: Add to seen cache
|
||||
}
|
||||
|
||||
/**
|
||||
* SPEC FUNCTION
|
||||
* https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.4/specs/fulu/p2p-interface.md#verify_data_column_sidecar
|
||||
|
||||
Reference in New Issue
Block a user