@aztec/stdlib 2.0.0-nightly.20250902 → 2.0.0-nightly.20250903

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.
@@ -24,8 +24,9 @@ export declare function getPenaltyForOffense(offense: OffenseType, config: Pick<
24
24
  export declare function getTimeUnitForOffense(offense: OffenseType): 'epoch' | 'slot';
25
25
  /** Returns the slot for a given offense. If the offense references an epoch, returns the first slot of the epoch. */
26
26
  export declare function getSlotForOffense(offense: Pick<Offense, 'epochOrSlot' | 'offenseType'>, constants: Pick<L1RollupConstants, 'epochDuration'>): bigint;
27
- /** Returns the epoch for a given offense. */
27
+ /** Returns the epoch for a given offense. If the offense type or epoch is not defined, returns undefined. */
28
28
  export declare function getEpochForOffense(offense: Pick<Offense, 'epochOrSlot' | 'offenseType'>, constants: Pick<L1RollupConstants, 'epochDuration'>): bigint;
29
+ export declare function getEpochForOffense(offense: Partial<Pick<Offense, 'epochOrSlot' | 'offenseType'>>, constants: Pick<L1RollupConstants, 'epochDuration'>): bigint | undefined;
29
30
  /** Returns the slashing round in which a given offense occurred. */
30
31
  export declare function getRoundForOffense(offense: Pick<Offense, 'epochOrSlot' | 'offenseType'>, constants: {
31
32
  slashingRoundSize: number;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/slashing/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAwC,MAAM,2BAA2B,CAAC;AACzG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,KAAK,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,4FAA4F;AAC5F,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAKvC;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC9D,CAAC,MAAM,EAAE,MAAM,CAAC,CAKlB;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,EAAE,CAUV;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,IAAI,CACV,aAAa,EACX,uCAAuC,GACvC,qCAAqC,GACrC,mBAAmB,GACnB,6BAA6B,GAC7B,qBAAqB,GACrB,wBAAwB,GACxB,wCAAwC,CAC3C,UAuBF;AAED,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,GAAG,MAAM,CAiB5E;AAED,qHAAqH;AACrH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,EACrD,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,GAClD,MAAM,CAGR;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,EACrD,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,GAClD,MAAM,CAGR;AAED,oEAAoE;AACpE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,EACrD,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,CAGR"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/slashing/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAwC,MAAM,2BAA2B,CAAC;AACzG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,KAAK,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvD,4FAA4F;AAC5F,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAKvC;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC9D,CAAC,MAAM,EAAE,MAAM,CAAC,CAKlB;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,EAAE,CAUV;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,IAAI,CACV,aAAa,EACX,uCAAuC,GACvC,qCAAqC,GACrC,mBAAmB,GACnB,6BAA6B,GAC7B,qBAAqB,GACrB,wBAAwB,GACxB,wCAAwC,CAC3C,UAuBF;AAED,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,GAAG,MAAM,CAiB5E;AAED,qHAAqH;AACrH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,EACrD,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,GAClD,MAAM,CAGR;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,EACrD,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,GAClD,MAAM,CAAC;AACV,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,CAAC,EAC9D,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,GAClD,MAAM,GAAG,SAAS,CAAC;AAYtB,oEAAoE;AACpE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAAC,EACrD,SAAS,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,CAGR"}
@@ -76,8 +76,11 @@ import { OffenseType } from './types.js';
76
76
  const { epochOrSlot, offenseType } = offense;
77
77
  return getTimeUnitForOffense(offenseType) === 'epoch' ? epochOrSlot * BigInt(constants.epochDuration) : epochOrSlot;
78
78
  }
79
- /** Returns the epoch for a given offense. */ export function getEpochForOffense(offense, constants) {
79
+ export function getEpochForOffense(offense, constants) {
80
80
  const { epochOrSlot, offenseType } = offense;
81
+ if (epochOrSlot === undefined || offenseType === undefined) {
82
+ return undefined;
83
+ }
81
84
  return getTimeUnitForOffense(offenseType) === 'epoch' ? epochOrSlot : epochOrSlot / BigInt(constants.epochDuration);
82
85
  }
83
86
  /** Returns the slashing round in which a given offense occurred. */ export function getRoundForOffense(offense, constants) {
@@ -1,14 +1,17 @@
1
1
  import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import type { PartialBy } from '@aztec/foundation/types';
2
3
  import type { Offense, ValidatorSlashVote } from './types.js';
3
4
  /**
4
5
  * Creates a consensus-slash vote for a given set of committees based on a set of Offenses
5
6
  * @param offenses - Array of offenses to consider
6
7
  * @param committees - Array of committees (each containing array of validator addresses)
8
+ * @param epochsForCommittees - Array of epochs corresponding to each committee
7
9
  * @param settings - Settings including slashingAmounts and optional validator override lists
8
10
  * @returns Array of ValidatorSlashVote, where each vote is how many slash units the validator in that position should be slashed
9
11
  */
10
- export declare function getSlashConsensusVotesFromOffenses(offenses: Pick<Offense, 'validator' | 'amount'>[], committees: EthAddress[][], settings: {
12
+ export declare function getSlashConsensusVotesFromOffenses(offenses: PartialBy<Offense, 'epochOrSlot'>[], committees: EthAddress[][], epochsForCommittees: bigint[], settings: {
11
13
  slashingAmounts: [bigint, bigint, bigint];
14
+ epochDuration: number;
12
15
  }): ValidatorSlashVote[];
13
16
  /**
14
17
  * Encodes a set of slash votes into a Buffer for use in a consensus slashing vote transaction.
@@ -1 +1 @@
1
- {"version":3,"file":"tally.d.ts","sourceRoot":"","sources":["../../src/slashing/tally.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,CAAC,EAAE,EACjD,UAAU,EAAE,UAAU,EAAE,EAAE,EAC1B,QAAQ,EAAE;IACR,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAC3C,GACA,kBAAkB,EAAE,CAuBtB;AAeD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAe7E"}
1
+ {"version":3,"file":"tally.d.ts","sourceRoot":"","sources":["../../src/slashing/tally.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,EAC7C,UAAU,EAAE,UAAU,EAAE,EAAE,EAC1B,mBAAmB,EAAE,MAAM,EAAE,EAC7B,QAAQ,EAAE;IACR,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,aAAa,EAAE,MAAM,CAAC;CACvB,GACA,kBAAkB,EAAE,CA2BtB;AAeD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAe7E"}
@@ -1,26 +1,29 @@
1
1
  import { sumBigint } from '@aztec/foundation/bigint';
2
+ import { getEpochForOffense } from './helpers.js';
2
3
  /**
3
4
  * Creates a consensus-slash vote for a given set of committees based on a set of Offenses
4
5
  * @param offenses - Array of offenses to consider
5
6
  * @param committees - Array of committees (each containing array of validator addresses)
7
+ * @param epochsForCommittees - Array of epochs corresponding to each committee
6
8
  * @param settings - Settings including slashingAmounts and optional validator override lists
7
9
  * @returns Array of ValidatorSlashVote, where each vote is how many slash units the validator in that position should be slashed
8
- */ export function getSlashConsensusVotesFromOffenses(offenses, committees, settings) {
10
+ */ export function getSlashConsensusVotesFromOffenses(offenses, committees, epochsForCommittees, settings) {
9
11
  const { slashingAmounts } = settings;
10
- const slashedSet = new Set();
11
- const votes = committees.flatMap((committee)=>committee.map((validator)=>{
12
- const validatorStr = validator.toString();
13
- // If already voted for slashing this validator, skip
14
- if (slashedSet.has(validatorStr)) {
15
- return 0;
16
- }
17
- // Normal offense-based slashing logic
18
- const validatorOffenses = offenses.filter((o)=>o.validator.equals(validator));
12
+ if (committees.length !== epochsForCommittees.length) {
13
+ throw new Error('committees and epochsForCommittees must have the same length');
14
+ }
15
+ const votes = committees.flatMap((committee, committeeIndex)=>{
16
+ const committeeEpoch = epochsForCommittees[committeeIndex];
17
+ return committee.map((validator)=>{
18
+ // Find offenses for this validator in this specific epoch.
19
+ // If an offense has no epoch, it is considered for all epochs due to a slashAlways setting.
20
+ const validatorOffenses = offenses.filter((o)=>o.validator.equals(validator) && (o.epochOrSlot === undefined || getEpochForOffense(o, settings) === committeeEpoch));
21
+ // Sum up the penalties for this validator in this epoch
19
22
  const slashAmount = sumBigint(validatorOffenses.map((o)=>o.amount));
20
23
  const slashUnits = getSlashUnitsForAmount(slashAmount, slashingAmounts);
21
- slashedSet.add(validatorStr);
22
24
  return Number(slashUnits);
23
- }));
25
+ });
26
+ });
24
27
  return votes;
25
28
  }
26
29
  /** Returns the slash vote for the given amount to slash. */ function getSlashUnitsForAmount(amountToSlash, slashingAmounts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/stdlib",
3
- "version": "2.0.0-nightly.20250902",
3
+ "version": "2.0.0-nightly.20250903",
4
4
  "type": "module",
5
5
  "inherits": [
6
6
  "../package.common.json",
@@ -69,13 +69,13 @@
69
69
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
70
70
  },
71
71
  "dependencies": {
72
- "@aztec/bb.js": "2.0.0-nightly.20250902",
73
- "@aztec/blob-lib": "2.0.0-nightly.20250902",
74
- "@aztec/constants": "2.0.0-nightly.20250902",
75
- "@aztec/ethereum": "2.0.0-nightly.20250902",
76
- "@aztec/foundation": "2.0.0-nightly.20250902",
77
- "@aztec/l1-artifacts": "2.0.0-nightly.20250902",
78
- "@aztec/noir-noirc_abi": "2.0.0-nightly.20250902",
72
+ "@aztec/bb.js": "2.0.0-nightly.20250903",
73
+ "@aztec/blob-lib": "2.0.0-nightly.20250903",
74
+ "@aztec/constants": "2.0.0-nightly.20250903",
75
+ "@aztec/ethereum": "2.0.0-nightly.20250903",
76
+ "@aztec/foundation": "2.0.0-nightly.20250903",
77
+ "@aztec/l1-artifacts": "2.0.0-nightly.20250903",
78
+ "@aztec/noir-noirc_abi": "2.0.0-nightly.20250903",
79
79
  "@google-cloud/storage": "^7.15.0",
80
80
  "axios": "^1.9.0",
81
81
  "json-stringify-deterministic": "1.0.12",
@@ -106,12 +106,23 @@ export function getSlotForOffense(
106
106
  return getTimeUnitForOffense(offenseType) === 'epoch' ? epochOrSlot * BigInt(constants.epochDuration) : epochOrSlot;
107
107
  }
108
108
 
109
- /** Returns the epoch for a given offense. */
109
+ /** Returns the epoch for a given offense. If the offense type or epoch is not defined, returns undefined. */
110
110
  export function getEpochForOffense(
111
111
  offense: Pick<Offense, 'epochOrSlot' | 'offenseType'>,
112
112
  constants: Pick<L1RollupConstants, 'epochDuration'>,
113
- ): bigint {
113
+ ): bigint;
114
+ export function getEpochForOffense(
115
+ offense: Partial<Pick<Offense, 'epochOrSlot' | 'offenseType'>>,
116
+ constants: Pick<L1RollupConstants, 'epochDuration'>,
117
+ ): bigint | undefined;
118
+ export function getEpochForOffense(
119
+ offense: Partial<Pick<Offense, 'epochOrSlot' | 'offenseType'>>,
120
+ constants: Pick<L1RollupConstants, 'epochDuration'>,
121
+ ): bigint | undefined {
114
122
  const { epochOrSlot, offenseType } = offense;
123
+ if (epochOrSlot === undefined || offenseType === undefined) {
124
+ return undefined;
125
+ }
115
126
  return getTimeUnitForOffense(offenseType) === 'epoch' ? epochOrSlot : epochOrSlot / BigInt(constants.epochDuration);
116
127
  }
117
128
 
@@ -1,43 +1,52 @@
1
1
  import { sumBigint } from '@aztec/foundation/bigint';
2
2
  import { EthAddress } from '@aztec/foundation/eth-address';
3
+ import type { PartialBy } from '@aztec/foundation/types';
3
4
 
5
+ import { getEpochForOffense } from './helpers.js';
4
6
  import type { Offense, ValidatorSlashVote } from './types.js';
5
7
 
6
8
  /**
7
9
  * Creates a consensus-slash vote for a given set of committees based on a set of Offenses
8
10
  * @param offenses - Array of offenses to consider
9
11
  * @param committees - Array of committees (each containing array of validator addresses)
12
+ * @param epochsForCommittees - Array of epochs corresponding to each committee
10
13
  * @param settings - Settings including slashingAmounts and optional validator override lists
11
14
  * @returns Array of ValidatorSlashVote, where each vote is how many slash units the validator in that position should be slashed
12
15
  */
13
16
  export function getSlashConsensusVotesFromOffenses(
14
- offenses: Pick<Offense, 'validator' | 'amount'>[],
17
+ offenses: PartialBy<Offense, 'epochOrSlot'>[],
15
18
  committees: EthAddress[][],
19
+ epochsForCommittees: bigint[],
16
20
  settings: {
17
21
  slashingAmounts: [bigint, bigint, bigint];
22
+ epochDuration: number;
18
23
  },
19
24
  ): ValidatorSlashVote[] {
20
25
  const { slashingAmounts } = settings;
21
26
 
22
- const slashedSet: Set<string> = new Set();
27
+ if (committees.length !== epochsForCommittees.length) {
28
+ throw new Error('committees and epochsForCommittees must have the same length');
29
+ }
23
30
 
24
- const votes = committees.flatMap(committee =>
25
- committee.map(validator => {
26
- const validatorStr = validator.toString();
31
+ const votes = committees.flatMap((committee, committeeIndex) => {
32
+ const committeeEpoch = epochsForCommittees[committeeIndex];
27
33
 
28
- // If already voted for slashing this validator, skip
29
- if (slashedSet.has(validatorStr)) {
30
- return 0;
31
- }
34
+ return committee.map(validator => {
35
+ // Find offenses for this validator in this specific epoch.
36
+ // If an offense has no epoch, it is considered for all epochs due to a slashAlways setting.
37
+ const validatorOffenses = offenses.filter(
38
+ o =>
39
+ o.validator.equals(validator) &&
40
+ (o.epochOrSlot === undefined || getEpochForOffense(o, settings) === committeeEpoch),
41
+ );
32
42
 
33
- // Normal offense-based slashing logic
34
- const validatorOffenses = offenses.filter(o => o.validator.equals(validator));
43
+ // Sum up the penalties for this validator in this epoch
35
44
  const slashAmount = sumBigint(validatorOffenses.map(o => o.amount));
36
45
  const slashUnits = getSlashUnitsForAmount(slashAmount, slashingAmounts);
37
- slashedSet.add(validatorStr);
38
46
  return Number(slashUnits);
39
- }),
40
- );
47
+ });
48
+ });
49
+
41
50
  return votes;
42
51
  }
43
52