@aztec/stdlib 3.0.0-nightly.20250908 → 3.0.0-nightly.20250911

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 (157) hide show
  1. package/dest/block/index.d.ts +2 -0
  2. package/dest/block/index.d.ts.map +1 -1
  3. package/dest/block/index.js +2 -0
  4. package/dest/block/l2_block.d.ts +2 -8
  5. package/dest/block/l2_block.d.ts.map +1 -1
  6. package/dest/block/l2_block.js +5 -3
  7. package/dest/block/l2_block_info.d.ts +41 -0
  8. package/dest/block/l2_block_info.d.ts.map +1 -0
  9. package/dest/block/l2_block_info.js +40 -0
  10. package/dest/block/l2_block_source.d.ts +1 -428
  11. package/dest/block/l2_block_source.d.ts.map +1 -1
  12. package/dest/block/l2_block_source.js +0 -28
  13. package/dest/block/proposal/attestations_and_signers.d.ts +48 -0
  14. package/dest/block/proposal/attestations_and_signers.d.ts.map +1 -0
  15. package/dest/block/proposal/attestations_and_signers.js +99 -0
  16. package/dest/block/proposal/index.d.ts +1 -0
  17. package/dest/block/proposal/index.d.ts.map +1 -1
  18. package/dest/block/proposal/index.js +1 -0
  19. package/dest/block/published_l2_block.d.ts +25 -1
  20. package/dest/block/published_l2_block.d.ts.map +1 -1
  21. package/dest/block/published_l2_block.js +20 -1
  22. package/dest/block/test/l2_tips_store_test_suite.d.ts.map +1 -1
  23. package/dest/block/test/l2_tips_store_test_suite.js +2 -1
  24. package/dest/block/validate_block_result.d.ts +222 -0
  25. package/dest/block/validate_block_result.d.ts.map +1 -0
  26. package/dest/block/validate_block_result.js +83 -0
  27. package/dest/interfaces/archiver.d.ts.map +1 -1
  28. package/dest/interfaces/archiver.js +2 -1
  29. package/dest/interfaces/block-builder.d.ts +5 -6
  30. package/dest/interfaces/block-builder.d.ts.map +1 -1
  31. package/dest/interfaces/proving-job.d.ts +24 -24
  32. package/dest/interfaces/proving-job.d.ts.map +1 -1
  33. package/dest/interfaces/proving-job.js +15 -15
  34. package/dest/interfaces/server_circuit_prover.d.ts +4 -8
  35. package/dest/interfaces/server_circuit_prover.d.ts.map +1 -1
  36. package/dest/interfaces/validator.d.ts +3 -0
  37. package/dest/interfaces/validator.d.ts.map +1 -1
  38. package/dest/kernel/private_kernel_prover_output.d.ts +1 -1
  39. package/dest/kernel/private_kernel_prover_output.d.ts.map +1 -1
  40. package/dest/kernel/private_to_public_kernel_circuit_public_inputs.d.ts +2 -0
  41. package/dest/kernel/private_to_public_kernel_circuit_public_inputs.d.ts.map +1 -1
  42. package/dest/kernel/private_to_public_kernel_circuit_public_inputs.js +7 -0
  43. package/dest/noir/index.d.ts +9 -0
  44. package/dest/noir/index.d.ts.map +1 -1
  45. package/dest/p2p/block_attestation.d.ts +1 -0
  46. package/dest/p2p/block_attestation.d.ts.map +1 -1
  47. package/dest/p2p/block_attestation.js +3 -0
  48. package/dest/p2p/block_proposal.d.ts +2 -2
  49. package/dest/p2p/block_proposal.d.ts.map +1 -1
  50. package/dest/p2p/block_proposal.js +3 -1
  51. package/dest/p2p/consensus_payload.d.ts +1 -0
  52. package/dest/p2p/consensus_payload.d.ts.map +1 -1
  53. package/dest/p2p/consensus_payload.js +6 -4
  54. package/dest/p2p/signature_utils.d.ts +2 -1
  55. package/dest/p2p/signature_utils.d.ts.map +1 -1
  56. package/dest/p2p/signature_utils.js +1 -0
  57. package/dest/proofs/client_ivc_proof.d.ts +5 -8
  58. package/dest/proofs/client_ivc_proof.d.ts.map +1 -1
  59. package/dest/proofs/client_ivc_proof.js +27 -20
  60. package/dest/proofs/index.d.ts +1 -0
  61. package/dest/proofs/index.d.ts.map +1 -1
  62. package/dest/proofs/index.js +1 -0
  63. package/dest/proofs/proof_data.d.ts +20 -0
  64. package/dest/proofs/proof_data.d.ts.map +1 -0
  65. package/dest/proofs/proof_data.js +22 -0
  66. package/dest/proofs/proving_request_type.d.ts +12 -13
  67. package/dest/proofs/proving_request_type.d.ts.map +1 -1
  68. package/dest/proofs/proving_request_type.js +12 -12
  69. package/dest/rollup/index.d.ts +1 -3
  70. package/dest/rollup/index.d.ts.map +1 -1
  71. package/dest/rollup/index.js +1 -3
  72. package/dest/rollup/private_base_rollup_inputs.d.ts +5 -5
  73. package/dest/rollup/private_base_rollup_inputs.d.ts.map +1 -1
  74. package/dest/rollup/private_base_rollup_inputs.js +7 -9
  75. package/dest/rollup/public_base_rollup_inputs.d.ts +5 -5
  76. package/dest/rollup/public_base_rollup_inputs.d.ts.map +1 -1
  77. package/dest/rollup/public_base_rollup_inputs.js +7 -9
  78. package/dest/rollup/public_tube_private_inputs.d.ts +19 -0
  79. package/dest/rollup/public_tube_private_inputs.d.ts.map +1 -0
  80. package/dest/rollup/public_tube_private_inputs.js +38 -0
  81. package/dest/stats/stats.d.ts +1 -1
  82. package/dest/stats/stats.d.ts.map +1 -1
  83. package/dest/tests/factories.d.ts +4 -1
  84. package/dest/tests/factories.d.ts.map +1 -1
  85. package/dest/tests/factories.js +9 -15
  86. package/dest/tests/mocks.d.ts +3 -1
  87. package/dest/tests/mocks.d.ts.map +1 -1
  88. package/dest/tests/mocks.js +10 -9
  89. package/dest/tx/content_commitment.d.ts +1 -0
  90. package/dest/tx/content_commitment.d.ts.map +1 -1
  91. package/dest/tx/content_commitment.js +3 -0
  92. package/dest/tx/partial_state_reference.d.ts +1 -0
  93. package/dest/tx/partial_state_reference.d.ts.map +1 -1
  94. package/dest/tx/partial_state_reference.js +3 -0
  95. package/dest/tx/proposed_block_header.d.ts +1 -0
  96. package/dest/tx/proposed_block_header.d.ts.map +1 -1
  97. package/dest/tx/proposed_block_header.js +3 -0
  98. package/dest/tx/state_reference.d.ts +1 -0
  99. package/dest/tx/state_reference.d.ts.map +1 -1
  100. package/dest/tx/state_reference.js +3 -0
  101. package/dest/tx/tx.d.ts +0 -2
  102. package/dest/tx/tx.d.ts.map +1 -1
  103. package/dest/tx/tx.js +2 -3
  104. package/dest/update-checker/update-checker.d.ts +1 -1
  105. package/dest/update-checker/update-checker.d.ts.map +1 -1
  106. package/dest/update-checker/update-checker.js +1 -1
  107. package/package.json +8 -8
  108. package/src/block/index.ts +2 -0
  109. package/src/block/l2_block.ts +6 -11
  110. package/src/block/l2_block_info.ts +63 -0
  111. package/src/block/l2_block_source.ts +1 -51
  112. package/src/block/proposal/attestations_and_signers.ts +121 -0
  113. package/src/block/proposal/index.ts +1 -0
  114. package/src/block/published_l2_block.ts +38 -5
  115. package/src/block/test/l2_tips_store_test_suite.ts +7 -6
  116. package/src/block/validate_block_result.ts +122 -0
  117. package/src/interfaces/archiver.ts +2 -1
  118. package/src/interfaces/block-builder.ts +9 -6
  119. package/src/interfaces/proving-job.ts +19 -14
  120. package/src/interfaces/server_circuit_prover.ts +13 -13
  121. package/src/interfaces/validator.ts +7 -0
  122. package/src/kernel/private_kernel_prover_output.ts +1 -1
  123. package/src/kernel/private_to_public_kernel_circuit_public_inputs.ts +9 -0
  124. package/src/noir/index.ts +9 -0
  125. package/src/p2p/block_attestation.ts +4 -0
  126. package/src/p2p/block_proposal.ts +5 -3
  127. package/src/p2p/consensus_payload.ts +7 -4
  128. package/src/p2p/signature_utils.ts +1 -0
  129. package/src/proofs/client_ivc_proof.ts +26 -20
  130. package/src/proofs/index.ts +1 -0
  131. package/src/proofs/proof_data.ts +39 -0
  132. package/src/proofs/proving_request_type.ts +1 -3
  133. package/src/rollup/index.ts +1 -3
  134. package/src/rollup/private_base_rollup_inputs.ts +8 -8
  135. package/src/rollup/public_base_rollup_inputs.ts +5 -8
  136. package/src/rollup/public_tube_private_inputs.ts +46 -0
  137. package/src/stats/stats.ts +2 -2
  138. package/src/tests/factories.ts +20 -23
  139. package/src/tests/mocks.ts +18 -6
  140. package/src/tx/content_commitment.ts +4 -0
  141. package/src/tx/partial_state_reference.ts +8 -0
  142. package/src/tx/proposed_block_header.ts +13 -0
  143. package/src/tx/state_reference.ts +4 -0
  144. package/src/tx/tx.ts +2 -3
  145. package/src/update-checker/update-checker.ts +1 -1
  146. package/dest/rollup/private_tube_data.d.ts +0 -15
  147. package/dest/rollup/private_tube_data.d.ts.map +0 -1
  148. package/dest/rollup/private_tube_data.js +0 -25
  149. package/dest/rollup/public_tube_data.d.ts +0 -15
  150. package/dest/rollup/public_tube_data.d.ts.map +0 -1
  151. package/dest/rollup/public_tube_data.js +0 -25
  152. package/dest/rollup/tube_inputs.d.ts +0 -43
  153. package/dest/rollup/tube_inputs.d.ts.map +0 -1
  154. package/dest/rollup/tube_inputs.js +0 -63
  155. package/src/rollup/private_tube_data.ts +0 -35
  156. package/src/rollup/public_tube_data.ts +0 -35
  157. package/src/rollup/tube_inputs.ts +0 -77
@@ -1,17 +1,16 @@
1
1
  import type { EthAddress } from '@aztec/foundation/eth-address';
2
- import { type ZodFor, schemas } from '@aztec/foundation/schemas';
3
2
  import type { TypedEventEmitter } from '@aztec/foundation/types';
4
3
 
5
4
  import { z } from 'zod';
6
5
 
7
6
  import type { L1RollupConstants } from '../epoch-helpers/index.js';
8
- import { BlockAttestation } from '../p2p/block_attestation.js';
9
7
  import type { BlockHeader } from '../tx/block_header.js';
10
8
  import type { IndexedTxEffect } from '../tx/indexed_tx_effect.js';
11
9
  import type { TxHash } from '../tx/tx_hash.js';
12
10
  import type { TxReceipt } from '../tx/tx_receipt.js';
13
11
  import type { L2Block } from './l2_block.js';
14
12
  import { PublishedL2Block } from './published_l2_block.js';
13
+ import type { ValidateBlockNegativeResult, ValidateBlockResult } from './validate_block_result.js';
15
14
 
16
15
  /**
17
16
  * Interface of classes allowing for the retrieval of L2 blocks.
@@ -140,59 +139,10 @@ export interface L2BlockSource {
140
139
  syncImmediate(): Promise<void>;
141
140
  }
142
141
 
143
- /** Subtype for invalid block validation results */
144
- export type ValidateBlockNegativeResult =
145
- | {
146
- valid: false;
147
- block: PublishedL2Block;
148
- committee: EthAddress[];
149
- epoch: bigint;
150
- seed: bigint;
151
- attestations: BlockAttestation[];
152
- reason: 'insufficient-attestations';
153
- }
154
- | {
155
- valid: false;
156
- block: PublishedL2Block;
157
- committee: EthAddress[];
158
- epoch: bigint;
159
- seed: bigint;
160
- reason: 'invalid-attestation';
161
- attestations: BlockAttestation[];
162
- invalidIndex: number;
163
- };
164
-
165
- /** Result type for validating a block attestations */
166
- export type ValidateBlockResult = { valid: true } | ValidateBlockNegativeResult;
167
-
168
- export const ValidateBlockResultSchema = z.union([
169
- z.object({ valid: z.literal(true), block: PublishedL2Block.schema.optional() }),
170
- z.object({
171
- valid: z.literal(false),
172
- block: PublishedL2Block.schema,
173
- committee: z.array(schemas.EthAddress),
174
- epoch: schemas.BigInt,
175
- seed: schemas.BigInt,
176
- attestations: z.array(BlockAttestation.schema),
177
- reason: z.literal('insufficient-attestations'),
178
- }),
179
- z.object({
180
- valid: z.literal(false),
181
- block: PublishedL2Block.schema,
182
- committee: z.array(schemas.EthAddress),
183
- epoch: schemas.BigInt,
184
- seed: schemas.BigInt,
185
- attestations: z.array(BlockAttestation.schema),
186
- reason: z.literal('invalid-attestation'),
187
- invalidIndex: z.number(),
188
- }),
189
- ]) satisfies ZodFor<ValidateBlockResult>;
190
-
191
142
  /**
192
143
  * L2BlockSource that emits events upon pending / proven chain changes.
193
144
  * see L2BlockSourceEvents for the events emitted.
194
145
  */
195
-
196
146
  export type ArchiverEmitter = TypedEventEmitter<{
197
147
  [L2BlockSourceEvents.L2PruneDetected]: (args: L2BlockPruneEvent) => void;
198
148
  [L2BlockSourceEvents.L2BlockProven]: (args: L2BlockProvenEvent) => void;
@@ -0,0 +1,121 @@
1
+ import type { ViemCommitteeAttestations } from '@aztec/ethereum';
2
+ import { hexToBuffer } from '@aztec/foundation/string';
3
+
4
+ import { encodeAbiParameters, parseAbiParameters } from 'viem';
5
+ import { z } from 'zod';
6
+
7
+ import type { Signable, SignatureDomainSeparator } from '../../p2p/signature_utils.js';
8
+ import { CommitteeAttestation } from './committee_attestation.js';
9
+
10
+ export class CommitteeAttestationsAndSigners implements Signable {
11
+ constructor(public attestations: CommitteeAttestation[]) {}
12
+
13
+ static get schema() {
14
+ return z
15
+ .object({
16
+ attestations: CommitteeAttestation.schema.array(),
17
+ })
18
+ .transform(obj => new CommitteeAttestationsAndSigners(obj.attestations));
19
+ }
20
+
21
+ getPayloadToSign(domainSeparator: SignatureDomainSeparator): Buffer {
22
+ const abi = parseAbiParameters('uint8,(bytes,bytes),address[]');
23
+ const packed = this.getPackedAttestations();
24
+
25
+ const encodedData = encodeAbiParameters(abi, [
26
+ domainSeparator,
27
+ [packed.signatureIndices, packed.signaturesOrAddresses],
28
+ this.getSigners().map(s => s.toString()),
29
+ ]);
30
+
31
+ return hexToBuffer(encodedData);
32
+ }
33
+
34
+ static empty(): CommitteeAttestationsAndSigners {
35
+ return new CommitteeAttestationsAndSigners([]);
36
+ }
37
+
38
+ toString() {
39
+ throw new Error('Not implemented');
40
+ }
41
+
42
+ getSigners() {
43
+ return this.attestations.filter(a => !a.signature.isEmpty()).map(a => a.address);
44
+ }
45
+
46
+ getSignedAttestations() {
47
+ return this.attestations.filter(a => !a.signature.isEmpty());
48
+ }
49
+
50
+ /**
51
+ * Packs an array of committee attestations into the format expected by the Solidity contract
52
+ *
53
+ * @param attestations - Array of committee attestations with addresses and signatures
54
+ * @returns Packed attestations with bitmap and tightly packed signature/address data
55
+ */
56
+ getPackedAttestations(): ViemCommitteeAttestations {
57
+ const length = this.attestations.length;
58
+ const attestations = this.attestations.map(a => a.toViem());
59
+
60
+ // Calculate bitmap size (1 bit per attestation, rounded up to nearest byte)
61
+ const bitmapSize = Math.ceil(length / 8);
62
+ const signatureIndices = new Uint8Array(bitmapSize);
63
+
64
+ // Calculate total data size needed
65
+ let totalDataSize = 0;
66
+ for (let i = 0; i < length; i++) {
67
+ const signature = attestations[i].signature;
68
+ // Check if signature is empty (v = 0)
69
+ const isEmpty = signature.v === 0;
70
+
71
+ if (!isEmpty) {
72
+ totalDataSize += 65; // v (1) + r (32) + s (32)
73
+ } else {
74
+ totalDataSize += 20; // address only
75
+ }
76
+ }
77
+
78
+ const signaturesOrAddresses = new Uint8Array(totalDataSize);
79
+ let dataIndex = 0;
80
+
81
+ // Pack the data
82
+ for (let i = 0; i < length; i++) {
83
+ const attestation = attestations[i];
84
+ const signature = attestation.signature;
85
+
86
+ // Check if signature is empty
87
+ const isEmpty = signature.v === 0;
88
+
89
+ if (!isEmpty) {
90
+ // Set bit in bitmap (bit 7-0 in each byte, left to right)
91
+ const byteIndex = Math.floor(i / 8);
92
+ const bitIndex = 7 - (i % 8);
93
+ signatureIndices[byteIndex] |= 1 << bitIndex;
94
+
95
+ // Pack signature: v + r + s
96
+ signaturesOrAddresses[dataIndex] = signature.v;
97
+ dataIndex++;
98
+
99
+ // Pack r (32 bytes)
100
+ const rBytes = Buffer.from(signature.r.slice(2), 'hex');
101
+ signaturesOrAddresses.set(rBytes, dataIndex);
102
+ dataIndex += 32;
103
+
104
+ // Pack s (32 bytes)
105
+ const sBytes = Buffer.from(signature.s.slice(2), 'hex');
106
+ signaturesOrAddresses.set(sBytes, dataIndex);
107
+ dataIndex += 32;
108
+ } else {
109
+ // Pack address only (20 bytes)
110
+ const addrBytes = Buffer.from(attestation.addr.slice(2), 'hex');
111
+ signaturesOrAddresses.set(addrBytes, dataIndex);
112
+ dataIndex += 20;
113
+ }
114
+ }
115
+
116
+ return {
117
+ signatureIndices: `0x${Buffer.from(signatureIndices).toString('hex')}`,
118
+ signaturesOrAddresses: `0x${Buffer.from(signaturesOrAddresses).toString('hex')}`,
119
+ };
120
+ }
121
+ }
@@ -1 +1,2 @@
1
1
  export * from './committee_attestation.js';
2
+ export * from './attestations_and_signers.js';
@@ -2,6 +2,8 @@
2
2
  import { Buffer32 } from '@aztec/foundation/buffer';
3
3
  import { randomBigInt } from '@aztec/foundation/crypto';
4
4
  import { schemas } from '@aztec/foundation/schemas';
5
+ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
6
+ import type { FieldsOf } from '@aztec/foundation/types';
5
7
 
6
8
  import { z } from 'zod';
7
9
 
@@ -32,6 +34,10 @@ export class L1PublishedData {
32
34
  Buffer32.random().toString(),
33
35
  );
34
36
  }
37
+
38
+ static fromFields(fields: FieldsOf<L1PublishedData>) {
39
+ return new L1PublishedData(fields.blockNumber, fields.timestamp, fields.blockHash);
40
+ }
35
41
  }
36
42
 
37
43
  export class PublishedL2Block {
@@ -42,11 +48,38 @@ export class PublishedL2Block {
42
48
  ) {}
43
49
 
44
50
  static get schema() {
45
- return z.object({
46
- block: L2Block.schema,
47
- l1: L1PublishedData.schema,
48
- attestations: z.array(CommitteeAttestation.schema),
49
- });
51
+ return z
52
+ .object({
53
+ block: L2Block.schema,
54
+ l1: L1PublishedData.schema,
55
+ attestations: z.array(CommitteeAttestation.schema),
56
+ })
57
+ .transform(obj => PublishedL2Block.fromFields(obj));
58
+ }
59
+
60
+ static fromBuffer(bufferOrReader: Buffer | BufferReader): PublishedL2Block {
61
+ const reader = BufferReader.asReader(bufferOrReader);
62
+ const block = reader.readObject(L2Block);
63
+ const l1BlockNumber = reader.readBigInt();
64
+ const l1BlockHash = reader.readString();
65
+ const l1Timestamp = reader.readBigInt();
66
+ const attestations = reader.readVector(CommitteeAttestation);
67
+ return new PublishedL2Block(block, new L1PublishedData(l1BlockNumber, l1Timestamp, l1BlockHash), attestations);
68
+ }
69
+
70
+ static fromFields(fields: FieldsOf<PublishedL2Block>) {
71
+ return new PublishedL2Block(fields.block, fields.l1, fields.attestations);
72
+ }
73
+
74
+ public toBuffer(): Buffer {
75
+ return serializeToBuffer(
76
+ this.block,
77
+ this.l1.blockNumber,
78
+ this.l1.blockHash,
79
+ this.l1.timestamp,
80
+ this.attestations.length,
81
+ this.attestations,
82
+ );
50
83
  }
51
84
  }
52
85
 
@@ -1,6 +1,6 @@
1
1
  import { times } from '@aztec/foundation/collection';
2
2
  import { Fr } from '@aztec/foundation/fields';
3
- import type { L2Block, L2BlockId, PublishedL2Block } from '@aztec/stdlib/block';
3
+ import { type L2Block, type L2BlockId, PublishedL2Block } from '@aztec/stdlib/block';
4
4
  import type { BlockHeader } from '@aztec/stdlib/tx';
5
5
 
6
6
  import { jestExpect as expect } from '@jest/expect';
@@ -14,11 +14,12 @@ export function testL2TipsStore(makeTipsStore: () => Promise<L2TipsStore>) {
14
14
  tipsStore = await makeTipsStore();
15
15
  });
16
16
 
17
- const makeBlock = (number: number): PublishedL2Block => ({
18
- block: { number, header: { hash: () => Promise.resolve(new Fr(number)) } as BlockHeader } as L2Block,
19
- l1: { blockNumber: BigInt(number), blockHash: `0x${number}`, timestamp: BigInt(number) },
20
- attestations: [],
21
- });
17
+ const makeBlock = (number: number): PublishedL2Block =>
18
+ PublishedL2Block.fromFields({
19
+ block: { number, header: { hash: () => Promise.resolve(new Fr(number)) } as BlockHeader } as L2Block,
20
+ l1: { blockNumber: BigInt(number), blockHash: `0x${number}`, timestamp: BigInt(number) },
21
+ attestations: [],
22
+ });
22
23
 
23
24
  const makeBlockId = (number: number): L2BlockId => ({
24
25
  number,
@@ -0,0 +1,122 @@
1
+ import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { type ZodFor, schemas } from '@aztec/foundation/schemas';
3
+ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
4
+
5
+ import { z } from 'zod';
6
+
7
+ import { BlockInfoSchema, type L2BlockInfo, deserializeBlockInfo, serializeBlockInfo } from './l2_block_info.js';
8
+ import { CommitteeAttestation } from './proposal/committee_attestation.js';
9
+
10
+ /** Subtype for invalid block validation results */
11
+ export type ValidateBlockNegativeResult =
12
+ | {
13
+ valid: false;
14
+ /** Identifiers from the invalid block */
15
+ block: L2BlockInfo;
16
+ /** Committee members at the epoch this block was proposed */
17
+ committee: EthAddress[];
18
+ /** Epoch in which this block was proposed */
19
+ epoch: bigint;
20
+ /** Proposer selection seed for the epoch */
21
+ seed: bigint;
22
+ /** List of committee members who signed this block proposal */
23
+ attestors: EthAddress[];
24
+ /** Committee attestations for this block as they were posted to L1 */
25
+ attestations: CommitteeAttestation[];
26
+ /** Reason for the block being invalid: not enough attestations were posted */
27
+ reason: 'insufficient-attestations';
28
+ }
29
+ | {
30
+ valid: false;
31
+ /** Identifiers from the invalid block */
32
+ block: L2BlockInfo;
33
+ /** Committee members at the epoch this block was proposed */
34
+ committee: EthAddress[];
35
+ /** Epoch in which this block was proposed */
36
+ epoch: bigint;
37
+ /** Proposer selection seed for the epoch */
38
+ seed: bigint;
39
+ /** List of committee members who signed this block proposal */
40
+ attestors: EthAddress[];
41
+ /** Committee attestations for this block as they were posted to L1 */
42
+ attestations: CommitteeAttestation[];
43
+ /** Reason for the block being invalid: an invalid attestation was posted */
44
+ reason: 'invalid-attestation';
45
+ /** Index in the attestations array of the invalid attestation posted */
46
+ invalidIndex: number;
47
+ };
48
+
49
+ /** Result type for validating a block attestations */
50
+ export type ValidateBlockResult = { valid: true } | ValidateBlockNegativeResult;
51
+
52
+ export const ValidateBlockResultSchema = z.union([
53
+ z.object({ valid: z.literal(true) }),
54
+ z.object({
55
+ valid: z.literal(false),
56
+ block: BlockInfoSchema,
57
+ committee: z.array(schemas.EthAddress),
58
+ epoch: schemas.BigInt,
59
+ seed: schemas.BigInt,
60
+ attestors: z.array(schemas.EthAddress),
61
+ attestations: z.array(CommitteeAttestation.schema),
62
+ reason: z.literal('insufficient-attestations'),
63
+ }),
64
+ z.object({
65
+ valid: z.literal(false),
66
+ block: BlockInfoSchema,
67
+ committee: z.array(schemas.EthAddress),
68
+ epoch: schemas.BigInt,
69
+ seed: schemas.BigInt,
70
+ attestors: z.array(schemas.EthAddress),
71
+ attestations: z.array(CommitteeAttestation.schema),
72
+ reason: z.literal('invalid-attestation'),
73
+ invalidIndex: z.number(),
74
+ }),
75
+ ]) satisfies ZodFor<ValidateBlockResult>;
76
+
77
+ export function serializeValidateBlockResult(result: ValidateBlockResult): Buffer {
78
+ if (result.valid) {
79
+ return serializeToBuffer(true);
80
+ }
81
+
82
+ const l2Block = serializeBlockInfo(result.block);
83
+ return serializeToBuffer(
84
+ result.valid,
85
+ result.reason,
86
+ l2Block.length,
87
+ l2Block,
88
+ result.committee.length,
89
+ result.committee,
90
+ result.epoch,
91
+ result.seed ?? 0n,
92
+ result.attestors.length,
93
+ result.attestors,
94
+ result.attestations.length,
95
+ result.attestations,
96
+ result.reason === 'invalid-attestation' ? result.invalidIndex : 0,
97
+ );
98
+ }
99
+
100
+ export function deserializeValidateBlockResult(bufferOrReader: Buffer | BufferReader): ValidateBlockResult {
101
+ const reader = BufferReader.asReader(bufferOrReader);
102
+ const valid = reader.readBoolean();
103
+ if (valid) {
104
+ return { valid };
105
+ }
106
+ const reason = reader.readString() as 'insufficient-attestations' | 'invalid-attestation';
107
+ const block = deserializeBlockInfo(reader.readBuffer());
108
+ const committee = reader.readVector(EthAddress);
109
+ const epoch = reader.readBigInt();
110
+ const seed = reader.readBigInt();
111
+ const attestors = reader.readVector(EthAddress);
112
+ const attestations = reader.readVector(CommitteeAttestation);
113
+ const invalidIndex = reader.readNumber();
114
+ if (reason === 'insufficient-attestations') {
115
+ return { valid, reason, block, committee, epoch, seed, attestors, attestations: attestations };
116
+ } else if (reason === 'invalid-attestation') {
117
+ return { valid, reason, block, committee, epoch, seed, attestors, invalidIndex, attestations: attestations };
118
+ } else {
119
+ const _: never = reason;
120
+ throw new Error(`Unknown reason: ${reason}`);
121
+ }
122
+ }
@@ -3,8 +3,9 @@ import type { ApiSchemaFor } from '@aztec/foundation/schemas';
3
3
  import { z } from 'zod';
4
4
 
5
5
  import { L2Block } from '../block/l2_block.js';
6
- import { type L2BlockSource, L2TipsSchema, ValidateBlockResultSchema } from '../block/l2_block_source.js';
6
+ import { type L2BlockSource, L2TipsSchema } from '../block/l2_block_source.js';
7
7
  import { PublishedL2Block } from '../block/published_l2_block.js';
8
+ import { ValidateBlockResultSchema } from '../block/validate_block_result.js';
8
9
  import {
9
10
  ContractClassPublicSchema,
10
11
  type ContractDataSource,
@@ -2,6 +2,8 @@ import type { Fr } from '@aztec/foundation/fields';
2
2
  import type { Timer } from '@aztec/foundation/timer';
3
3
 
4
4
  import type { L2Block } from '../block/l2_block.js';
5
+ import type { ChainConfig, SequencerConfig } from '../config/chain-config.js';
6
+ import type { L1RollupConstants } from '../epoch-helpers/index.js';
5
7
  import type { Gas } from '../gas/gas.js';
6
8
  import type { MerkleTreeWriteOperations } from '../trees/index.js';
7
9
  import type { BlockHeader } from '../tx/block_header.js';
@@ -59,13 +61,14 @@ export interface BuildBlockResult {
59
61
  usedTxs: Tx[];
60
62
  }
61
63
 
64
+ export type FullNodeBlockBuilderConfig = Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'> &
65
+ Pick<ChainConfig, 'l1ChainId' | 'rollupVersion'> &
66
+ Pick<SequencerConfig, 'txPublicSetupAllowList' | 'fakeProcessingDelayPerTxMs'>;
67
+
62
68
  export interface IFullNodeBlockBuilder {
63
- getConfig(): {
64
- l1GenesisTime: bigint;
65
- slotDuration: number;
66
- l1ChainId: number;
67
- rollupVersion: number;
68
- };
69
+ getConfig(): FullNodeBlockBuilderConfig;
70
+
71
+ updateConfig(config: Partial<FullNodeBlockBuilderConfig>): void;
69
72
 
70
73
  buildBlock(
71
74
  txs: Iterable<Tx> | AsyncIterable<Tx>,
@@ -3,7 +3,6 @@ import {
3
3
  NESTED_RECURSIVE_PROOF_LENGTH,
4
4
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
5
5
  RECURSIVE_PROOF_LENGTH,
6
- TUBE_PROOF_LENGTH,
7
6
  } from '@aztec/constants';
8
7
  import type { ZodFor } from '@aztec/foundation/schemas';
9
8
 
@@ -11,6 +10,7 @@ import { z } from 'zod';
11
10
 
12
11
  import { AvmCircuitInputs } from '../avm/avm.js';
13
12
  import { AvmProvingRequestSchema } from '../avm/avm_proving_request.js';
13
+ import { PrivateToPublicKernelCircuitPublicInputs } from '../kernel/private_to_public_kernel_circuit_public_inputs.js';
14
14
  import { BaseParityInputs } from '../parity/base_parity_inputs.js';
15
15
  import { ParityPublicInputs } from '../parity/parity_public_inputs.js';
16
16
  import { RootParityInputs } from '../parity/root_parity_inputs.js';
@@ -21,12 +21,11 @@ import { BlockMergeRollupInputs } from '../rollup/block_merge_rollup.js';
21
21
  import { BlockRootOrBlockMergePublicInputs } from '../rollup/block_root_or_block_merge_public_inputs.js';
22
22
  import { BlockRootRollupInputs, SingleTxBlockRootRollupInputs } from '../rollup/block_root_rollup.js';
23
23
  import { EmptyBlockRootRollupInputs } from '../rollup/empty_block_root_rollup_inputs.js';
24
- import { PaddingBlockRootRollupInputs } from '../rollup/index.js';
24
+ import { PaddingBlockRootRollupInputs, PublicTubePrivateInputs } from '../rollup/index.js';
25
25
  import { MergeRollupInputs } from '../rollup/merge_rollup.js';
26
26
  import { PrivateBaseRollupInputs } from '../rollup/private_base_rollup_inputs.js';
27
27
  import { PublicBaseRollupInputs } from '../rollup/public_base_rollup_inputs.js';
28
28
  import { RootRollupInputs, RootRollupPublicInputs } from '../rollup/root_rollup.js';
29
- import { TubeInputs } from '../rollup/tube_inputs.js';
30
29
  import type { ServerCircuitName } from '../stats/index.js';
31
30
  import { VerificationKeyData } from '../vks/verification_key.js';
32
31
 
@@ -80,6 +79,8 @@ export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): Se
80
79
  switch (type) {
81
80
  case ProvingRequestType.PUBLIC_VM:
82
81
  return 'avm-circuit';
82
+ case ProvingRequestType.PUBLIC_TUBE:
83
+ return 'public-tube';
83
84
  case ProvingRequestType.PRIVATE_BASE_ROLLUP:
84
85
  return 'private-base-rollup';
85
86
  case ProvingRequestType.PUBLIC_BASE_ROLLUP:
@@ -102,8 +103,6 @@ export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): Se
102
103
  return 'base-parity';
103
104
  case ProvingRequestType.ROOT_PARITY:
104
105
  return 'root-parity';
105
- case ProvingRequestType.TUBE_PROOF:
106
- return 'tube-circuit';
107
106
  default: {
108
107
  const _exhaustive: never = type;
109
108
  throw new Error(`Cannot find circuit name for proving request type: ${type}`);
@@ -115,6 +114,7 @@ export const ProvingJobInputs = z.discriminatedUnion('type', [
115
114
  AvmProvingRequestSchema,
116
115
  z.object({ type: z.literal(ProvingRequestType.BASE_PARITY), inputs: BaseParityInputs.schema }),
117
116
  z.object({ type: z.literal(ProvingRequestType.ROOT_PARITY), inputs: RootParityInputs.schema }),
117
+ z.object({ type: z.literal(ProvingRequestType.PUBLIC_TUBE), inputs: PublicTubePrivateInputs.schema }),
118
118
  z.object({ type: z.literal(ProvingRequestType.PRIVATE_BASE_ROLLUP), inputs: PrivateBaseRollupInputs.schema }),
119
119
  z.object({ type: z.literal(ProvingRequestType.PUBLIC_BASE_ROLLUP), inputs: PublicBaseRollupInputs.schema }),
120
120
  z.object({ type: z.literal(ProvingRequestType.MERGE_ROLLUP), inputs: MergeRollupInputs.schema }),
@@ -130,13 +130,14 @@ export const ProvingJobInputs = z.discriminatedUnion('type', [
130
130
  }),
131
131
  z.object({ type: z.literal(ProvingRequestType.BLOCK_MERGE_ROLLUP), inputs: BlockMergeRollupInputs.schema }),
132
132
  z.object({ type: z.literal(ProvingRequestType.ROOT_ROLLUP), inputs: RootRollupInputs.schema }),
133
- z.object({ type: z.literal(ProvingRequestType.TUBE_PROOF), inputs: TubeInputs.schema }),
134
133
  ]);
135
134
 
136
135
  export function getProvingJobInputClassFor(type: ProvingRequestType) {
137
136
  switch (type) {
138
137
  case ProvingRequestType.PUBLIC_VM:
139
138
  return AvmCircuitInputs;
139
+ case ProvingRequestType.PUBLIC_TUBE:
140
+ return PublicTubePrivateInputs;
140
141
  case ProvingRequestType.PRIVATE_BASE_ROLLUP:
141
142
  return PrivateBaseRollupInputs;
142
143
  case ProvingRequestType.PUBLIC_BASE_ROLLUP:
@@ -159,8 +160,6 @@ export function getProvingJobInputClassFor(type: ProvingRequestType) {
159
160
  return BaseParityInputs;
160
161
  case ProvingRequestType.ROOT_PARITY:
161
162
  return RootParityInputs;
162
- case ProvingRequestType.TUBE_PROOF:
163
- return TubeInputs;
164
163
  default: {
165
164
  const _exhaustive: never = type;
166
165
  throw new Error(`Cannot find circuit inputs class for proving type ${type}`);
@@ -172,6 +171,7 @@ export type ProvingJobInputs = z.infer<typeof ProvingJobInputs>;
172
171
 
173
172
  export type ProvingJobInputsMap = {
174
173
  [ProvingRequestType.PUBLIC_VM]: AvmCircuitInputs;
174
+ [ProvingRequestType.PUBLIC_TUBE]: PublicTubePrivateInputs;
175
175
  [ProvingRequestType.PRIVATE_BASE_ROLLUP]: PrivateBaseRollupInputs;
176
176
  [ProvingRequestType.PUBLIC_BASE_ROLLUP]: PublicBaseRollupInputs;
177
177
  [ProvingRequestType.MERGE_ROLLUP]: MergeRollupInputs;
@@ -183,7 +183,6 @@ export type ProvingJobInputsMap = {
183
183
  [ProvingRequestType.ROOT_ROLLUP]: RootRollupInputs;
184
184
  [ProvingRequestType.BASE_PARITY]: BaseParityInputs;
185
185
  [ProvingRequestType.ROOT_PARITY]: RootParityInputs;
186
- [ProvingRequestType.TUBE_PROOF]: TubeInputs;
187
186
  };
188
187
 
189
188
  export const ProvingJobResult = z.discriminatedUnion('type', [
@@ -191,6 +190,13 @@ export const ProvingJobResult = z.discriminatedUnion('type', [
191
190
  type: z.literal(ProvingRequestType.PUBLIC_VM),
192
191
  result: schemaForRecursiveProofAndVerificationKey(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED),
193
192
  }),
193
+ z.object({
194
+ type: z.literal(ProvingRequestType.PUBLIC_TUBE),
195
+ result: schemaForPublicInputsAndRecursiveProof(
196
+ PrivateToPublicKernelCircuitPublicInputs.schema,
197
+ NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
198
+ ),
199
+ }),
194
200
  z.object({
195
201
  type: z.literal(ProvingRequestType.PRIVATE_BASE_ROLLUP),
196
202
  result: schemaForPublicInputsAndRecursiveProof(
@@ -259,14 +265,14 @@ export const ProvingJobResult = z.discriminatedUnion('type', [
259
265
  type: z.literal(ProvingRequestType.ROOT_PARITY),
260
266
  result: schemaForPublicInputsAndRecursiveProof(ParityPublicInputs.schema, NESTED_RECURSIVE_PROOF_LENGTH),
261
267
  }),
262
- z.object({
263
- type: z.literal(ProvingRequestType.TUBE_PROOF),
264
- result: schemaForRecursiveProofAndVerificationKey(TUBE_PROOF_LENGTH),
265
- }),
266
268
  ]);
267
269
  export type ProvingJobResult = z.infer<typeof ProvingJobResult>;
268
270
  export type ProvingJobResultsMap = {
269
271
  [ProvingRequestType.PUBLIC_VM]: ProofAndVerificationKey<typeof AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED>;
272
+ [ProvingRequestType.PUBLIC_TUBE]: PublicInputsAndRecursiveProof<
273
+ PrivateToPublicKernelCircuitPublicInputs,
274
+ typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
275
+ >;
270
276
  [ProvingRequestType.PRIVATE_BASE_ROLLUP]: PublicInputsAndRecursiveProof<
271
277
  BaseOrMergeRollupPublicInputs,
272
278
  typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
@@ -305,7 +311,6 @@ export type ProvingJobResultsMap = {
305
311
  ParityPublicInputs,
306
312
  typeof NESTED_RECURSIVE_PROOF_LENGTH
307
313
  >;
308
- [ProvingRequestType.TUBE_PROOF]: ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>;
309
314
  };
310
315
 
311
316
  export type ProvingRequestResultFor<T extends ProvingRequestType> = { type: T; result: ProvingJobResultsMap[T] };
@@ -3,10 +3,10 @@ import type {
3
3
  NESTED_RECURSIVE_PROOF_LENGTH,
4
4
  NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
5
5
  RECURSIVE_PROOF_LENGTH,
6
- TUBE_PROOF_LENGTH,
7
6
  } from '@aztec/constants';
8
7
 
9
8
  import type { AvmCircuitInputs } from '../avm/avm.js';
9
+ import type { PrivateToPublicKernelCircuitPublicInputs } from '../kernel/private_to_public_kernel_circuit_public_inputs.js';
10
10
  import type { BaseParityInputs } from '../parity/base_parity_inputs.js';
11
11
  import type { ParityPublicInputs } from '../parity/parity_public_inputs.js';
12
12
  import type { RootParityInputs } from '../parity/root_parity_inputs.js';
@@ -15,12 +15,11 @@ import type { BlockMergeRollupInputs } from '../rollup/block_merge_rollup.js';
15
15
  import type { BlockRootOrBlockMergePublicInputs } from '../rollup/block_root_or_block_merge_public_inputs.js';
16
16
  import type { BlockRootRollupInputs, SingleTxBlockRootRollupInputs } from '../rollup/block_root_rollup.js';
17
17
  import type { EmptyBlockRootRollupInputs } from '../rollup/empty_block_root_rollup_inputs.js';
18
- import type { PaddingBlockRootRollupInputs } from '../rollup/index.js';
18
+ import type { PaddingBlockRootRollupInputs, PublicTubePrivateInputs } from '../rollup/index.js';
19
19
  import type { MergeRollupInputs } from '../rollup/merge_rollup.js';
20
20
  import type { PrivateBaseRollupInputs } from '../rollup/private_base_rollup_inputs.js';
21
21
  import type { PublicBaseRollupInputs } from '../rollup/public_base_rollup_inputs.js';
22
22
  import type { RootRollupInputs, RootRollupPublicInputs } from '../rollup/root_rollup.js';
23
- import type { TubeInputs } from '../rollup/tube_inputs.js';
24
23
  import type { Tx } from '../tx/tx.js';
25
24
  import type { ProofAndVerificationKey, PublicInputsAndRecursiveProof } from './proving-job.js';
26
25
 
@@ -48,6 +47,17 @@ export interface ServerCircuitProver {
48
47
  epochNumber?: number,
49
48
  ): Promise<PublicInputsAndRecursiveProof<ParityPublicInputs, typeof NESTED_RECURSIVE_PROOF_LENGTH>>;
50
49
 
50
+ getPublicTubeProof(
51
+ inputs: PublicTubePrivateInputs,
52
+ signal?: AbortSignal,
53
+ epochNumber?: number,
54
+ ): Promise<
55
+ PublicInputsAndRecursiveProof<
56
+ PrivateToPublicKernelCircuitPublicInputs,
57
+ typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH
58
+ >
59
+ >;
60
+
51
61
  /**
52
62
  * Creates a proof for the given input.
53
63
  * @param input - Input to the circuit.
@@ -68,16 +78,6 @@ export interface ServerCircuitProver {
68
78
  PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
69
79
  >;
70
80
 
71
- /**
72
- * Get a recursively verified client IVC proof (making it a compatible honk proof for the rest of the rollup).
73
- * @param input - Input to the circuit.
74
- */
75
- getTubeProof(
76
- tubeInput: TubeInputs,
77
- signal?: AbortSignal,
78
- epochNumber?: number,
79
- ): Promise<ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>>;
80
-
81
81
  /**
82
82
  * Creates a proof for the given input.
83
83
  * @param input - Input to the circuit.
@@ -1,5 +1,6 @@
1
1
  import type { SecretValue } from '@aztec/foundation/config';
2
2
  import type { EthAddress } from '@aztec/foundation/eth-address';
3
+ import type { Signature } from '@aztec/foundation/eth-signature';
3
4
  import { Fr } from '@aztec/foundation/fields';
4
5
  import { type ZodFor, schemas } from '@aztec/foundation/schemas';
5
6
  import type { SequencerConfig, SlasherConfig } from '@aztec/stdlib/interfaces/server';
@@ -9,6 +10,8 @@ import type { ProposedBlockHeader, StateReference, Tx } from '@aztec/stdlib/tx';
9
10
  import type { PeerId } from '@libp2p/interface';
10
11
  import { z } from 'zod';
11
12
 
13
+ import type { CommitteeAttestationsAndSigners } from '../block/index.js';
14
+
12
15
  /**
13
16
  * Validator client configuration
14
17
  */
@@ -67,4 +70,8 @@ export interface Validator {
67
70
 
68
71
  broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
69
72
  collectAttestations(proposal: BlockProposal, required: number, deadline: Date): Promise<BlockAttestation[]>;
73
+ signAttestationsAndSigners(
74
+ attestationsAndSigners: CommitteeAttestationsAndSigners,
75
+ proposer: EthAddress,
76
+ ): Promise<Signature>;
70
77
  }