@aztec/stdlib 4.0.4-rc.9 → 4.1.0-nightly.20260311

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.
Files changed (74) hide show
  1. package/dest/abi/decoder.d.ts +2 -2
  2. package/dest/abi/decoder.d.ts.map +1 -1
  3. package/dest/abi/decoder.js +6 -1
  4. package/dest/abi/encoder.d.ts +1 -1
  5. package/dest/abi/encoder.d.ts.map +1 -1
  6. package/dest/abi/encoder.js +28 -1
  7. package/dest/abi/event_metadata_definition.d.ts +3 -1
  8. package/dest/abi/event_metadata_definition.d.ts.map +1 -1
  9. package/dest/abi/event_metadata_definition.js +1 -1
  10. package/dest/abi/utils.d.ts +14 -1
  11. package/dest/abi/utils.d.ts.map +1 -1
  12. package/dest/abi/utils.js +15 -0
  13. package/dest/block/l2_block_source.d.ts +6 -1
  14. package/dest/block/l2_block_source.d.ts.map +1 -1
  15. package/dest/epoch-helpers/index.d.ts +5 -1
  16. package/dest/epoch-helpers/index.d.ts.map +1 -1
  17. package/dest/epoch-helpers/index.js +4 -2
  18. package/dest/interfaces/allowed_element.d.ts +26 -20
  19. package/dest/interfaces/allowed_element.d.ts.map +1 -1
  20. package/dest/interfaces/allowed_element.js +8 -8
  21. package/dest/interfaces/archiver.d.ts +1 -1
  22. package/dest/interfaces/archiver.d.ts.map +1 -1
  23. package/dest/interfaces/archiver.js +1 -0
  24. package/dest/interfaces/aztec-node-admin.d.ts +37 -24
  25. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  26. package/dest/interfaces/aztec-node.d.ts +10 -5
  27. package/dest/interfaces/aztec-node.d.ts.map +1 -1
  28. package/dest/interfaces/aztec-node.js +3 -2
  29. package/dest/interfaces/block-builder.d.ts +2 -5
  30. package/dest/interfaces/block-builder.d.ts.map +1 -1
  31. package/dest/interfaces/block-builder.js +1 -1
  32. package/dest/interfaces/configs.d.ts +37 -27
  33. package/dest/interfaces/configs.d.ts.map +1 -1
  34. package/dest/interfaces/configs.js +1 -1
  35. package/dest/interfaces/prover-client.d.ts +6 -1
  36. package/dest/interfaces/prover-client.d.ts.map +1 -1
  37. package/dest/interfaces/prover-client.js +7 -1
  38. package/dest/interfaces/validator.d.ts +35 -25
  39. package/dest/interfaces/validator.d.ts.map +1 -1
  40. package/dest/interfaces/validator.js +1 -1
  41. package/dest/logs/public_log.d.ts +4 -3
  42. package/dest/logs/public_log.d.ts.map +1 -1
  43. package/dest/logs/public_log.js +2 -1
  44. package/dest/p2p/peer_error.d.ts +3 -1
  45. package/dest/p2p/peer_error.d.ts.map +1 -1
  46. package/dest/p2p/peer_error.js +5 -0
  47. package/dest/slashing/tally.d.ts +7 -2
  48. package/dest/slashing/tally.d.ts.map +1 -1
  49. package/dest/slashing/tally.js +30 -2
  50. package/dest/tx/simulated_tx.d.ts +5 -2
  51. package/dest/tx/simulated_tx.d.ts.map +1 -1
  52. package/dest/tx/simulated_tx.js +4 -1
  53. package/dest/tx/validator/error_texts.d.ts +5 -1
  54. package/dest/tx/validator/error_texts.d.ts.map +1 -1
  55. package/dest/tx/validator/error_texts.js +4 -0
  56. package/package.json +9 -9
  57. package/src/abi/decoder.ts +14 -2
  58. package/src/abi/encoder.ts +41 -1
  59. package/src/abi/event_metadata_definition.ts +2 -0
  60. package/src/abi/utils.ts +25 -0
  61. package/src/block/l2_block_source.ts +6 -0
  62. package/src/epoch-helpers/index.ts +3 -0
  63. package/src/interfaces/allowed_element.ts +29 -9
  64. package/src/interfaces/archiver.ts +1 -0
  65. package/src/interfaces/aztec-node.ts +14 -4
  66. package/src/interfaces/block-builder.ts +4 -7
  67. package/src/interfaces/configs.ts +4 -4
  68. package/src/interfaces/prover-client.ts +8 -0
  69. package/src/interfaces/validator.ts +2 -2
  70. package/src/logs/public_log.ts +4 -2
  71. package/src/p2p/peer_error.ts +7 -0
  72. package/src/slashing/tally.ts +34 -1
  73. package/src/tx/simulated_tx.ts +8 -1
  74. package/src/tx/validator/error_texts.ts +4 -0
package/src/abi/utils.ts CHANGED
@@ -81,6 +81,31 @@ export function isBoundedVecStruct(abiType: AbiType) {
81
81
  );
82
82
  }
83
83
 
84
+ /**
85
+ * Returns whether the ABI type is Noir's std::option::Option lowered to a struct.
86
+ * @param abiType - Type to check.
87
+ * @returns A boolean indicating whether the ABI type is an Option struct.
88
+ */
89
+ export function isOptionStruct(abiType: AbiType) {
90
+ return (
91
+ abiType.kind === 'struct' &&
92
+ abiType.path === 'std::option::Option' &&
93
+ abiType.fields.length === 2 &&
94
+ abiType.fields[0].name === '_is_some' &&
95
+ abiType.fields[1].name === '_value'
96
+ );
97
+ }
98
+
99
+ /**
100
+ * Returns whether `null` or `undefined` can be mapped to a valid ABI value for this type.
101
+ *
102
+ * @param abiType - Type to check.
103
+ * @returns A boolean indicating whether nullish values are valid shorthand for this ABI type.
104
+ */
105
+ export function canBeMappedFromNullOrUndefined(abiType: AbiType) {
106
+ return isOptionStruct(abiType);
107
+ }
108
+
84
109
  /**
85
110
  * Returns a bigint by parsing a serialized 2's complement signed int.
86
111
  * @param b - The signed int as a buffer
@@ -49,6 +49,12 @@ export interface L2BlockSource {
49
49
  */
50
50
  getBlockNumber(): Promise<BlockNumber>;
51
51
 
52
+ /**
53
+ * Gets the number of the latest L2 checkpoint processed by the block source implementation.
54
+ * @returns The number of the latest L2 checkpoint processed by the block source implementation.
55
+ */
56
+ getCheckpointNumber(): Promise<CheckpointNumber>;
57
+
52
58
  /**
53
59
  * Gets the number of the latest L2 block proven seen by the block source implementation.
54
60
  * @returns The number of the latest L2 block proven seen by the block source implementation.
@@ -12,6 +12,7 @@ export type L1RollupConstants = {
12
12
  ethereumSlotDuration: number;
13
13
  proofSubmissionEpochs: number;
14
14
  targetCommitteeSize: number;
15
+ rollupManaLimit: number;
15
16
  };
16
17
 
17
18
  export const EmptyL1RollupConstants: L1RollupConstants = {
@@ -22,6 +23,7 @@ export const EmptyL1RollupConstants: L1RollupConstants = {
22
23
  ethereumSlotDuration: 1,
23
24
  proofSubmissionEpochs: 1,
24
25
  targetCommitteeSize: 48,
26
+ rollupManaLimit: Number.MAX_SAFE_INTEGER,
25
27
  };
26
28
 
27
29
  export const L1RollupConstantsSchema = zodFor<L1RollupConstants>()(
@@ -33,6 +35,7 @@ export const L1RollupConstantsSchema = zodFor<L1RollupConstants>()(
33
35
  ethereumSlotDuration: z.number(),
34
36
  proofSubmissionEpochs: z.number(),
35
37
  targetCommitteeSize: z.number(),
38
+ rollupManaLimit: z.number(),
36
39
  }),
37
40
  );
38
41
 
@@ -6,18 +6,38 @@ import type { FunctionSelector } from '../abi/function_selector.js';
6
6
  import type { AztecAddress } from '../aztec-address/index.js';
7
7
  import { schemas, zodFor } from '../schemas/index.js';
8
8
 
9
- type AllowedInstance = { address: AztecAddress };
10
- type AllowedInstanceFunction = { address: AztecAddress; selector: FunctionSelector };
11
- type AllowedClass = { classId: Fr };
12
- type AllowedClassFunction = { classId: Fr; selector: FunctionSelector };
9
+ type AllowedInstanceFunction = {
10
+ address: AztecAddress;
11
+ selector: FunctionSelector;
12
+ onlySelf?: boolean;
13
+ rejectNullMsgSender?: boolean;
14
+ calldataLength?: number;
15
+ };
16
+ type AllowedClassFunction = {
17
+ classId: Fr;
18
+ selector: FunctionSelector;
19
+ onlySelf?: boolean;
20
+ rejectNullMsgSender?: boolean;
21
+ calldataLength?: number;
22
+ };
13
23
 
14
- export type AllowedElement = AllowedInstance | AllowedInstanceFunction | AllowedClass | AllowedClassFunction;
24
+ export type AllowedElement = AllowedInstanceFunction | AllowedClassFunction;
15
25
 
16
26
  export const AllowedElementSchema = zodFor<AllowedElement>()(
17
27
  z.union([
18
- z.object({ address: schemas.AztecAddress, selector: schemas.FunctionSelector }),
19
- z.object({ address: schemas.AztecAddress }),
20
- z.object({ classId: schemas.Fr, selector: schemas.FunctionSelector }),
21
- z.object({ classId: schemas.Fr }),
28
+ z.object({
29
+ address: schemas.AztecAddress,
30
+ selector: schemas.FunctionSelector,
31
+ onlySelf: z.boolean().optional(),
32
+ rejectNullMsgSender: z.boolean().optional(),
33
+ calldataLength: z.number().optional(),
34
+ }),
35
+ z.object({
36
+ classId: schemas.Fr,
37
+ selector: schemas.FunctionSelector,
38
+ onlySelf: z.boolean().optional(),
39
+ rejectNullMsgSender: z.boolean().optional(),
40
+ calldataLength: z.number().optional(),
41
+ }),
22
42
  ]),
23
43
  );
@@ -86,6 +86,7 @@ export const ArchiverApiSchema: ApiSchemaFor<ArchiverApi> = {
86
86
  getBlockNumber: z.function().args().returns(BlockNumberSchema),
87
87
  getProvenBlockNumber: z.function().args().returns(BlockNumberSchema),
88
88
  getCheckpointedL2BlockNumber: z.function().args().returns(BlockNumberSchema),
89
+ getCheckpointNumber: z.function().args().returns(CheckpointNumberSchema),
89
90
  getFinalizedL2BlockNumber: z.function().args().returns(BlockNumberSchema),
90
91
  getBlock: z.function().args(BlockNumberSchema).returns(L2Block.schema.optional()),
91
92
  getBlockHeader: z
@@ -4,7 +4,9 @@ import {
4
4
  BlockNumber,
5
5
  BlockNumberPositiveSchema,
6
6
  BlockNumberSchema,
7
+ CheckpointNumber,
7
8
  CheckpointNumberPositiveSchema,
9
+ CheckpointNumberSchema,
8
10
  EpochNumber,
9
11
  EpochNumberSchema,
10
12
  type SlotNumber,
@@ -172,14 +174,14 @@ export interface AztecNode
172
174
  l1ToL2Message: Fr,
173
175
  ): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>] | undefined>;
174
176
 
175
- /** Returns the L2 block number in which this L1 to L2 message becomes available, or undefined if not found. */
176
- getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<BlockNumber | undefined>;
177
+ /** Returns the L2 checkpoint number in which this L1 to L2 message becomes available, or undefined if not found. */
178
+ getL1ToL2MessageCheckpoint(l1ToL2Message: Fr): Promise<CheckpointNumber | undefined>;
177
179
 
178
180
  /**
179
181
  * Returns whether an L1 to L2 message is synced by archiver.
180
182
  * @param l1ToL2Message - The L1 to L2 message to check.
181
183
  * @returns Whether the message is synced.
182
- * @deprecated Use `getL1ToL2MessageBlock` instead. This method may return true even if the message is not ready to use.
184
+ * @deprecated Use `getL1ToL2MessageCheckpoint` instead. This method may return true even if the message is not ready to use.
183
185
  */
184
186
  isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise<boolean>;
185
187
 
@@ -230,6 +232,12 @@ export interface AztecNode
230
232
  */
231
233
  getCheckpointedBlockNumber(): Promise<BlockNumber>;
232
234
 
235
+ /**
236
+ * Method to fetch the latest checkpoint number synchronized by the node.
237
+ * @returns The checkpoint number.
238
+ */
239
+ getCheckpointNumber(): Promise<CheckpointNumber>;
240
+
233
241
  /**
234
242
  * Method to determine if the node is ready to accept transactions.
235
243
  * @returns - Flag indicating the readiness for tx submission.
@@ -517,7 +525,7 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
517
525
  .args(BlockParameterSchema, schemas.Fr)
518
526
  .returns(z.tuple([schemas.BigInt, SiblingPath.schemaFor(L1_TO_L2_MSG_TREE_HEIGHT)]).optional()),
519
527
 
520
- getL1ToL2MessageBlock: z.function().args(schemas.Fr).returns(BlockNumberSchema.optional()),
528
+ getL1ToL2MessageCheckpoint: z.function().args(schemas.Fr).returns(CheckpointNumberSchema.optional()),
521
529
 
522
530
  isL1ToL2MessageSynced: z.function().args(schemas.Fr).returns(z.boolean()),
523
531
 
@@ -534,6 +542,8 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
534
542
 
535
543
  getBlockNumber: z.function().returns(BlockNumberSchema),
536
544
 
545
+ getCheckpointNumber: z.function().returns(CheckpointNumberSchema),
546
+
537
547
  getProvenBlockNumber: z.function().returns(BlockNumberSchema),
538
548
 
539
549
  getCheckpointedBlockNumber: z.function().returns(BlockNumberSchema),
@@ -53,28 +53,25 @@ export interface PublicProcessorValidator {
53
53
  nullifierCache?: { addNullifiers: (nullifiers: Buffer[]) => void };
54
54
  }
55
55
 
56
- export type FullNodeBlockBuilderConfig = Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'> &
56
+ export type FullNodeBlockBuilderConfig = Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration' | 'rollupManaLimit'> &
57
57
  Pick<ChainConfig, 'l1ChainId' | 'rollupVersion'> &
58
58
  Pick<
59
59
  SequencerConfig,
60
- | 'txPublicSetupAllowList'
60
+ | 'txPublicSetupAllowListExtend'
61
61
  | 'fakeProcessingDelayPerTxMs'
62
62
  | 'fakeThrowAfterProcessingTxCount'
63
63
  | 'maxTxsPerBlock'
64
64
  | 'maxTxsPerCheckpoint'
65
65
  | 'maxL2BlockGas'
66
66
  | 'maxDABlockGas'
67
- > & {
68
- /** Total L2 gas (mana) allowed per checkpoint. Fetched from L1 getManaLimit(). */
69
- rollupManaLimit: number;
70
- };
67
+ >;
71
68
 
72
69
  export const FullNodeBlockBuilderConfigKeys: (keyof FullNodeBlockBuilderConfig)[] = [
73
70
  'l1GenesisTime',
74
71
  'slotDuration',
75
72
  'l1ChainId',
76
73
  'rollupVersion',
77
- 'txPublicSetupAllowList',
74
+ 'txPublicSetupAllowListExtend',
78
75
  'fakeProcessingDelayPerTxMs',
79
76
  'fakeThrowAfterProcessingTxCount',
80
77
  'maxTxsPerBlock',
@@ -35,8 +35,8 @@ export interface SequencerConfig {
35
35
  acvmWorkingDirectory?: string;
36
36
  /** The path to the ACVM binary */
37
37
  acvmBinaryPath?: string;
38
- /** The list of functions calls allowed to run in setup */
39
- txPublicSetupAllowList?: AllowedElement[];
38
+ /** Additional entries to extend the default setup allow list. */
39
+ txPublicSetupAllowListExtend?: AllowedElement[];
40
40
  /** Payload address to vote for */
41
41
  governanceProposerPayload?: EthAddress;
42
42
  /** Whether to enforce the time table when building blocks */
@@ -98,7 +98,7 @@ export const SequencerConfigSchema = zodFor<SequencerConfig>()(
98
98
  feeRecipient: schemas.AztecAddress.optional(),
99
99
  acvmWorkingDirectory: z.string().optional(),
100
100
  acvmBinaryPath: z.string().optional(),
101
- txPublicSetupAllowList: z.array(AllowedElementSchema).optional(),
101
+ txPublicSetupAllowListExtend: z.array(AllowedElementSchema).optional(),
102
102
  governanceProposerPayload: schemas.EthAddress.optional(),
103
103
  l1PublishingTime: z.number().optional(),
104
104
  enforceTimeTable: z.boolean().optional(),
@@ -135,7 +135,7 @@ type SequencerConfigOptionalKeys =
135
135
  | 'fakeProcessingDelayPerTxMs'
136
136
  | 'fakeThrowAfterProcessingTxCount'
137
137
  | 'l1PublishingTime'
138
- | 'txPublicSetupAllowList'
138
+ | 'txPublicSetupAllowListExtend'
139
139
  | 'minValidTxsPerBlock'
140
140
  | 'minBlocksForCheckpoint'
141
141
  | 'maxTxsPerBlock'
@@ -23,6 +23,8 @@ export type ActualProverConfig = {
23
23
  * When true, jobs are explicitly cancelled with the broker, which prevents reuse.
24
24
  */
25
25
  cancelJobsOnStop: boolean;
26
+ /** Max concurrent jobs the orchestrator serializes and enqueues to the broker. */
27
+ enqueueConcurrency: number;
26
28
  };
27
29
 
28
30
  /**
@@ -53,6 +55,7 @@ export const ProverConfigSchema = zodFor<ProverConfig>()(
53
55
  proofStore: z.string().optional(),
54
56
  failedProofStore: z.string().optional(),
55
57
  cancelJobsOnStop: z.boolean(),
58
+ enqueueConcurrency: z.number(),
56
59
  }),
57
60
  );
58
61
 
@@ -107,6 +110,11 @@ export const proverConfigMappings: ConfigMappingsType<ProverConfig> = {
107
110
  'When true, jobs are explicitly cancelled with the broker, which prevents reuse.',
108
111
  ...booleanConfigHelper(false),
109
112
  },
113
+ enqueueConcurrency: {
114
+ env: 'PROVER_ENQUEUE_CONCURRENCY',
115
+ description: 'Max concurrent jobs the orchestrator serializes and enqueues to the broker.',
116
+ ...numberConfigHelper(10),
117
+ },
110
118
  };
111
119
 
112
120
  function parseProverId(str?: string) {
@@ -74,7 +74,7 @@ export type ValidatorClientConfig = ValidatorHASignerConfig & {
74
74
  };
75
75
 
76
76
  export type ValidatorClientFullConfig = ValidatorClientConfig &
77
- Pick<SequencerConfig, 'txPublicSetupAllowList' | 'broadcastInvalidBlockProposal'> &
77
+ Pick<SequencerConfig, 'txPublicSetupAllowListExtend' | 'broadcastInvalidBlockProposal'> &
78
78
  Pick<
79
79
  SlasherConfig,
80
80
  'slashBroadcastedInvalidBlockPenalty' | 'slashDuplicateProposalPenalty' | 'slashDuplicateAttestationPenalty'
@@ -107,7 +107,7 @@ export const ValidatorClientConfigSchema = zodFor<Omit<ValidatorClientConfig, 'v
107
107
 
108
108
  export const ValidatorClientFullConfigSchema = zodFor<Omit<ValidatorClientFullConfig, 'validatorPrivateKeys'>>()(
109
109
  ValidatorClientConfigSchema.extend({
110
- txPublicSetupAllowList: z.array(AllowedElementSchema).optional(),
110
+ txPublicSetupAllowListExtend: z.array(AllowedElementSchema).optional(),
111
111
  broadcastInvalidBlockProposal: z.boolean().optional(),
112
112
  slashBroadcastedInvalidBlockPenalty: schemas.BigInt,
113
113
  slashDuplicateProposalPenalty: schemas.BigInt,
@@ -120,8 +120,8 @@ export class FlatPublicLogs {
120
120
 
121
121
  export class PublicLog {
122
122
  constructor(
123
- public contractAddress: AztecAddress,
124
- public fields: Fr[],
123
+ public readonly contractAddress: AztecAddress,
124
+ public readonly fields: Fr[],
125
125
  ) {}
126
126
 
127
127
  static from(fields: FieldsOf<PublicLog>) {
@@ -146,7 +146,9 @@ export class PublicLog {
146
146
  return this.fields.length + PUBLIC_LOG_HEADER_LENGTH;
147
147
  }
148
148
 
149
+ /** Returns the serialized log (field as in noir field and not a struct field). */
149
150
  getEmittedFields() {
151
+ // We slice from 0 to return a shallow copy.
150
152
  return this.fields.slice(0);
151
153
  }
152
154
 
@@ -15,3 +15,10 @@ export enum PeerErrorSeverity {
15
15
  */
16
16
  HighToleranceError = 'HighToleranceError',
17
17
  }
18
+
19
+ /** Severities ordered from mildest to harshest. */
20
+ export const PeerErrorSeverityByHarshness = [
21
+ PeerErrorSeverity.HighToleranceError,
22
+ PeerErrorSeverity.MidToleranceError,
23
+ PeerErrorSeverity.LowToleranceError,
24
+ ] as const;
@@ -1,6 +1,7 @@
1
1
  import { sumBigint } from '@aztec/foundation/bigint';
2
2
  import { padArrayEnd } from '@aztec/foundation/collection';
3
3
  import { EthAddress } from '@aztec/foundation/eth-address';
4
+ import { type Logger, createLogger } from '@aztec/foundation/log';
4
5
  import type { PartialBy } from '@aztec/foundation/types';
5
6
 
6
7
  import { getEpochForOffense } from './helpers.js';
@@ -12,6 +13,9 @@ import type { Offense, ValidatorSlashVote } from './types.js';
12
13
  * @param committees - Array of committees (each containing array of validator addresses)
13
14
  * @param epochsForCommittees - Array of epochs corresponding to each committee
14
15
  * @param settings - Settings including slashingAmounts and optional validator override lists
16
+ * @param settings.maxSlashedValidators - If set, limits the total number of [validator, epoch] pairs
17
+ * with non-zero votes. The lowest-vote pairs are zeroed out to stay within the limit.
18
+ * @param logger - Logger, logs which validators were dropped.
15
19
  * @returns Array of ValidatorSlashVote, where each vote is how many slash units the validator in that position should be slashed
16
20
  */
17
21
  export function getSlashConsensusVotesFromOffenses(
@@ -22,9 +26,11 @@ export function getSlashConsensusVotesFromOffenses(
22
26
  slashingAmounts: [bigint, bigint, bigint];
23
27
  epochDuration: number;
24
28
  targetCommitteeSize: number;
29
+ maxSlashedValidators?: number;
25
30
  },
31
+ logger: Logger = createLogger('slasher:tally'),
26
32
  ): ValidatorSlashVote[] {
27
- const { slashingAmounts, targetCommitteeSize } = settings;
33
+ const { slashingAmounts, targetCommitteeSize, maxSlashedValidators } = settings;
28
34
 
29
35
  if (committees.length !== epochsForCommittees.length) {
30
36
  throw new Error('committees and epochsForCommittees must have the same length');
@@ -53,6 +59,33 @@ export function getSlashConsensusVotesFromOffenses(
53
59
  return padArrayEnd(votes, 0, targetCommitteeSize);
54
60
  });
55
61
 
62
+ // if a cap is set, zero out the lowest-vote [validator, epoch] pairs so that the most severe slashes stay.
63
+ if (maxSlashedValidators === undefined) {
64
+ return votes;
65
+ }
66
+
67
+ const nonZeroByDescendingVote = [...votes.entries()].filter(([, vote]) => vote > 0).sort(([, a], [, b]) => b - a);
68
+
69
+ const toTruncate = nonZeroByDescendingVote.slice(maxSlashedValidators);
70
+ for (const [idx] of toTruncate) {
71
+ votes[idx] = 0;
72
+ }
73
+
74
+ if (toTruncate.length > 0) {
75
+ const truncated = toTruncate.map(([idx]) => {
76
+ const committeeIndex = Math.floor(idx / targetCommitteeSize);
77
+ const positionInCommittee = idx % targetCommitteeSize;
78
+ return {
79
+ validator: committees[committeeIndex][positionInCommittee].toString(),
80
+ epoch: epochsForCommittees[committeeIndex],
81
+ };
82
+ });
83
+ logger.warn(
84
+ `Truncated ${toTruncate.length} validator-epoch pairs to stay within limit of ${maxSlashedValidators}`,
85
+ { truncated },
86
+ );
87
+ }
88
+
56
89
  return votes;
57
90
  }
58
91
 
@@ -12,9 +12,11 @@ import { Gas } from '../gas/gas.js';
12
12
  import type { GasUsed } from '../gas/gas_used.js';
13
13
  import { PrivateKernelTailCircuitPublicInputs } from '../kernel/private_kernel_tail_circuit_public_inputs.js';
14
14
  import { ChonkProof } from '../proofs/chonk_proof.js';
15
+ import type { OffchainEffect } from './offchain_effect.js';
15
16
  import {
16
17
  PrivateCallExecutionResult,
17
18
  PrivateExecutionResult,
19
+ collectOffchainEffects,
18
20
  collectSortedContractClassLogs,
19
21
  } from './private_execution_result.js';
20
22
  import { type SimulationStats, SimulationStatsSchema } from './profiling.js';
@@ -84,6 +86,11 @@ export class TxSimulationResult {
84
86
  public stats?: SimulationStats,
85
87
  ) {}
86
88
 
89
+ /** Returns offchain effects collected from private execution. */
90
+ get offchainEffects(): OffchainEffect[] {
91
+ return collectOffchainEffects(this.privateExecutionResult);
92
+ }
93
+
87
94
  get gasUsed(): GasUsed {
88
95
  return (
89
96
  this.publicOutput?.gasUsed ?? {
@@ -106,7 +113,7 @@ export class TxSimulationResult {
106
113
  .transform(TxSimulationResult.from);
107
114
  }
108
115
 
109
- static from(fields: Omit<FieldsOf<TxSimulationResult>, 'gasUsed'>) {
116
+ static from(fields: Omit<FieldsOf<TxSimulationResult>, 'gasUsed' | 'offchainEffects'>) {
110
117
  return new TxSimulationResult(
111
118
  fields.privateExecutionResult,
112
119
  fields.publicInputs,
@@ -6,6 +6,10 @@ export const TX_ERROR_GAS_LIMIT_TOO_HIGH = 'Gas limit is higher than the amount
6
6
 
7
7
  // Phases
8
8
  export const TX_ERROR_SETUP_FUNCTION_NOT_ALLOWED = 'Setup function not on allow list';
9
+ export const TX_ERROR_SETUP_FUNCTION_UNKNOWN_CONTRACT = 'Setup function targets unknown contract';
10
+ export const TX_ERROR_SETUP_ONLY_SELF_WRONG_SENDER = 'Setup only_self function called with incorrect msg_sender';
11
+ export const TX_ERROR_SETUP_NULL_MSG_SENDER = 'Setup function called with null msg sender';
12
+ export const TX_ERROR_SETUP_WRONG_CALLDATA_LENGTH = 'Setup function called with wrong calldata length';
9
13
 
10
14
  // Nullifiers
11
15
  export const TX_ERROR_DUPLICATE_NULLIFIER_IN_TX = 'Duplicate nullifier in tx';