Skip to content

Commit 872b751

Browse files
committed
feat: update slash on bad attestations
1 parent 6e4f894 commit 872b751

16 files changed

Lines changed: 867 additions & 13 deletions

File tree

yarn-project/end-to-end/src/e2e_slashing/attested_invalid_proposal.test.ts

Lines changed: 603 additions & 0 deletions
Large diffs are not rendered by default.

yarn-project/end-to-end/src/fixtures/setup_p2p_test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ export type CreateNodeConfig = AztecNodeConfig & {
8888
dontStartSequencer?: boolean;
8989
/** Override the private key (instead of deriving from addressIndex). */
9090
validatorPrivateKey?: `0x${string}`;
91+
/** Corrupt only the block proposal at this indexWithinCheckpoint (testing only). */
92+
invalidBlockProposalIndexWithinCheckpoint?: number;
93+
/** Accept proposal gossip regardless of slot timing (testing only). */
94+
skipProposalSlotValidation?: boolean;
9195
};
9296

9397
/** Creates a P2P enabled instance of Aztec Node Service with a validator. */

yarn-project/p2p/src/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ export interface P2PConfig
229229

230230
/** Drop incoming block and checkpoint proposals at the libp2p dispatch layer (for testing only) */
231231
skipIncomingProposals?: boolean;
232+
233+
/** Accept proposal gossip regardless of slot timing (for testing only). */
234+
skipProposalSlotValidation?: boolean;
232235
}
233236

234237
export const DEFAULT_P2P_PORT = 40400;
@@ -554,6 +557,10 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
554557
description: 'Drop incoming block and checkpoint proposals at the libp2p dispatch layer (for testing only)',
555558
...booleanConfigHelper(false),
556559
},
560+
skipProposalSlotValidation: {
561+
description: 'Accept proposal gossip regardless of slot timing (for testing only)',
562+
...booleanConfigHelper(false),
563+
},
557564
minTxPoolAgeMs: {
558565
env: 'P2P_MIN_TX_POOL_AGE_MS',
559566
description: 'Minimum age (ms) a transaction must have been in the pool before it is eligible for block building.',

yarn-project/p2p/src/msg_validators/proposal_validator/block_proposal_validator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class BlockProposalValidator implements P2PValidator<BlockProposal> {
1313
maxTxsPerBlock?: number;
1414
maxBlocksPerCheckpoint?: number;
1515
p2pPropagationTime?: number;
16+
skipSlotValidation?: boolean;
1617
signatureContext: CoordinationSignatureContext;
1718
},
1819
) {

yarn-project/p2p/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export class CheckpointProposalValidator implements P2PValidator<CheckpointPropo
1818
maxTxsPerBlock?: number;
1919
maxBlocksPerCheckpoint?: number;
2020
p2pPropagationTime?: number;
21+
skipSlotValidation?: boolean;
2122
signatureContext: CoordinationSignatureContext;
2223
},
2324
) {

yarn-project/p2p/src/msg_validators/proposal_validator/proposal_validator.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class ProposalValidator {
2020
private maxTxsPerBlock?: number;
2121
private maxBlocksPerCheckpoint?: number;
2222
private pipeliningWindow: PipeliningWindow;
23+
private skipSlotValidation: boolean;
2324
private signatureContext: CoordinationSignatureContext;
2425

2526
constructor(
@@ -29,6 +30,7 @@ export class ProposalValidator {
2930
maxTxsPerBlock?: number;
3031
maxBlocksPerCheckpoint?: number;
3132
p2pPropagationTime?: number;
33+
skipSlotValidation?: boolean;
3234
signatureContext: CoordinationSignatureContext;
3335
},
3436
loggerName: string,
@@ -38,6 +40,7 @@ export class ProposalValidator {
3840
this.maxTxsPerBlock = opts.maxTxsPerBlock;
3941
this.maxBlocksPerCheckpoint = opts.maxBlocksPerCheckpoint;
4042
this.pipeliningWindow = new PipeliningWindow(epochCache, { p2pPropagationTime: opts.p2pPropagationTime });
43+
this.skipSlotValidation = opts.skipSlotValidation ?? false;
4144
this.signatureContext = opts.signatureContext;
4245
this.logger = createLogger(loggerName);
4346
}
@@ -60,7 +63,7 @@ export class ProposalValidator {
6063
const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
6164

6265
const slotNumber = proposal.slotNumber;
63-
if (slotNumber !== targetSlot && slotNumber !== nextSlot) {
66+
if (!this.skipSlotValidation && slotNumber !== targetSlot && slotNumber !== nextSlot) {
6467
// When pipelining, accept proposals for the current slot (built in the previous slot)
6568
// if they're still within the shared proposal acceptance window.
6669
if (this.pipeliningWindow.acceptsProposal(slotNumber)) {

yarn-project/p2p/src/services/libp2p/libp2p_service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ export class LibP2PService extends WithTracer implements P2PService {
241241
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
242242
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
243243
p2pPropagationTime,
244+
skipSlotValidation: config.skipProposalSlotValidation,
244245
signatureContext: {
245246
chainId: config.l1ChainId,
246247
rollupAddress: config.rollupAddress,

yarn-project/sequencer-client/src/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
191191
description: 'Broadcast invalid block proposals with corrupted state (for testing only)',
192192
...booleanConfigHelper(DefaultSequencerConfig.broadcastInvalidBlockProposal),
193193
},
194+
invalidBlockProposalIndexWithinCheckpoint: {
195+
description: 'Broadcast an invalid block proposal only at this indexWithinCheckpoint (for testing only)',
196+
...optionalNumberConfigHelper(),
197+
},
194198
injectFakeAttestation: {
195199
description: 'Inject a fake attestation (for testing only)',
196200
...booleanConfigHelper(DefaultSequencerConfig.injectFakeAttestation),

yarn-project/sequencer-client/src/sequencer/checkpoint_proposal_job.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,6 @@ export class CheckpointProposalJob implements Traceable {
631631

632632
const checkpointProposalOptions: CheckpointProposalOptions = {
633633
publishFullTxs: !!this.config.publishTxsWithProposals,
634-
broadcastInvalidCheckpointProposal: this.config.broadcastInvalidBlockProposal,
635634
};
636635

637636
let blocksInCheckpoint: L2Block[] = [];
@@ -887,7 +886,12 @@ export class CheckpointProposalJob implements Traceable {
887886
usedTxs.forEach(tx => txHashesAlreadyIncluded.add(tx.txHash.toString()));
888887

889888
// Sign the block proposal. This will throw if HA signing fails.
890-
const proposal = await this.createBlockProposal(block, inHash, usedTxs, blockProposalOptions);
889+
const proposal = await this.createBlockProposal(block, inHash, usedTxs, {
890+
...blockProposalOptions,
891+
broadcastInvalidBlockProposal:
892+
blockProposalOptions.broadcastInvalidBlockProposal ||
893+
block.indexWithinCheckpoint === this.config.invalidBlockProposalIndexWithinCheckpoint,
894+
});
891895

892896
// Sync the proposed block to the archiver to make it available, only after we've managed to sign the proposal,
893897
// so we avoid polluting our archive with a block that would fail.
@@ -1107,6 +1111,9 @@ export class CheckpointProposalJob implements Traceable {
11071111
// `buildSlot` is the wall-clock slot during which the block was actually built.
11081112
this.eventEmitter.emit('block-proposed', {
11091113
blockNumber: block.number,
1114+
blockHash,
1115+
checkpointNumber: this.checkpointNumber,
1116+
indexWithinCheckpoint: block.indexWithinCheckpoint,
11101117
slot: this.targetSlot,
11111118
buildSlot: this.slotNow,
11121119
});

yarn-project/sequencer-client/src/sequencer/events.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import type { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
1+
import type { BlockNumber, CheckpointNumber, IndexWithinCheckpoint, SlotNumber } from '@aztec/foundation/branded-types';
2+
import type { BlockHash } from '@aztec/stdlib/block';
23

34
import type { Action } from '../publisher/sequencer-publisher.js';
45
import type { SequencerState } from './utils.js';
@@ -33,7 +34,14 @@ export type SequencerEvents = {
3334
['proposer-rollup-check-failed']: (args: { reason: string; slot: SlotNumber }) => void;
3435
['block-tx-count-check-failed']: (args: { minTxs: number; availableTxs: number; slot: SlotNumber }) => void;
3536
['block-build-failed']: (args: { reason: string; slot: SlotNumber }) => void;
36-
['block-proposed']: (args: { blockNumber: BlockNumber; slot: SlotNumber; buildSlot: SlotNumber }) => void;
37+
['block-proposed']: (args: {
38+
blockNumber: BlockNumber;
39+
blockHash: BlockHash;
40+
checkpointNumber: CheckpointNumber;
41+
indexWithinCheckpoint: IndexWithinCheckpoint;
42+
slot: SlotNumber;
43+
buildSlot: SlotNumber;
44+
}) => void;
3745
['checkpoint-empty']: (args: { slot: SlotNumber }) => void;
3846
['checkpoint-publish-failed']: (args: {
3947
slot: SlotNumber;

0 commit comments

Comments
 (0)