@aztec/sequencer-client 2.0.0-nightly.20250821 → 2.0.0-nightly.20250823

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
4
4
  import { EthAddress } from '@aztec/foundation/eth-address';
5
5
  import type { DateProvider } from '@aztec/foundation/timer';
6
6
  import type { P2P } from '@aztec/p2p';
7
- import type { SlasherClient } from '@aztec/slasher';
7
+ import type { SlasherClientInterface } from '@aztec/slasher';
8
8
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
9
9
  import type { L2BlockSource } from '@aztec/stdlib/block';
10
10
  import type { IFullNodeBlockBuilder, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
@@ -37,7 +37,7 @@ export declare class SequencerClient {
37
37
  validatorClient: ValidatorClient | undefined;
38
38
  p2pClient: P2P;
39
39
  worldStateSynchronizer: WorldStateSynchronizer;
40
- slasherClient: SlasherClient;
40
+ slasherClient: SlasherClientInterface | undefined;
41
41
  blockBuilder: IFullNodeBlockBuilder;
42
42
  l2BlockSource: L2BlockSource;
43
43
  l1ToL2MessageSource: L1ToL2MessageSource;
@@ -1 +1 @@
1
- {"version":3,"file":"sequencer-client.d.ts","sourceRoot":"","sources":["../../src/client/sequencer-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAShD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACrG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExE;;GAEG;AACH,qBAAa,eAAe;IAExB,SAAS,CAAC,SAAS,EAAE,SAAS;IAC9B,SAAS,CAAC,eAAe,CAAC,EAAE,eAAe;gBADjC,SAAS,EAAE,SAAS,EACpB,eAAe,CAAC,EAAE,eAAe,YAAA;IAG7C;;;;;;;;;;;OAWG;WACiB,GAAG,CACrB,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE;QACJ,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;QAC7C,SAAS,EAAE,GAAG,CAAC;QACf,sBAAsB,EAAE,sBAAsB,CAAC;QAC/C,aAAa,EAAE,aAAa,CAAC;QAC7B,YAAY,EAAE,qBAAqB,CAAC;QACpC,aAAa,EAAE,aAAa,CAAC;QAC7B,mBAAmB,EAAE,mBAAmB,CAAC;QACzC,SAAS,EAAE,eAAe,CAAC;QAC3B,SAAS,CAAC,EAAE,kBAAkB,CAAC;QAC/B,cAAc,CAAC,EAAE,uBAAuB,CAAC;QACzC,YAAY,EAAE,YAAY,CAAC;QAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,SAAS,CAAC,EAAE,kBAAkB,CAAC;KAChC;IAsGH;;;OAGG;IACI,qBAAqB,CAAC,MAAM,EAAE,eAAe;IAIpD,4BAA4B;IACf,KAAK;IAKlB;;OAEG;IACU,IAAI;IAIjB;;OAEG;IACI,MAAM;IAIN,YAAY,IAAI,SAAS;IAIhC,IAAI,QAAQ,IAAI,UAAU,CAEzB;IAED,IAAI,YAAY,IAAI,YAAY,CAE/B;IAED,IAAI,kBAAkB,IAAI,UAAU,EAAE,GAAG,SAAS,CAEjD;IAED,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;CACF"}
1
+ {"version":3,"file":"sequencer-client.d.ts","sourceRoot":"","sources":["../../src/client/sequencer-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAErG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExE;;GAEG;AACH,qBAAa,eAAe;IAExB,SAAS,CAAC,SAAS,EAAE,SAAS;IAC9B,SAAS,CAAC,eAAe,CAAC,EAAE,eAAe;gBADjC,SAAS,EAAE,SAAS,EACpB,eAAe,CAAC,EAAE,eAAe,YAAA;IAG7C;;;;;;;;;;;OAWG;WACiB,GAAG,CACrB,MAAM,EAAE,qBAAqB,EAC7B,IAAI,EAAE;QACJ,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;QAC7C,SAAS,EAAE,GAAG,CAAC;QACf,sBAAsB,EAAE,sBAAsB,CAAC;QAC/C,aAAa,EAAE,sBAAsB,GAAG,SAAS,CAAC;QAClD,YAAY,EAAE,qBAAqB,CAAC;QACpC,aAAa,EAAE,aAAa,CAAC;QAC7B,mBAAmB,EAAE,mBAAmB,CAAC;QACzC,SAAS,EAAE,eAAe,CAAC;QAC3B,SAAS,CAAC,EAAE,kBAAkB,CAAC;QAC/B,cAAc,CAAC,EAAE,uBAAuB,CAAC;QACzC,YAAY,EAAE,YAAY,CAAC;QAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,SAAS,CAAC,EAAE,kBAAkB,CAAC;KAChC;IA2GH;;;OAGG;IACI,qBAAqB,CAAC,MAAM,EAAE,eAAe;IAIpD,4BAA4B;IACf,KAAK;IAKlB;;OAEG;IACU,IAAI;IAIjB;;OAEG;IACI,MAAM;IAIN,YAAY,IAAI,SAAS;IAIhC,IAAI,QAAQ,IAAI,UAAU,CAEzB;IAED,IAAI,YAAY,IAAI,YAAY,CAE/B;IAED,IAAI,kBAAkB,IAAI,UAAU,EAAE,GAAG,SAAS,CAEjD;IAED,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;CACF"}
@@ -1,7 +1,9 @@
1
1
  import { EpochCache } from '@aztec/epoch-cache';
2
- import { GovernanceProposerContract, RollupContract, SlashingProposerContract, createEthereumChain, createExtendedL1Client, isAnvilTestChain } from '@aztec/ethereum';
2
+ import { GovernanceProposerContract, RollupContract, createEthereumChain, createExtendedL1Client, isAnvilTestChain } from '@aztec/ethereum';
3
3
  import { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
4
+ import { EthAddress } from '@aztec/foundation/eth-address';
4
5
  import { createLogger } from '@aztec/foundation/log';
6
+ import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
5
7
  import { GlobalVariableBuilder } from '../global_variable_builder/index.js';
6
8
  import { SequencerPublisher } from '../publisher/index.js';
7
9
  import { Sequencer } from '../sequencer/index.js';
@@ -38,8 +40,7 @@ import { Sequencer } from '../sequencer/index.js';
38
40
  rollupContract.getSlotDuration()
39
41
  ]);
40
42
  const governanceProposerContract = new GovernanceProposerContract(l1Client, config.l1Contracts.governanceProposerAddress.toString());
41
- const slashingProposerAddress = await rollupContract.getSlashingProposerAddress();
42
- const slashingProposerContract = new SlashingProposerContract(l1Client, slashingProposerAddress.toString());
43
+ const slashingProposerContract = await rollupContract.getSlashingProposer();
43
44
  const epochCache = deps.epochCache ?? await EpochCache.create(config.l1Contracts.rollupAddress, {
44
45
  l1RpcUrls: rpcUrls,
45
46
  l1ChainId: chainId,
@@ -50,6 +51,7 @@ import { Sequencer } from '../sequencer/index.js';
50
51
  }, {
51
52
  dateProvider: deps.dateProvider
52
53
  });
54
+ const slashFactoryContract = new SlashFactoryContract(l1Client, config.l1Contracts.slashFactoryAddress?.toString() ?? EthAddress.ZERO.toString());
53
55
  const publisher = deps.publisher ?? new SequencerPublisher(config, {
54
56
  l1TxUtils,
55
57
  telemetry: telemetryClient,
@@ -58,6 +60,7 @@ import { Sequencer } from '../sequencer/index.js';
58
60
  epochCache,
59
61
  governanceProposerContract,
60
62
  slashingProposerContract,
63
+ slashFactoryContract,
61
64
  dateProvider: deps.dateProvider
62
65
  });
63
66
  const globalsBuilder = new GlobalVariableBuilder(config);
@@ -1,12 +1,14 @@
1
1
  import type { L2Block } from '@aztec/aztec.js';
2
2
  import { type BlobSinkClientInterface } from '@aztec/blob-sink/client';
3
3
  import type { EpochCache } from '@aztec/epoch-cache';
4
- import { FormattedViemError, type GasPrice, type GovernanceProposerContract, type L1BlobInputs, type L1ContractsConfig, type L1GasConfig, type L1TxRequest, RollupContract, type SlashingProposerContract, type TransactionStats } from '@aztec/ethereum';
4
+ import { type EmpireSlashingProposerContract, FormattedViemError, type GasPrice, type GovernanceProposerContract, type L1BlobInputs, type L1ContractsConfig, type L1GasConfig, type L1TxRequest, RollupContract, type TallySlashingProposerContract, type TransactionStats } from '@aztec/ethereum';
5
5
  import type { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
6
6
  import { EthAddress } from '@aztec/foundation/eth-address';
7
7
  import type { Fr } from '@aztec/foundation/fields';
8
8
  import { DateProvider } from '@aztec/foundation/timer';
9
+ import { type ProposerSlashAction } from '@aztec/slasher';
9
10
  import { CommitteeAttestation, type ValidateBlockResult } from '@aztec/stdlib/block';
11
+ import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
10
12
  import { type ProposedBlockHeader, TxHash } from '@aztec/stdlib/tx';
11
13
  import { type TelemetryClient } from '@aztec/telemetry-client';
12
14
  import { type TransactionReceipt, type TypedDataDefinition } from 'viem';
@@ -15,8 +17,7 @@ export declare enum SignalType {
15
17
  GOVERNANCE = 0,
16
18
  SLASHING = 1
17
19
  }
18
- type GetSlashPayloadCallBack = (slotNumber: bigint) => Promise<EthAddress | undefined>;
19
- declare const Actions: readonly ["propose", "governance-signal", "slashing-signal", "invalidate-by-invalid-attestation", "invalidate-by-insufficient-attestations"];
20
+ declare const Actions: readonly ["propose", "governance-signal", "empire-slashing-signal", "create-empire-payload", "execute-empire-payload", "vote-offenses", "execute-slash", "invalidate-by-invalid-attestation", "invalidate-by-insufficient-attestations"];
20
21
  export type Action = (typeof Actions)[number];
21
22
  export type InvalidateBlockRequest = {
22
23
  request: L1TxRequest;
@@ -46,7 +47,7 @@ export declare class SequencerPublisher {
46
47
  protected governanceLog: import("@aztec/foundation/log").Logger;
47
48
  private governancePayload;
48
49
  protected slashingLog: import("@aztec/foundation/log").Logger;
49
- private getSlashPayload?;
50
+ protected slashingProposerAddress?: EthAddress;
50
51
  private myLastSignals;
51
52
  protected log: import("@aztec/foundation/log").Logger;
52
53
  protected ethereumSlotDuration: bigint;
@@ -57,20 +58,21 @@ export declare class SequencerPublisher {
57
58
  l1TxUtils: L1TxUtilsWithBlobs;
58
59
  rollupContract: RollupContract;
59
60
  govProposerContract: GovernanceProposerContract;
60
- slashingProposerContract: SlashingProposerContract;
61
+ slashingProposerContract: EmpireSlashingProposerContract | TallySlashingProposerContract;
62
+ slashFactoryContract: SlashFactoryContract;
61
63
  protected requests: RequestWithExpiry[];
62
64
  constructor(config: TxSenderConfig & PublisherConfig & Pick<L1ContractsConfig, 'ethereumSlotDuration'>, deps: {
63
65
  telemetry?: TelemetryClient;
64
66
  blobSinkClient?: BlobSinkClientInterface;
65
67
  l1TxUtils: L1TxUtilsWithBlobs;
66
68
  rollupContract: RollupContract;
67
- slashingProposerContract: SlashingProposerContract;
69
+ slashingProposerContract: EmpireSlashingProposerContract | TallySlashingProposerContract;
68
70
  governanceProposerContract: GovernanceProposerContract;
71
+ slashFactoryContract: SlashFactoryContract;
69
72
  epochCache: EpochCache;
70
73
  dateProvider: DateProvider;
71
74
  });
72
75
  getRollupContract(): RollupContract;
73
- registerSlashPayloadGetter(callback: GetSlashPayloadCallBack): void;
74
76
  getSenderAddress(): EthAddress;
75
77
  getGovernancePayload(): EthAddress;
76
78
  setGovernancePayload(payload: EthAddress): void;
@@ -95,10 +97,10 @@ export declare class SequencerPublisher {
95
97
  errorMsg: string | undefined;
96
98
  stats?: undefined;
97
99
  };
98
- expiredActions: ("propose" | "governance-signal" | "slashing-signal" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
99
- sentActions: ("propose" | "governance-signal" | "slashing-signal" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
100
- successfulActions: ("propose" | "governance-signal" | "slashing-signal" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
101
- failedActions: ("propose" | "governance-signal" | "slashing-signal" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
100
+ expiredActions: ("propose" | "governance-signal" | "empire-slashing-signal" | "create-empire-payload" | "execute-empire-payload" | "vote-offenses" | "execute-slash" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
101
+ sentActions: ("propose" | "governance-signal" | "empire-slashing-signal" | "create-empire-payload" | "execute-empire-payload" | "vote-offenses" | "execute-slash" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
102
+ successfulActions: ("propose" | "governance-signal" | "empire-slashing-signal" | "create-empire-payload" | "execute-empire-payload" | "vote-offenses" | "execute-slash" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
103
+ failedActions: ("propose" | "governance-signal" | "empire-slashing-signal" | "create-empire-payload" | "execute-empire-payload" | "vote-offenses" | "execute-slash" | "invalidate-by-invalid-attestation" | "invalidate-by-insufficient-attestations")[];
102
104
  } | undefined>;
103
105
  private callbackBundledTransactions;
104
106
  /**
@@ -144,15 +146,15 @@ export declare class SequencerPublisher {
144
146
  forcePendingBlockNumber?: number;
145
147
  }): Promise<bigint>;
146
148
  private enqueueCastSignalHelper;
147
- private getSignalConfig;
148
149
  /**
149
- * Enqueues a castSignal transaction to cast a signal for a given slot number.
150
+ * Enqueues a governance castSignal transaction to cast a signal for a given slot number.
150
151
  * @param slotNumber - The slot number to cast a signal for.
151
152
  * @param timestamp - The timestamp of the slot to cast a signal for.
152
- * @param signalType - The type of signal to cast.
153
153
  * @returns True if the signal was successfully enqueued, false otherwise.
154
154
  */
155
- enqueueCastSignal(slotNumber: bigint, timestamp: bigint, signalType: SignalType, signerAddress: EthAddress, signer: (msg: TypedDataDefinition) => Promise<`0x${string}`>): Promise<boolean>;
155
+ enqueueGovernanceCastSignal(slotNumber: bigint, timestamp: bigint, signerAddress: EthAddress, signer: (msg: TypedDataDefinition) => Promise<`0x${string}`>): Promise<boolean>;
156
+ /** Enqueues all slashing actions as returned by the slasher client. */
157
+ enqueueSlashingActions(actions: ProposerSlashAction[], slotNumber: bigint, timestamp: bigint, signerAddress: EthAddress, signer: (msg: TypedDataDefinition) => Promise<`0x${string}`>): Promise<boolean>;
156
158
  /**
157
159
  * Proposes a L2 block on L1.
158
160
  *
@@ -166,6 +168,7 @@ export declare class SequencerPublisher {
166
168
  enqueueInvalidateBlock(request: InvalidateBlockRequest | undefined, opts?: {
167
169
  txTimeoutAt?: Date;
168
170
  }): void;
171
+ private simulateAndEnqueueRequest;
169
172
  /**
170
173
  * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
171
174
  * Be warned, the call may return false even if the tx subsequently gets successfully mined.
@@ -1 +1 @@
1
- {"version":3,"file":"sequencer-publisher.d.ts","sourceRoot":"","sources":["../../src/publisher/sequencer-publisher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sequencer-publisher.d.ts","sourceRoot":"","sources":["../../src/publisher/sequencer-publisher.ts"],"names":[],"mappings":"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"}
@@ -5,8 +5,10 @@ import { sumBigint } from '@aztec/foundation/bigint';
5
5
  import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
6
6
  import { EthAddress } from '@aztec/foundation/eth-address';
7
7
  import { createLogger } from '@aztec/foundation/log';
8
+ import { bufferToHex } from '@aztec/foundation/string';
8
9
  import { Timer } from '@aztec/foundation/timer';
9
10
  import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
11
+ import { encodeSlashConsensusVotes } from '@aztec/slasher';
10
12
  import { CommitteeAttestation } from '@aztec/stdlib/block';
11
13
  import { ConsensusPayload, SignatureDomainSeparator, getHashedSignaturePayload } from '@aztec/stdlib/p2p';
12
14
  import { getTelemetryClient } from '@aztec/telemetry-client';
@@ -21,11 +23,15 @@ export var SignalType = /*#__PURE__*/ function(SignalType) {
21
23
  const Actions = [
22
24
  'propose',
23
25
  'governance-signal',
24
- 'slashing-signal',
26
+ 'empire-slashing-signal',
27
+ 'create-empire-payload',
28
+ 'execute-empire-payload',
29
+ 'vote-offenses',
30
+ 'execute-slash',
25
31
  'invalidate-by-invalid-attestation',
26
32
  'invalidate-by-insufficient-attestations'
27
33
  ];
28
- // Sorting for actions such that invalidations go first, then proposals, and last votes
34
+ // Sorting for actions such that invalidations go before proposals, and proposals go before votes
29
35
  const compareActions = (a, b)=>Actions.indexOf(b) - Actions.indexOf(a);
30
36
  export class SequencerPublisher {
31
37
  config;
@@ -35,7 +41,7 @@ export class SequencerPublisher {
35
41
  governanceLog;
36
42
  governancePayload;
37
43
  slashingLog;
38
- getSlashPayload;
44
+ slashingProposerAddress;
39
45
  myLastSignals;
40
46
  log;
41
47
  ethereumSlotDuration;
@@ -52,6 +58,7 @@ export class SequencerPublisher {
52
58
  rollupContract;
53
59
  govProposerContract;
54
60
  slashingProposerContract;
61
+ slashFactoryContract;
55
62
  requests;
56
63
  constructor(config, deps){
57
64
  this.config = config;
@@ -59,7 +66,6 @@ export class SequencerPublisher {
59
66
  this.governanceLog = createLogger('sequencer:publisher:governance');
60
67
  this.governancePayload = EthAddress.ZERO;
61
68
  this.slashingLog = createLogger('sequencer:publisher:slashing');
62
- this.getSlashPayload = undefined;
63
69
  this.myLastSignals = {
64
70
  [0]: 0n,
65
71
  [1]: 0n
@@ -82,13 +88,11 @@ export class SequencerPublisher {
82
88
  const newSlashingProposer = await this.rollupContract.getSlashingProposer();
83
89
  this.slashingProposerContract = newSlashingProposer;
84
90
  });
91
+ this.slashFactoryContract = deps.slashFactoryContract;
85
92
  }
86
93
  getRollupContract() {
87
94
  return this.rollupContract;
88
95
  }
89
- registerSlashPayloadGetter(callback) {
90
- this.getSlashPayload = callback;
91
- }
92
96
  getSenderAddress() {
93
97
  return EthAddress.fromString(this.l1TxUtils.getSenderAddress());
94
98
  }
@@ -422,7 +426,7 @@ export class SequencerPublisher {
422
426
  }
423
427
  const cachedLastVote = this.myLastSignals[signalType];
424
428
  this.myLastSignals[signalType] = slotNumber;
425
- const action = signalType === 0 ? 'governance-signal' : 'slashing-signal';
429
+ const action = signalType === 0 ? 'governance-signal' : 'empire-slashing-signal';
426
430
  const request = await base.createSignalRequestWithSignature(payload.toString(), slotNumber, this.config.l1ChainId, signerAddress.toString(), signer);
427
431
  this.log.debug(`Created ${action} request with signature`, {
428
432
  request,
@@ -438,9 +442,10 @@ export class SequencerPublisher {
438
442
  request
439
443
  });
440
444
  } catch (err) {
441
- this.log.warn(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, err);
445
+ this.log.error(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, err);
442
446
  // Yes, we enqueue the request anyway, in case there was a bug with the simulation itself
443
447
  }
448
+ // TODO(palla/slash): All votes (governance and slashing) should txTimeoutAt at the end of the slot.
444
449
  this.addRequest({
445
450
  gasConfig: {
446
451
  gasLimit: SequencerPublisher.VOTE_GAS_GUESS
@@ -468,43 +473,100 @@ export class SequencerPublisher {
468
473
  });
469
474
  return true;
470
475
  }
471
- async getSignalConfig(slotNumber, signalType) {
472
- if (signalType === 0) {
473
- return {
474
- payload: this.governancePayload,
475
- base: this.govProposerContract
476
- };
477
- } else if (signalType === 1) {
478
- if (!this.getSlashPayload) {
479
- return undefined;
480
- }
481
- const slashPayload = await this.getSlashPayload(slotNumber);
482
- if (!slashPayload) {
483
- return undefined;
484
- }
485
- this.log.info(`Slash payload: ${slashPayload}`);
486
- return {
487
- payload: slashPayload,
488
- base: this.slashingProposerContract
489
- };
490
- } else {
491
- const _ = signalType;
492
- throw new Error('Unreachable: Invalid signal type');
493
- }
494
- }
495
476
  /**
496
- * Enqueues a castSignal transaction to cast a signal for a given slot number.
477
+ * Enqueues a governance castSignal transaction to cast a signal for a given slot number.
497
478
  * @param slotNumber - The slot number to cast a signal for.
498
479
  * @param timestamp - The timestamp of the slot to cast a signal for.
499
- * @param signalType - The type of signal to cast.
500
480
  * @returns True if the signal was successfully enqueued, false otherwise.
501
- */ async enqueueCastSignal(slotNumber, timestamp, signalType, signerAddress, signer) {
502
- const signalConfig = await this.getSignalConfig(slotNumber, signalType);
503
- if (!signalConfig) {
481
+ */ enqueueGovernanceCastSignal(slotNumber, timestamp, signerAddress, signer) {
482
+ return this.enqueueCastSignalHelper(slotNumber, timestamp, 0, this.governancePayload, this.govProposerContract, signerAddress, signer);
483
+ }
484
+ /** Enqueues all slashing actions as returned by the slasher client. */ async enqueueSlashingActions(actions, slotNumber, timestamp, signerAddress, signer) {
485
+ if (actions.length === 0) {
486
+ this.log.debug(`No slashing actions to enqueue for slot ${slotNumber}`);
504
487
  return false;
505
488
  }
506
- const { payload, base } = signalConfig;
507
- return this.enqueueCastSignalHelper(slotNumber, timestamp, signalType, payload, base, signerAddress, signer);
489
+ for (const action of actions){
490
+ switch(action.type){
491
+ case 'vote-empire-payload':
492
+ {
493
+ if (this.slashingProposerContract.type !== 'empire') {
494
+ this.log.error('Cannot vote for empire payload on non-empire slashing contract');
495
+ break;
496
+ }
497
+ this.log.debug(`Enqueuing slashing vote for payload ${action.payload} at slot ${slotNumber}`, {
498
+ signerAddress
499
+ });
500
+ await this.enqueueCastSignalHelper(slotNumber, timestamp, 1, action.payload, this.slashingProposerContract, signerAddress, signer);
501
+ break;
502
+ }
503
+ case 'create-empire-payload':
504
+ {
505
+ this.log.debug(`Enqueuing slashing create payload at slot ${slotNumber}`, {
506
+ slotNumber,
507
+ signerAddress
508
+ });
509
+ const request = this.slashFactoryContract.buildCreatePayloadRequest(action.data);
510
+ await this.simulateAndEnqueueRequest('create-empire-payload', request, (receipt)=>!!this.slashFactoryContract.tryExtractSlashPayloadCreatedEvent(receipt.logs), slotNumber, timestamp);
511
+ break;
512
+ }
513
+ case 'execute-empire-payload':
514
+ {
515
+ this.log.debug(`Enqueuing slashing execute payload at slot ${slotNumber}`, {
516
+ slotNumber,
517
+ signerAddress
518
+ });
519
+ if (this.slashingProposerContract.type !== 'empire') {
520
+ this.log.error('Cannot execute slashing payload on non-empire slashing contract');
521
+ return false;
522
+ }
523
+ const empireSlashingProposer = this.slashingProposerContract;
524
+ const request = empireSlashingProposer.buildExecuteRoundRequest(action.round);
525
+ await this.simulateAndEnqueueRequest('execute-empire-payload', request, (receipt)=>!!empireSlashingProposer.tryExtractPayloadSubmittedEvent(receipt.logs), slotNumber, timestamp);
526
+ break;
527
+ }
528
+ case 'vote-offenses':
529
+ {
530
+ this.log.debug(`Enqueuing slashing vote for ${action.votes.length} votes at slot ${slotNumber}`, {
531
+ slotNumber,
532
+ round: action.round,
533
+ votesCount: action.votes.length,
534
+ signerAddress
535
+ });
536
+ if (this.slashingProposerContract.type !== 'tally') {
537
+ this.log.error('Cannot vote for slashing offenses on non-tally slashing contract');
538
+ return false;
539
+ }
540
+ const tallySlashingProposer = this.slashingProposerContract;
541
+ const votes = bufferToHex(encodeSlashConsensusVotes(action.votes));
542
+ const request = await tallySlashingProposer.buildVoteRequestFromSigner(votes, slotNumber, signer);
543
+ await this.simulateAndEnqueueRequest('vote-offenses', request, (receipt)=>!!tallySlashingProposer.tryExtractVoteCastEvent(receipt.logs), slotNumber, timestamp);
544
+ break;
545
+ }
546
+ case 'execute-slash':
547
+ {
548
+ this.log.debug(`Enqueuing slash execution for round ${action.round} at slot ${slotNumber}`, {
549
+ slotNumber,
550
+ round: action.round,
551
+ signerAddress
552
+ });
553
+ if (this.slashingProposerContract.type !== 'tally') {
554
+ this.log.error('Cannot execute slashing offenses on non-tally slashing contract');
555
+ return false;
556
+ }
557
+ const tallySlashingProposer = this.slashingProposerContract;
558
+ const request = tallySlashingProposer.buildExecuteRoundRequest(action.round, action.committees);
559
+ await this.simulateAndEnqueueRequest('execute-slash', request, (receipt)=>!!tallySlashingProposer.tryExtractRoundExecutedEvent(receipt.logs), slotNumber, timestamp);
560
+ break;
561
+ }
562
+ default:
563
+ {
564
+ const _ = action;
565
+ throw new Error(`Unknown slashing action type: ${action.type}`);
566
+ }
567
+ }
568
+ }
569
+ return true;
508
570
  }
509
571
  /**
510
572
  * Proposes a L2 block on L1.
@@ -556,7 +618,7 @@ export class SequencerPublisher {
556
618
  if (!request) {
557
619
  return;
558
620
  }
559
- // We issue the simulation against the rollup contract, so we need to account for the overhead of the multicall3
621
+ // We issued the simulation against the rollup contract, so we need to account for the overhead of the multicall3
560
622
  const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(request.gasUsed) * 64 / 63)));
561
623
  const logData = {
562
624
  ...pick(request, 'gasUsed', 'blockNumber'),
@@ -589,6 +651,57 @@ export class SequencerPublisher {
589
651
  }
590
652
  });
591
653
  }
654
+ async simulateAndEnqueueRequest(action, request, checkSuccess, slotNumber, timestamp) {
655
+ const logData = {
656
+ slotNumber,
657
+ timestamp,
658
+ gasLimit: undefined
659
+ };
660
+ let gasUsed;
661
+ this.log.debug(`Simulating ${action}`, logData);
662
+ try {
663
+ ({ gasUsed } = await this.l1TxUtils.simulate(request, {
664
+ time: timestamp
665
+ }, [], ErrorsAbi)); // TODO(palla/slash): Check the timestamp logic
666
+ this.log.verbose(`Simulation for ${action} succeeded`, {
667
+ ...logData,
668
+ request,
669
+ gasUsed
670
+ });
671
+ } catch (err) {
672
+ const viemError = formatViemError(err);
673
+ this.log.error(`Simulation for ${action} at ${slotNumber} failed`, viemError, logData);
674
+ return false;
675
+ }
676
+ // We issued the simulation against the rollup contract, so we need to account for the overhead of the multicall3
677
+ const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(gasUsed) * 64 / 63)));
678
+ logData.gasLimit = gasLimit;
679
+ this.log.debug(`Enqueuing ${action}`, logData);
680
+ this.addRequest({
681
+ action,
682
+ request,
683
+ gasConfig: {
684
+ gasLimit
685
+ },
686
+ lastValidL2Slot: slotNumber,
687
+ checkSuccess: (_req, result)=>{
688
+ const success = result && result.receipt && result.receipt.status === 'success' && checkSuccess(result.receipt);
689
+ if (!success) {
690
+ this.log.warn(`Action ${action} at ${slotNumber} failed`, {
691
+ ...result,
692
+ ...logData
693
+ });
694
+ } else {
695
+ this.log.info(`Action ${action} at ${slotNumber} succeeded`, {
696
+ ...result,
697
+ ...logData
698
+ });
699
+ }
700
+ return !!success;
701
+ }
702
+ });
703
+ return true;
704
+ }
592
705
  /**
593
706
  * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
594
707
  * Be warned, the call may return false even if the tx subsequently gets successfully mined.
@@ -728,7 +841,7 @@ export class SequencerPublisher {
728
841
  blobs: encodedData.blobs.map((b)=>b.data),
729
842
  kzg
730
843
  },
731
- checkSuccess: (request, result)=>{
844
+ checkSuccess: (_request, result)=>{
732
845
  if (!result) {
733
846
  return false;
734
847
  }
@@ -4,7 +4,7 @@ import { Fr } from '@aztec/foundation/fields';
4
4
  import { type DateProvider } from '@aztec/foundation/timer';
5
5
  import type { TypedEventEmitter } from '@aztec/foundation/types';
6
6
  import type { P2P } from '@aztec/p2p';
7
- import type { SlasherClient } from '@aztec/slasher';
7
+ import type { SlasherClientInterface } from '@aztec/slasher';
8
8
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
9
9
  import type { CommitteeAttestation, L2BlockSource, ValidateBlockResult } from '@aztec/stdlib/block';
10
10
  import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
@@ -14,7 +14,7 @@ import { Tx, type TxHash } from '@aztec/stdlib/tx';
14
14
  import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
15
15
  import type { ValidatorClient } from '@aztec/validator-client';
16
16
  import type { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
17
- import { type Action, type InvalidateBlockRequest, type SequencerPublisher } from '../publisher/sequencer-publisher.js';
17
+ import type { Action, InvalidateBlockRequest, SequencerPublisher } from '../publisher/sequencer-publisher.js';
18
18
  import type { SequencerConfig } from './config.js';
19
19
  import { SequencerTimetable } from './timetable.js';
20
20
  import { SequencerState, type SequencerStateWithSlot } from './utils.js';
@@ -64,7 +64,7 @@ export declare class Sequencer extends Sequencer_base {
64
64
  protected globalsBuilder: GlobalVariableBuilder;
65
65
  protected p2pClient: P2P;
66
66
  protected worldState: WorldStateSynchronizer;
67
- protected slasherClient: SlasherClient;
67
+ protected slasherClient: SlasherClientInterface | undefined;
68
68
  protected l2BlockSource: L2BlockSource;
69
69
  protected l1ToL2MessageSource: L1ToL2MessageSource;
70
70
  protected blockBuilder: IFullNodeBlockBuilder;
@@ -90,7 +90,7 @@ export declare class Sequencer extends Sequencer_base {
90
90
  protected timetable: SequencerTimetable;
91
91
  protected enforceTimeTable: boolean;
92
92
  constructor(publisher: SequencerPublisher, validatorClient: ValidatorClient | undefined, // During migration the validator client can be inactive
93
- globalsBuilder: GlobalVariableBuilder, p2pClient: P2P, worldState: WorldStateSynchronizer, slasherClient: SlasherClient, l2BlockSource: L2BlockSource, l1ToL2MessageSource: L1ToL2MessageSource, blockBuilder: IFullNodeBlockBuilder, l1Constants: SequencerRollupConstants, dateProvider: DateProvider, config?: SequencerConfig, telemetry?: TelemetryClient, log?: import("@aztec/aztec.js").Logger);
93
+ globalsBuilder: GlobalVariableBuilder, p2pClient: P2P, worldState: WorldStateSynchronizer, slasherClient: SlasherClientInterface | undefined, l2BlockSource: L2BlockSource, l1ToL2MessageSource: L1ToL2MessageSource, blockBuilder: IFullNodeBlockBuilder, l1Constants: SequencerRollupConstants, dateProvider: DateProvider, config?: SequencerConfig, telemetry?: TelemetryClient, log?: import("@aztec/aztec.js").Logger);
94
94
  get tracer(): Tracer;
95
95
  getValidatorAddresses(): EthAddress[] | undefined;
96
96
  getConfig(): SequencerConfig;
@@ -181,11 +181,12 @@ export declare class Sequencer extends Sequencer_base {
181
181
  */
182
182
  protected considerInvalidatingBlock(syncedTo: NonNullable<Awaited<ReturnType<Sequencer['getChainTip']>>>, currentSlot: bigint, ourValidatorAddresses: EthAddress[]): Promise<void>;
183
183
  private getSlotStartBuildTimestamp;
184
+ private getTxTimeoutForSlot;
184
185
  private getSecondsIntoSlot;
185
186
  get aztecSlotDuration(): number;
186
187
  get coinbase(): EthAddress;
187
188
  get feeRecipient(): AztecAddress;
188
189
  get maxL2BlockGas(): number | undefined;
189
- getSlasherClient(): SlasherClient;
190
+ getSlasherClient(): SlasherClientInterface | undefined;
190
191
  }
191
192
  //# sourceMappingURL=sequencer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
@@ -23,7 +23,6 @@ import { ContentCommitment, ProposedBlockHeader } from '@aztec/stdlib/tx';
23
23
  import { AttestationTimeoutError } from '@aztec/stdlib/validators';
24
24
  import { Attributes, L1Metrics, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
25
25
  import EventEmitter from 'node:events';
26
- import { SignalType } from '../publisher/sequencer-publisher.js';
27
26
  import { SequencerMetrics } from './metrics.js';
28
27
  import { SequencerTimetable, SequencerTooSlowError } from './timetable.js';
29
28
  import { SequencerState } from './utils.js';
@@ -73,8 +72,6 @@ export { SequencerState };
73
72
  this.l1Metrics = new L1Metrics(telemetry.getMeter('SequencerL1Metrics'), publisher.l1TxUtils.client, [
74
73
  publisher.getSenderAddress()
75
74
  ]);
76
- // Register the slasher on the publisher to fetch slashing payloads
77
- this.publisher.registerSlashPayloadGetter(this.slasherClient.getSlashPayload.bind(this.slasherClient));
78
75
  // Initialize config
79
76
  this.updateConfig(this.config);
80
77
  }
@@ -302,8 +299,10 @@ export { SequencerState };
302
299
  validatorAddresses
303
300
  });
304
301
  const newGlobalVariables = await this.globalsBuilder.buildGlobalVariables(newBlockNumber, this.coinbase, this._feeRecipient, slot);
305
- const enqueueGovernanceVotePromise = this.publisher.enqueueCastSignal(slot, newGlobalVariables.timestamp, SignalType.GOVERNANCE, proposerAddress, (msg)=>this.validatorClient.signWithAddress(proposerAddress, msg).then((s)=>s.toString()));
306
- const enqueueSlashingVotePromise = this.publisher.enqueueCastSignal(slot, newGlobalVariables.timestamp, SignalType.SLASHING, proposerAddress, (msg)=>this.validatorClient.signWithAddress(proposerAddress, msg).then((s)=>s.toString()));
302
+ const { timestamp } = newGlobalVariables;
303
+ const signerFn = (msg)=>this.validatorClient.signWithAddress(proposerAddress, msg).then((s)=>s.toString());
304
+ const enqueueGovernanceSignalPromise = this.publisher.enqueueGovernanceCastSignal(slot, timestamp, proposerAddress, signerFn);
305
+ const enqueueSlashingActionsPromise = this.slasherClient?.getProposerActions(slot)?.then((actions)=>this.publisher.enqueueSlashingActions(actions, slot, timestamp, proposerAddress, signerFn));
307
306
  if (invalidateBlock && !this.config.skipInvalidateBlockAsProposer) {
308
307
  this.publisher.enqueueInvalidateBlock(invalidateBlock);
309
308
  }
@@ -355,14 +354,14 @@ export { SequencerState };
355
354
  availableTxs: pendingTxCount
356
355
  });
357
356
  }
358
- await enqueueGovernanceVotePromise.catch((err)=>{
357
+ await enqueueGovernanceSignalPromise?.catch((err)=>{
359
358
  this.log.error(`Error enqueuing governance vote`, err, {
360
359
  blockNumber: newBlockNumber,
361
360
  slot
362
361
  });
363
362
  });
364
- await enqueueSlashingVotePromise.catch((err)=>{
365
- this.log.error(`Error enqueuing slashing vote`, err, {
363
+ await enqueueSlashingActionsPromise?.catch((err)=>{
364
+ this.log.error(`Error enqueuing slashing actions`, err, {
366
365
  blockNumber: newBlockNumber,
367
366
  slot
368
367
  });
@@ -567,11 +566,8 @@ export { SequencerState };
567
566
  */ async enqueuePublishL2Block(block, attestations, txHashes, invalidateBlock) {
568
567
  // Publishes new block to the network and awaits the tx to be mined
569
568
  this.setState(SequencerState.PUBLISHING_BLOCK, block.header.globalVariables.slotNumber.toBigInt());
570
- // Time out tx at the end of the slot
571
- const slot = block.header.globalVariables.slotNumber.toNumber();
572
- const txTimeoutAt = new Date((this.getSlotStartBuildTimestamp(slot) + this.aztecSlotDuration) * 1000);
573
569
  const enqueued = await this.publisher.enqueueProposeL2Block(block, attestations, txHashes, {
574
- txTimeoutAt,
570
+ txTimeoutAt: this.getTxTimeoutForSlot(block.slot),
575
571
  forcePendingBlockNumber: invalidateBlock?.forcePendingBlockNumber
576
572
  });
577
573
  if (!enqueued) {
@@ -675,6 +671,9 @@ export { SequencerState };
675
671
  getSlotStartBuildTimestamp(slotNumber) {
676
672
  return Number(this.l1Constants.l1GenesisTime) + Number(slotNumber) * this.l1Constants.slotDuration - this.l1Constants.ethereumSlotDuration;
677
673
  }
674
+ getTxTimeoutForSlot(slotNumber) {
675
+ return new Date((this.getSlotStartBuildTimestamp(slotNumber) + this.aztecSlotDuration) * 1000);
676
+ }
678
677
  getSecondsIntoSlot(slotNumber) {
679
678
  const slotStartTimestamp = this.getSlotStartBuildTimestamp(slotNumber);
680
679
  return Number((this.dateProvider.now() / 1000 - slotStartTimestamp).toFixed(3));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/sequencer-client",
3
- "version": "2.0.0-nightly.20250821",
3
+ "version": "2.0.0-nightly.20250823",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -26,37 +26,37 @@
26
26
  "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
27
27
  },
28
28
  "dependencies": {
29
- "@aztec/aztec.js": "2.0.0-nightly.20250821",
30
- "@aztec/bb-prover": "2.0.0-nightly.20250821",
31
- "@aztec/blob-lib": "2.0.0-nightly.20250821",
32
- "@aztec/blob-sink": "2.0.0-nightly.20250821",
33
- "@aztec/constants": "2.0.0-nightly.20250821",
34
- "@aztec/epoch-cache": "2.0.0-nightly.20250821",
35
- "@aztec/ethereum": "2.0.0-nightly.20250821",
36
- "@aztec/foundation": "2.0.0-nightly.20250821",
37
- "@aztec/l1-artifacts": "2.0.0-nightly.20250821",
38
- "@aztec/merkle-tree": "2.0.0-nightly.20250821",
39
- "@aztec/noir-acvm_js": "2.0.0-nightly.20250821",
40
- "@aztec/noir-contracts.js": "2.0.0-nightly.20250821",
41
- "@aztec/noir-protocol-circuits-types": "2.0.0-nightly.20250821",
42
- "@aztec/noir-types": "2.0.0-nightly.20250821",
43
- "@aztec/p2p": "2.0.0-nightly.20250821",
44
- "@aztec/protocol-contracts": "2.0.0-nightly.20250821",
45
- "@aztec/prover-client": "2.0.0-nightly.20250821",
46
- "@aztec/simulator": "2.0.0-nightly.20250821",
47
- "@aztec/slasher": "2.0.0-nightly.20250821",
48
- "@aztec/stdlib": "2.0.0-nightly.20250821",
49
- "@aztec/telemetry-client": "2.0.0-nightly.20250821",
50
- "@aztec/validator-client": "2.0.0-nightly.20250821",
51
- "@aztec/world-state": "2.0.0-nightly.20250821",
29
+ "@aztec/aztec.js": "2.0.0-nightly.20250823",
30
+ "@aztec/bb-prover": "2.0.0-nightly.20250823",
31
+ "@aztec/blob-lib": "2.0.0-nightly.20250823",
32
+ "@aztec/blob-sink": "2.0.0-nightly.20250823",
33
+ "@aztec/constants": "2.0.0-nightly.20250823",
34
+ "@aztec/epoch-cache": "2.0.0-nightly.20250823",
35
+ "@aztec/ethereum": "2.0.0-nightly.20250823",
36
+ "@aztec/foundation": "2.0.0-nightly.20250823",
37
+ "@aztec/l1-artifacts": "2.0.0-nightly.20250823",
38
+ "@aztec/merkle-tree": "2.0.0-nightly.20250823",
39
+ "@aztec/noir-acvm_js": "2.0.0-nightly.20250823",
40
+ "@aztec/noir-contracts.js": "2.0.0-nightly.20250823",
41
+ "@aztec/noir-protocol-circuits-types": "2.0.0-nightly.20250823",
42
+ "@aztec/noir-types": "2.0.0-nightly.20250823",
43
+ "@aztec/p2p": "2.0.0-nightly.20250823",
44
+ "@aztec/protocol-contracts": "2.0.0-nightly.20250823",
45
+ "@aztec/prover-client": "2.0.0-nightly.20250823",
46
+ "@aztec/simulator": "2.0.0-nightly.20250823",
47
+ "@aztec/slasher": "2.0.0-nightly.20250823",
48
+ "@aztec/stdlib": "2.0.0-nightly.20250823",
49
+ "@aztec/telemetry-client": "2.0.0-nightly.20250823",
50
+ "@aztec/validator-client": "2.0.0-nightly.20250823",
51
+ "@aztec/world-state": "2.0.0-nightly.20250823",
52
52
  "lodash.chunk": "^4.2.0",
53
53
  "lodash.pick": "^4.4.0",
54
54
  "tslib": "^2.4.0",
55
55
  "viem": "2.23.7"
56
56
  },
57
57
  "devDependencies": {
58
- "@aztec/archiver": "2.0.0-nightly.20250821",
59
- "@aztec/kv-store": "2.0.0-nightly.20250821",
58
+ "@aztec/archiver": "2.0.0-nightly.20250823",
59
+ "@aztec/kv-store": "2.0.0-nightly.20250823",
60
60
  "@jest/globals": "^30.0.0",
61
61
  "@types/jest": "^30.0.0",
62
62
  "@types/lodash.chunk": "^4.2.7",
@@ -3,7 +3,6 @@ import { EpochCache } from '@aztec/epoch-cache';
3
3
  import {
4
4
  GovernanceProposerContract,
5
5
  RollupContract,
6
- SlashingProposerContract,
7
6
  createEthereumChain,
8
7
  createExtendedL1Client,
9
8
  isAnvilTestChain,
@@ -13,10 +12,11 @@ import { EthAddress } from '@aztec/foundation/eth-address';
13
12
  import { createLogger } from '@aztec/foundation/log';
14
13
  import type { DateProvider } from '@aztec/foundation/timer';
15
14
  import type { P2P } from '@aztec/p2p';
16
- import type { SlasherClient } from '@aztec/slasher';
15
+ import type { SlasherClientInterface } from '@aztec/slasher';
17
16
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
18
17
  import type { L2BlockSource } from '@aztec/stdlib/block';
19
18
  import type { IFullNodeBlockBuilder, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
19
+ import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
20
20
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
21
21
  import type { TelemetryClient } from '@aztec/telemetry-client';
22
22
  import type { ValidatorClient } from '@aztec/validator-client';
@@ -53,7 +53,7 @@ export class SequencerClient {
53
53
  validatorClient: ValidatorClient | undefined; // allowed to be undefined while we migrate
54
54
  p2pClient: P2P;
55
55
  worldStateSynchronizer: WorldStateSynchronizer;
56
- slasherClient: SlasherClient;
56
+ slasherClient: SlasherClientInterface | undefined;
57
57
  blockBuilder: IFullNodeBlockBuilder;
58
58
  l2BlockSource: L2BlockSource;
59
59
  l1ToL2MessageSource: L1ToL2MessageSource;
@@ -90,8 +90,7 @@ export class SequencerClient {
90
90
  l1Client,
91
91
  config.l1Contracts.governanceProposerAddress.toString(),
92
92
  );
93
- const slashingProposerAddress = await rollupContract.getSlashingProposerAddress();
94
- const slashingProposerContract = new SlashingProposerContract(l1Client, slashingProposerAddress.toString());
93
+ const slashingProposerContract = await rollupContract.getSlashingProposer();
95
94
  const epochCache =
96
95
  deps.epochCache ??
97
96
  (await EpochCache.create(
@@ -107,6 +106,11 @@ export class SequencerClient {
107
106
  { dateProvider: deps.dateProvider },
108
107
  ));
109
108
 
109
+ const slashFactoryContract = new SlashFactoryContract(
110
+ l1Client,
111
+ config.l1Contracts.slashFactoryAddress?.toString() ?? EthAddress.ZERO.toString(),
112
+ );
113
+
110
114
  const publisher =
111
115
  deps.publisher ??
112
116
  new SequencerPublisher(config, {
@@ -117,6 +121,7 @@ export class SequencerClient {
117
121
  epochCache,
118
122
  governanceProposerContract,
119
123
  slashingProposerContract,
124
+ slashFactoryContract,
120
125
  dateProvider: deps.dateProvider,
121
126
  });
122
127
  const globalsBuilder = new GlobalVariableBuilder(config);
@@ -3,6 +3,7 @@ import { Blob } from '@aztec/blob-lib';
3
3
  import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
4
4
  import type { EpochCache } from '@aztec/epoch-cache';
5
5
  import {
6
+ type EmpireSlashingProposerContract,
6
7
  FormattedViemError,
7
8
  type GasPrice,
8
9
  type GovernanceProposerContract,
@@ -14,7 +15,7 @@ import {
14
15
  MULTI_CALL_3_ADDRESS,
15
16
  Multicall3,
16
17
  RollupContract,
17
- type SlashingProposerContract,
18
+ type TallySlashingProposerContract,
18
19
  type TransactionStats,
19
20
  type ViemCommitteeAttestations,
20
21
  type ViemHeader,
@@ -28,9 +29,12 @@ import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
28
29
  import { EthAddress } from '@aztec/foundation/eth-address';
29
30
  import type { Fr } from '@aztec/foundation/fields';
30
31
  import { createLogger } from '@aztec/foundation/log';
32
+ import { bufferToHex } from '@aztec/foundation/string';
31
33
  import { DateProvider, Timer } from '@aztec/foundation/timer';
32
34
  import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
35
+ import { type ProposerSlashAction, encodeSlashConsensusVotes } from '@aztec/slasher';
33
36
  import { CommitteeAttestation, type ValidateBlockResult } from '@aztec/stdlib/block';
37
+ import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
34
38
  import { ConsensusPayload, SignatureDomainSeparator, getHashedSignaturePayload } from '@aztec/stdlib/p2p';
35
39
  import type { L1PublishBlockStats } from '@aztec/stdlib/stats';
36
40
  import { type ProposedBlockHeader, StateReference, TxHash } from '@aztec/stdlib/tx';
@@ -63,18 +67,20 @@ export enum SignalType {
63
67
  SLASHING,
64
68
  }
65
69
 
66
- type GetSlashPayloadCallBack = (slotNumber: bigint) => Promise<EthAddress | undefined>;
67
-
68
70
  const Actions = [
69
71
  'propose',
70
72
  'governance-signal',
71
- 'slashing-signal',
73
+ 'empire-slashing-signal',
74
+ 'create-empire-payload',
75
+ 'execute-empire-payload',
76
+ 'vote-offenses',
77
+ 'execute-slash',
72
78
  'invalidate-by-invalid-attestation',
73
79
  'invalidate-by-insufficient-attestations',
74
80
  ] as const;
75
81
  export type Action = (typeof Actions)[number];
76
82
 
77
- // Sorting for actions such that invalidations go first, then proposals, and last votes
83
+ // Sorting for actions such that invalidations go before proposals, and proposals go before votes
78
84
  const compareActions = (a: Action, b: Action) => Actions.indexOf(b) - Actions.indexOf(a);
79
85
 
80
86
  export type InvalidateBlockRequest = {
@@ -106,7 +112,7 @@ export class SequencerPublisher {
106
112
  private governancePayload: EthAddress = EthAddress.ZERO;
107
113
 
108
114
  protected slashingLog = createLogger('sequencer:publisher:slashing');
109
- private getSlashPayload?: GetSlashPayloadCallBack = undefined;
115
+ protected slashingProposerAddress?: EthAddress;
110
116
 
111
117
  private myLastSignals: Record<SignalType, bigint> = {
112
118
  [SignalType.GOVERNANCE]: 0n,
@@ -131,7 +137,8 @@ export class SequencerPublisher {
131
137
  public l1TxUtils: L1TxUtilsWithBlobs;
132
138
  public rollupContract: RollupContract;
133
139
  public govProposerContract: GovernanceProposerContract;
134
- public slashingProposerContract: SlashingProposerContract;
140
+ public slashingProposerContract: EmpireSlashingProposerContract | TallySlashingProposerContract;
141
+ public slashFactoryContract: SlashFactoryContract;
135
142
 
136
143
  protected requests: RequestWithExpiry[] = [];
137
144
 
@@ -142,8 +149,9 @@ export class SequencerPublisher {
142
149
  blobSinkClient?: BlobSinkClientInterface;
143
150
  l1TxUtils: L1TxUtilsWithBlobs;
144
151
  rollupContract: RollupContract;
145
- slashingProposerContract: SlashingProposerContract;
152
+ slashingProposerContract: EmpireSlashingProposerContract | TallySlashingProposerContract;
146
153
  governanceProposerContract: GovernanceProposerContract;
154
+ slashFactoryContract: SlashFactoryContract;
147
155
  epochCache: EpochCache;
148
156
  dateProvider: DateProvider;
149
157
  },
@@ -168,16 +176,13 @@ export class SequencerPublisher {
168
176
  const newSlashingProposer = await this.rollupContract.getSlashingProposer();
169
177
  this.slashingProposerContract = newSlashingProposer;
170
178
  });
179
+ this.slashFactoryContract = deps.slashFactoryContract;
171
180
  }
172
181
 
173
182
  public getRollupContract(): RollupContract {
174
183
  return this.rollupContract;
175
184
  }
176
185
 
177
- public registerSlashPayloadGetter(callback: GetSlashPayloadCallBack) {
178
- this.getSlashPayload = callback;
179
- }
180
-
181
186
  public getSenderAddress() {
182
187
  return EthAddress.fromString(this.l1TxUtils.getSenderAddress());
183
188
  }
@@ -554,7 +559,7 @@ export class SequencerPublisher {
554
559
  const cachedLastVote = this.myLastSignals[signalType];
555
560
  this.myLastSignals[signalType] = slotNumber;
556
561
 
557
- const action = signalType === SignalType.GOVERNANCE ? 'governance-signal' : 'slashing-signal';
562
+ const action = signalType === SignalType.GOVERNANCE ? 'governance-signal' : 'empire-slashing-signal';
558
563
 
559
564
  const request = await base.createSignalRequestWithSignature(
560
565
  payload.toString(),
@@ -574,10 +579,11 @@ export class SequencerPublisher {
574
579
  await this.l1TxUtils.simulate(request, { time: timestamp }, [], ErrorsAbi);
575
580
  this.log.debug(`Simulation for ${action} at slot ${slotNumber} succeeded`, { request });
576
581
  } catch (err) {
577
- this.log.warn(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, err);
582
+ this.log.error(`Failed simulation for ${action} at slot ${slotNumber} (enqueuing the action anyway)`, err);
578
583
  // Yes, we enqueue the request anyway, in case there was a bug with the simulation itself
579
584
  }
580
585
 
586
+ // TODO(palla/slash): All votes (governance and slashing) should txTimeoutAt at the end of the slot.
581
587
  this.addRequest({
582
588
  gasConfig: { gasLimit: SequencerPublisher.VOTE_GAS_GUESS },
583
589
  action,
@@ -610,48 +616,150 @@ export class SequencerPublisher {
610
616
  return true;
611
617
  }
612
618
 
613
- private async getSignalConfig(
614
- slotNumber: bigint,
615
- signalType: SignalType,
616
- ): Promise<{ payload: EthAddress; base: IEmpireBase } | undefined> {
617
- if (signalType === SignalType.GOVERNANCE) {
618
- return { payload: this.governancePayload, base: this.govProposerContract };
619
- } else if (signalType === SignalType.SLASHING) {
620
- if (!this.getSlashPayload) {
621
- return undefined;
622
- }
623
- const slashPayload = await this.getSlashPayload(slotNumber);
624
- if (!slashPayload) {
625
- return undefined;
626
- }
627
- this.log.info(`Slash payload: ${slashPayload}`);
628
- return { payload: slashPayload, base: this.slashingProposerContract };
629
- } else {
630
- const _: never = signalType;
631
- throw new Error('Unreachable: Invalid signal type');
632
- }
633
- }
634
-
635
619
  /**
636
- * Enqueues a castSignal transaction to cast a signal for a given slot number.
620
+ * Enqueues a governance castSignal transaction to cast a signal for a given slot number.
637
621
  * @param slotNumber - The slot number to cast a signal for.
638
622
  * @param timestamp - The timestamp of the slot to cast a signal for.
639
- * @param signalType - The type of signal to cast.
640
623
  * @returns True if the signal was successfully enqueued, false otherwise.
641
624
  */
642
- public async enqueueCastSignal(
625
+ public enqueueGovernanceCastSignal(
626
+ slotNumber: bigint,
627
+ timestamp: bigint,
628
+ signerAddress: EthAddress,
629
+ signer: (msg: TypedDataDefinition) => Promise<`0x${string}`>,
630
+ ): Promise<boolean> {
631
+ return this.enqueueCastSignalHelper(
632
+ slotNumber,
633
+ timestamp,
634
+ SignalType.GOVERNANCE,
635
+ this.governancePayload,
636
+ this.govProposerContract,
637
+ signerAddress,
638
+ signer,
639
+ );
640
+ }
641
+
642
+ /** Enqueues all slashing actions as returned by the slasher client. */
643
+ public async enqueueSlashingActions(
644
+ actions: ProposerSlashAction[],
643
645
  slotNumber: bigint,
644
646
  timestamp: bigint,
645
- signalType: SignalType,
646
647
  signerAddress: EthAddress,
647
648
  signer: (msg: TypedDataDefinition) => Promise<`0x${string}`>,
648
649
  ): Promise<boolean> {
649
- const signalConfig = await this.getSignalConfig(slotNumber, signalType);
650
- if (!signalConfig) {
650
+ if (actions.length === 0) {
651
+ this.log.debug(`No slashing actions to enqueue for slot ${slotNumber}`);
651
652
  return false;
652
653
  }
653
- const { payload, base } = signalConfig;
654
- return this.enqueueCastSignalHelper(slotNumber, timestamp, signalType, payload, base, signerAddress, signer);
654
+
655
+ for (const action of actions) {
656
+ switch (action.type) {
657
+ case 'vote-empire-payload': {
658
+ if (this.slashingProposerContract.type !== 'empire') {
659
+ this.log.error('Cannot vote for empire payload on non-empire slashing contract');
660
+ break;
661
+ }
662
+ this.log.debug(`Enqueuing slashing vote for payload ${action.payload} at slot ${slotNumber}`, {
663
+ signerAddress,
664
+ });
665
+ await this.enqueueCastSignalHelper(
666
+ slotNumber,
667
+ timestamp,
668
+ SignalType.SLASHING,
669
+ action.payload,
670
+ this.slashingProposerContract,
671
+ signerAddress,
672
+ signer,
673
+ );
674
+ break;
675
+ }
676
+
677
+ case 'create-empire-payload': {
678
+ this.log.debug(`Enqueuing slashing create payload at slot ${slotNumber}`, { slotNumber, signerAddress });
679
+ const request = this.slashFactoryContract.buildCreatePayloadRequest(action.data);
680
+ await this.simulateAndEnqueueRequest(
681
+ 'create-empire-payload',
682
+ request,
683
+ (receipt: TransactionReceipt) =>
684
+ !!this.slashFactoryContract.tryExtractSlashPayloadCreatedEvent(receipt.logs),
685
+ slotNumber,
686
+ timestamp,
687
+ );
688
+ break;
689
+ }
690
+
691
+ case 'execute-empire-payload': {
692
+ this.log.debug(`Enqueuing slashing execute payload at slot ${slotNumber}`, { slotNumber, signerAddress });
693
+ if (this.slashingProposerContract.type !== 'empire') {
694
+ this.log.error('Cannot execute slashing payload on non-empire slashing contract');
695
+ return false;
696
+ }
697
+ const empireSlashingProposer = this.slashingProposerContract as EmpireSlashingProposerContract;
698
+ const request = empireSlashingProposer.buildExecuteRoundRequest(action.round);
699
+ await this.simulateAndEnqueueRequest(
700
+ 'execute-empire-payload',
701
+ request,
702
+ (receipt: TransactionReceipt) => !!empireSlashingProposer.tryExtractPayloadSubmittedEvent(receipt.logs),
703
+ slotNumber,
704
+ timestamp,
705
+ );
706
+ break;
707
+ }
708
+
709
+ case 'vote-offenses': {
710
+ this.log.debug(`Enqueuing slashing vote for ${action.votes.length} votes at slot ${slotNumber}`, {
711
+ slotNumber,
712
+ round: action.round,
713
+ votesCount: action.votes.length,
714
+ signerAddress,
715
+ });
716
+ if (this.slashingProposerContract.type !== 'tally') {
717
+ this.log.error('Cannot vote for slashing offenses on non-tally slashing contract');
718
+ return false;
719
+ }
720
+ const tallySlashingProposer = this.slashingProposerContract as TallySlashingProposerContract;
721
+ const votes = bufferToHex(encodeSlashConsensusVotes(action.votes));
722
+ const request = await tallySlashingProposer.buildVoteRequestFromSigner(votes, slotNumber, signer);
723
+ await this.simulateAndEnqueueRequest(
724
+ 'vote-offenses',
725
+ request,
726
+ (receipt: TransactionReceipt) => !!tallySlashingProposer.tryExtractVoteCastEvent(receipt.logs),
727
+ slotNumber,
728
+ timestamp,
729
+ );
730
+ break;
731
+ }
732
+
733
+ case 'execute-slash': {
734
+ this.log.debug(`Enqueuing slash execution for round ${action.round} at slot ${slotNumber}`, {
735
+ slotNumber,
736
+ round: action.round,
737
+ signerAddress,
738
+ });
739
+ if (this.slashingProposerContract.type !== 'tally') {
740
+ this.log.error('Cannot execute slashing offenses on non-tally slashing contract');
741
+ return false;
742
+ }
743
+ const tallySlashingProposer = this.slashingProposerContract as TallySlashingProposerContract;
744
+ const request = tallySlashingProposer.buildExecuteRoundRequest(action.round, action.committees);
745
+ await this.simulateAndEnqueueRequest(
746
+ 'execute-slash',
747
+ request,
748
+ (receipt: TransactionReceipt) => !!tallySlashingProposer.tryExtractRoundExecutedEvent(receipt.logs),
749
+ slotNumber,
750
+ timestamp,
751
+ );
752
+ break;
753
+ }
754
+
755
+ default: {
756
+ const _: never = action;
757
+ throw new Error(`Unknown slashing action type: ${(action as ProposerSlashAction).type}`);
758
+ }
759
+ }
760
+ }
761
+
762
+ return true;
655
763
  }
656
764
 
657
765
  /**
@@ -711,7 +819,7 @@ export class SequencerPublisher {
711
819
  return;
712
820
  }
713
821
 
714
- // We issue the simulation against the rollup contract, so we need to account for the overhead of the multicall3
822
+ // We issued the simulation against the rollup contract, so we need to account for the overhead of the multicall3
715
823
  const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil((Number(request.gasUsed) * 64) / 63)));
716
824
 
717
825
  const logData = { ...pick(request, 'gasUsed', 'blockNumber'), gasLimit, opts };
@@ -737,6 +845,49 @@ export class SequencerPublisher {
737
845
  });
738
846
  }
739
847
 
848
+ private async simulateAndEnqueueRequest(
849
+ action: RequestWithExpiry['action'],
850
+ request: L1TxRequest,
851
+ checkSuccess: (receipt: TransactionReceipt) => boolean | undefined,
852
+ slotNumber: bigint,
853
+ timestamp: bigint,
854
+ ) {
855
+ const logData = { slotNumber, timestamp, gasLimit: undefined as bigint | undefined };
856
+ let gasUsed: bigint;
857
+
858
+ this.log.debug(`Simulating ${action}`, logData);
859
+ try {
860
+ ({ gasUsed } = await this.l1TxUtils.simulate(request, { time: timestamp }, [], ErrorsAbi)); // TODO(palla/slash): Check the timestamp logic
861
+ this.log.verbose(`Simulation for ${action} succeeded`, { ...logData, request, gasUsed });
862
+ } catch (err) {
863
+ const viemError = formatViemError(err);
864
+ this.log.error(`Simulation for ${action} at ${slotNumber} failed`, viemError, logData);
865
+ return false;
866
+ }
867
+
868
+ // We issued the simulation against the rollup contract, so we need to account for the overhead of the multicall3
869
+ const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil((Number(gasUsed) * 64) / 63)));
870
+ logData.gasLimit = gasLimit;
871
+
872
+ this.log.debug(`Enqueuing ${action}`, logData);
873
+ this.addRequest({
874
+ action,
875
+ request,
876
+ gasConfig: { gasLimit },
877
+ lastValidL2Slot: slotNumber,
878
+ checkSuccess: (_req, result) => {
879
+ const success = result && result.receipt && result.receipt.status === 'success' && checkSuccess(result.receipt);
880
+ if (!success) {
881
+ this.log.warn(`Action ${action} at ${slotNumber} failed`, { ...result, ...logData });
882
+ } else {
883
+ this.log.info(`Action ${action} at ${slotNumber} succeeded`, { ...result, ...logData });
884
+ }
885
+ return !!success;
886
+ },
887
+ });
888
+ return true;
889
+ }
890
+
740
891
  /**
741
892
  * Calling `interrupt` will cause any in progress call to `publishRollup` to return `false` asap.
742
893
  * Be warned, the call may return false even if the tx subsequently gets successfully mined.
@@ -928,7 +1079,7 @@ export class SequencerPublisher {
928
1079
  blobs: encodedData.blobs.map(b => b.data),
929
1080
  kzg,
930
1081
  },
931
- checkSuccess: (request, result) => {
1082
+ checkSuccess: (_request, result) => {
932
1083
  if (!result) {
933
1084
  return false;
934
1085
  }
@@ -9,7 +9,7 @@ import { RunningPromise } from '@aztec/foundation/running-promise';
9
9
  import { type DateProvider, Timer } from '@aztec/foundation/timer';
10
10
  import type { TypedEventEmitter } from '@aztec/foundation/types';
11
11
  import type { P2P } from '@aztec/p2p';
12
- import type { SlasherClient } from '@aztec/slasher';
12
+ import type { SlasherClientInterface } from '@aztec/slasher';
13
13
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
14
14
  import type { CommitteeAttestation, L2BlockSource, ValidateBlockResult } from '@aztec/stdlib/block';
15
15
  import { type L1RollupConstants, getSlotAtTimestamp } from '@aztec/stdlib/epoch-helpers';
@@ -46,14 +46,10 @@ import {
46
46
  import type { ValidatorClient } from '@aztec/validator-client';
47
47
 
48
48
  import EventEmitter from 'node:events';
49
+ import type { TypedDataDefinition } from 'viem';
49
50
 
50
51
  import type { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
51
- import {
52
- type Action,
53
- type InvalidateBlockRequest,
54
- type SequencerPublisher,
55
- SignalType,
56
- } from '../publisher/sequencer-publisher.js';
52
+ import type { Action, InvalidateBlockRequest, SequencerPublisher } from '../publisher/sequencer-publisher.js';
57
53
  import type { SequencerConfig } from './config.js';
58
54
  import { SequencerMetrics } from './metrics.js';
59
55
  import { SequencerTimetable, SequencerTooSlowError } from './timetable.js';
@@ -117,7 +113,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
117
113
  protected globalsBuilder: GlobalVariableBuilder,
118
114
  protected p2pClient: P2P,
119
115
  protected worldState: WorldStateSynchronizer,
120
- protected slasherClient: SlasherClient,
116
+ protected slasherClient: SlasherClientInterface | undefined,
121
117
  protected l2BlockSource: L2BlockSource,
122
118
  protected l1ToL2MessageSource: L1ToL2MessageSource,
123
119
  protected blockBuilder: IFullNodeBlockBuilder,
@@ -142,9 +138,6 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
142
138
  [publisher.getSenderAddress()],
143
139
  );
144
140
 
145
- // Register the slasher on the publisher to fetch slashing payloads
146
- this.publisher.registerSlashPayloadGetter(this.slasherClient.getSlashPayload.bind(this.slasherClient));
147
-
148
141
  // Initialize config
149
142
  this.updateConfig(this.config);
150
143
  }
@@ -415,22 +408,21 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
415
408
  slot,
416
409
  );
417
410
 
418
- const enqueueGovernanceVotePromise = this.publisher.enqueueCastSignal(
419
- slot,
420
- newGlobalVariables.timestamp,
421
- SignalType.GOVERNANCE,
422
- proposerAddress,
423
- msg => this.validatorClient!.signWithAddress(proposerAddress, msg).then(s => s.toString()),
424
- );
411
+ const { timestamp } = newGlobalVariables;
412
+ const signerFn = (msg: TypedDataDefinition) =>
413
+ this.validatorClient!.signWithAddress(proposerAddress, msg).then(s => s.toString());
425
414
 
426
- const enqueueSlashingVotePromise = this.publisher.enqueueCastSignal(
415
+ const enqueueGovernanceSignalPromise = this.publisher.enqueueGovernanceCastSignal(
427
416
  slot,
428
- newGlobalVariables.timestamp,
429
- SignalType.SLASHING,
417
+ timestamp,
430
418
  proposerAddress,
431
- msg => this.validatorClient!.signWithAddress(proposerAddress, msg).then(s => s.toString()),
419
+ signerFn,
432
420
  );
433
421
 
422
+ const enqueueSlashingActionsPromise = this.slasherClient
423
+ ?.getProposerActions(slot)
424
+ ?.then(actions => this.publisher.enqueueSlashingActions(actions, slot, timestamp, proposerAddress, signerFn));
425
+
434
426
  if (invalidateBlock && !this.config.skipInvalidateBlockAsProposer) {
435
427
  this.publisher.enqueueInvalidateBlock(invalidateBlock);
436
428
  }
@@ -484,11 +476,11 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
484
476
  this.emit('tx-count-check-failed', { minTxs: this.minTxsPerBlock, availableTxs: pendingTxCount });
485
477
  }
486
478
 
487
- await enqueueGovernanceVotePromise.catch(err => {
479
+ await enqueueGovernanceSignalPromise?.catch(err => {
488
480
  this.log.error(`Error enqueuing governance vote`, err, { blockNumber: newBlockNumber, slot });
489
481
  });
490
- await enqueueSlashingVotePromise.catch(err => {
491
- this.log.error(`Error enqueuing slashing vote`, err, { blockNumber: newBlockNumber, slot });
482
+ await enqueueSlashingActionsPromise?.catch(err => {
483
+ this.log.error(`Error enqueuing slashing actions`, err, { blockNumber: newBlockNumber, slot });
492
484
  });
493
485
 
494
486
  const l1Response = await this.publisher.sendRequests();
@@ -781,12 +773,8 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
781
773
  // Publishes new block to the network and awaits the tx to be mined
782
774
  this.setState(SequencerState.PUBLISHING_BLOCK, block.header.globalVariables.slotNumber.toBigInt());
783
775
 
784
- // Time out tx at the end of the slot
785
- const slot = block.header.globalVariables.slotNumber.toNumber();
786
- const txTimeoutAt = new Date((this.getSlotStartBuildTimestamp(slot) + this.aztecSlotDuration) * 1000);
787
-
788
776
  const enqueued = await this.publisher.enqueueProposeL2Block(block, attestations, txHashes, {
789
- txTimeoutAt,
777
+ txTimeoutAt: this.getTxTimeoutForSlot(block.slot),
790
778
  forcePendingBlockNumber: invalidateBlock?.forcePendingBlockNumber,
791
779
  });
792
780
 
@@ -942,6 +930,10 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
942
930
  );
943
931
  }
944
932
 
933
+ private getTxTimeoutForSlot(slotNumber: number | bigint): Date {
934
+ return new Date((this.getSlotStartBuildTimestamp(slotNumber) + this.aztecSlotDuration) * 1000);
935
+ }
936
+
945
937
  private getSecondsIntoSlot(slotNumber: number | bigint): number {
946
938
  const slotStartTimestamp = this.getSlotStartBuildTimestamp(slotNumber);
947
939
  return Number((this.dateProvider.now() / 1000 - slotStartTimestamp).toFixed(3));
@@ -967,7 +959,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
967
959
  return this.config.maxL2BlockGas;
968
960
  }
969
961
 
970
- public getSlasherClient(): SlasherClient {
962
+ public getSlasherClient(): SlasherClientInterface | undefined {
971
963
  return this.slasherClient;
972
964
  }
973
965
  }