Skip to content

Commit

Permalink
Merge 0fc928e into cb99fc4
Browse files Browse the repository at this point in the history
  • Loading branch information
jeluard committed Feb 8, 2024
2 parents cb99fc4 + 0fc928e commit bcdf203
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 0 deletions.
10 changes: 10 additions & 0 deletions packages/api/src/beacon/routes/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export enum EventType {
attestation = "attestation",
/** The node has received a valid voluntary exit (from P2P or API) */
voluntaryExit = "voluntary_exit",
/** The node has received a valid proposer slashing (from P2P or API) */
proposerSlashing = "proposer_slashing",
/** The node has received a valid attester slashing (from P2P or API) */
attesterSlashing = "attester_slashing",
/** The node has received a valid blsToExecutionChange (from P2P or API) */
blsToExecutionChange = "bls_to_execution_change",
/** Finalized checkpoint has been updated */
Expand All @@ -58,6 +62,8 @@ export const eventTypes: {[K in EventType]: K} = {
[EventType.block]: EventType.block,
[EventType.attestation]: EventType.attestation,
[EventType.voluntaryExit]: EventType.voluntaryExit,
[EventType.proposerSlashing]: EventType.proposerSlashing,
[EventType.attesterSlashing]: EventType.attesterSlashing,
[EventType.blsToExecutionChange]: EventType.blsToExecutionChange,
[EventType.finalizedCheckpoint]: EventType.finalizedCheckpoint,
[EventType.chainReorg]: EventType.chainReorg,
Expand Down Expand Up @@ -85,6 +91,8 @@ export type EventData = {
};
[EventType.attestation]: phase0.Attestation;
[EventType.voluntaryExit]: phase0.SignedVoluntaryExit;
[EventType.proposerSlashing]: phase0.ProposerSlashing;
[EventType.attesterSlashing]: phase0.AttesterSlashing;
[EventType.blsToExecutionChange]: capella.SignedBLSToExecutionChange;
[EventType.finalizedCheckpoint]: {
block: RootHex;
Expand Down Expand Up @@ -174,6 +182,8 @@ export function getTypeByEvent(): {[K in EventType]: TypeJson<EventData[K]>} {

[EventType.attestation]: ssz.phase0.Attestation,
[EventType.voluntaryExit]: ssz.phase0.SignedVoluntaryExit,
[EventType.proposerSlashing]: ssz.phase0.ProposerSlashing,
[EventType.attesterSlashing]: ssz.phase0.AttesterSlashing,
[EventType.blsToExecutionChange]: ssz.capella.SignedBLSToExecutionChange,

[EventType.finalizedCheckpoint]: new ContainerType(
Expand Down
62 changes: 62 additions & 0 deletions packages/api/test/unit/beacon/testData/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,68 @@ export const eventTestData: EventData = {
signature:
"0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
}),
[EventType.proposerSlashing]: ssz.phase0.ProposerSlashing.fromJson({
signed_header_1: {
message: {
slot: "0",
proposer_index: "0",
parent_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
state_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
body_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
},
signature:
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
},
signed_header_2: {
message: {
slot: "0",
proposer_index: "0",
parent_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
state_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
body_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
},
signature:
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
},
}),
[EventType.attesterSlashing]: ssz.phase0.AttesterSlashing.fromJson({
attestation_1: {
attesting_indices: ["0", "1"],
data: {
slot: "0",
index: "0",
beacon_block_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
source: {
epoch: "0",
root: "0x0000000000000000000000000000000000000000000000000000000000000000",
},
target: {
epoch: "0",
root: "0x0000000000000000000000000000000000000000000000000000000000000000",
},
},
signature:
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
},
attestation_2: {
attesting_indices: ["0", "1"],
data: {
slot: "0",
index: "0",
beacon_block_root: "0x0000000000000000000000000000000000000000000000000000000000000000",
source: {
epoch: "0",
root: "0x0000000000000000000000000000000000000000000000000000000000000000",
},
target: {
epoch: "0",
root: "0x0000000000000000000000000000000000000000000000000000000000000000",
},
},
signature:
"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
},
}),
[EventType.blsToExecutionChange]: ssz.capella.SignedBLSToExecutionChange.fromJson({
message: {
validator_index: "1",
Expand Down
10 changes: 10 additions & 0 deletions packages/beacon-node/src/chain/blocks/importBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,16 @@ export async function importBlock(
this.emitter.emit(routes.events.EventType.attestation, attestation);
}
}
if (this.emitter.listenerCount(routes.events.EventType.attesterSlashing)) {
for (const attesterSlashing of block.message.body.attesterSlashings) {
this.emitter.emit(routes.events.EventType.attesterSlashing, attesterSlashing);
}
}
if (this.emitter.listenerCount(routes.events.EventType.proposerSlashing)) {
for (const proposerSlashing of block.message.body.proposerSlashings) {
this.emitter.emit(routes.events.EventType.proposerSlashing, proposerSlashing);
}
}
}

// Register stat metrics about the block after importing it
Expand Down
4 changes: 4 additions & 0 deletions packages/beacon-node/src/network/processor/gossipHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler
} catch (e) {
logger.error("Error adding attesterSlashing to pool", {}, e as Error);
}

chain.emitter.emit(routes.events.EventType.attesterSlashing, attesterSlashing);
},

[GossipType.proposer_slashing]: async ({
Expand All @@ -470,6 +472,8 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler
} catch (e) {
logger.error("Error adding attesterSlashing to pool", {}, e as Error);
}

chain.emitter.emit(routes.events.EventType.proposerSlashing, proposerSlashing);
},

[GossipType.voluntary_exit]: async ({gossipData, topic}: GossipHandlerParamGeneric<GossipType.voluntary_exit>) => {
Expand Down
64 changes: 64 additions & 0 deletions packages/beacon-node/test/e2e/network/gossipsub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,70 @@ function runTests({useWorker}: {useWorker: boolean}): void {
);
});

it("Publish and receive an attesterSlashing", async function () {
let onAttesterSlashingChange: (payload: Uint8Array) => void;
const onAttesterSlashingChangePromise = new Promise<Uint8Array>((resolve) => (onAttesterSlashingChange = resolve));

const {netA, netB} = await mockModules({
[GossipType.attester_slashing]: async ({gossipData}: GossipHandlerParamGeneric<GossipType.attester_slashing>) => {
onAttesterSlashingChange(gossipData.serializedData);
},
});

await Promise.all([onPeerConnect(netA), onPeerConnect(netB), connect(netA, netB)]);
expect(netA.getConnectedPeerCount()).toBe(1);
expect(netB.getConnectedPeerCount()).toBe(1);

await netA.subscribeGossipCoreTopics();
await netB.subscribeGossipCoreTopics();

// Wait to have a peer connected to a topic
while (!netA.closed) {
await sleep(500);
if (await hasSomeMeshPeer(netA)) {
break;
}
}

const attesterSlashing = ssz.phase0.AttesterSlashing.defaultValue();
await netA.publishAttesterSlashing(attesterSlashing);

const received = await onAttesterSlashingChangePromise;
expect(Buffer.from(received)).toEqual(Buffer.from(ssz.phase0.AttesterSlashing.serialize(attesterSlashing)));
});

it("Publish and receive a proposerSlashing", async function () {
let onProposerSlashingChange: (payload: Uint8Array) => void;
const onProposerSlashingChangePromise = new Promise<Uint8Array>((resolve) => (onProposerSlashingChange = resolve));

const {netA, netB} = await mockModules({
[GossipType.proposer_slashing]: async ({gossipData}: GossipHandlerParamGeneric<GossipType.proposer_slashing>) => {
onProposerSlashingChange(gossipData.serializedData);
},
});

await Promise.all([onPeerConnect(netA), onPeerConnect(netB), connect(netA, netB)]);
expect(netA.getConnectedPeerCount()).toBe(1);
expect(netB.getConnectedPeerCount()).toBe(1);

await netA.subscribeGossipCoreTopics();
await netB.subscribeGossipCoreTopics();

// Wait to have a peer connected to a topic
while (!netA.closed) {
await sleep(500);
if (await hasSomeMeshPeer(netA)) {
break;
}
}

const proposerSlashing = ssz.phase0.ProposerSlashing.defaultValue();
await netA.publishProposerSlashing(proposerSlashing);

const received = await onProposerSlashingChangePromise;
expect(Buffer.from(received)).toEqual(Buffer.from(ssz.phase0.ProposerSlashing.serialize(proposerSlashing)));
});

it("Publish and receive a LightClientOptimisticUpdate", async function () {
let onLightClientOptimisticUpdate: (ou: Uint8Array) => void;
const onLightClientOptimisticUpdatePromise = new Promise<Uint8Array>(
Expand Down

0 comments on commit bcdf203

Please sign in to comment.