@aztec/stdlib 3.0.0-nightly.20251114 → 3.0.0-nightly.20251118
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.
- package/dest/avm/avm.d.ts +139 -45
- package/dest/avm/avm.d.ts.map +1 -1
- package/dest/avm/avm.js +58 -19
- package/dest/avm/avm_proving_request.d.ts +21 -21
- package/dest/avm/public_data_write.d.ts +1 -1
- package/dest/avm/public_data_write.d.ts.map +1 -1
- package/dest/avm/revert_code.d.ts +2 -1
- package/dest/avm/revert_code.d.ts.map +1 -1
- package/dest/avm/revert_code.js +8 -8
- package/dest/block/body.d.ts +3 -6
- package/dest/block/body.d.ts.map +1 -1
- package/dest/block/body.js +6 -25
- package/dest/block/index.d.ts +1 -0
- package/dest/block/index.d.ts.map +1 -1
- package/dest/block/index.js +1 -0
- package/dest/block/l2_block.d.ts +5 -0
- package/dest/block/l2_block.d.ts.map +1 -1
- package/dest/block/l2_block.js +34 -4
- package/dest/block/l2_block_new.d.ts +97 -0
- package/dest/block/l2_block_new.d.ts.map +1 -0
- package/dest/block/l2_block_new.js +113 -0
- package/dest/checkpoint/checkpoint.d.ts +108 -0
- package/dest/checkpoint/checkpoint.d.ts.map +1 -0
- package/dest/checkpoint/checkpoint.js +39 -0
- package/dest/checkpoint/index.d.ts +1 -1
- package/dest/checkpoint/index.d.ts.map +1 -1
- package/dest/checkpoint/index.js +1 -1
- package/dest/interfaces/proving-job.d.ts +21 -21
- package/dest/logs/private_log.d.ts +1 -1
- package/dest/logs/private_log.d.ts.map +1 -1
- package/dest/logs/private_log.js +2 -5
- package/dest/messaging/in_hash.d.ts +4 -0
- package/dest/messaging/in_hash.d.ts.map +1 -0
- package/dest/messaging/in_hash.js +15 -0
- package/dest/messaging/index.d.ts +2 -0
- package/dest/messaging/index.d.ts.map +1 -1
- package/dest/messaging/index.js +2 -0
- package/dest/messaging/out_hash.d.ts +5 -0
- package/dest/messaging/out_hash.d.ts.map +1 -0
- package/dest/messaging/out_hash.js +28 -0
- package/dest/rollup/checkpoint_constant_data.d.ts +16 -0
- package/dest/rollup/checkpoint_constant_data.d.ts.map +1 -1
- package/dest/rollup/checkpoint_constant_data.js +17 -0
- package/dest/tests/factories.d.ts +21 -25
- package/dest/tests/factories.d.ts.map +1 -1
- package/dest/tests/factories.js +24 -121
- package/dest/tests/mocks.d.ts +17 -1
- package/dest/tests/mocks.d.ts.map +1 -1
- package/dest/tests/mocks.js +108 -4
- package/dest/tx/partial_state_reference.d.ts +3 -0
- package/dest/tx/partial_state_reference.d.ts.map +1 -1
- package/dest/tx/partial_state_reference.js +10 -0
- package/dest/tx/state_reference.d.ts +3 -0
- package/dest/tx/state_reference.d.ts.map +1 -1
- package/dest/tx/state_reference.js +9 -0
- package/dest/tx/tx_effect.d.ts +9 -6
- package/dest/tx/tx_effect.d.ts.map +1 -1
- package/dest/tx/tx_effect.js +53 -57
- package/dest/vks/verification_key.d.ts +9 -0
- package/dest/vks/verification_key.d.ts.map +1 -1
- package/dest/vks/verification_key.js +20 -0
- package/package.json +8 -8
- package/src/avm/avm.ts +66 -28
- package/src/avm/public_data_write.ts +1 -1
- package/src/avm/revert_code.ts +9 -8
- package/src/block/body.ts +7 -32
- package/src/block/index.ts +1 -0
- package/src/block/l2_block.ts +33 -2
- package/src/block/l2_block_new.ts +143 -0
- package/src/checkpoint/checkpoint.ts +46 -0
- package/src/checkpoint/index.ts +1 -1
- package/src/logs/private_log.ts +2 -3
- package/src/messaging/in_hash.ts +15 -0
- package/src/messaging/index.ts +2 -0
- package/src/messaging/out_hash.ts +36 -0
- package/src/rollup/checkpoint_constant_data.ts +20 -0
- package/src/tests/factories.ts +109 -211
- package/src/tests/mocks.ts +196 -4
- package/src/tx/partial_state_reference.ts +9 -0
- package/src/tx/state_reference.ts +9 -0
- package/src/tx/tx_effect.ts +61 -67
- package/src/vks/verification_key.ts +25 -0
- package/dest/checkpoint/checkpoint_body.d.ts +0 -4
- package/dest/checkpoint/checkpoint_body.d.ts.map +0 -1
- package/dest/checkpoint/checkpoint_body.js +0 -9
- package/src/checkpoint/checkpoint_body.ts +0 -10
package/src/avm/avm.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DEFAULT_MAX_DEBUG_LOG_MEMORY_READS } from '@aztec/constants';
|
|
1
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc';
|
|
3
4
|
|
|
@@ -666,9 +667,9 @@ export class AvmRevertCheckpointHint {
|
|
|
666
667
|
}
|
|
667
668
|
}
|
|
668
669
|
|
|
669
|
-
export class
|
|
670
|
-
export class
|
|
671
|
-
export class
|
|
670
|
+
export class AvmContractDbCreateCheckpointHint extends AvmCheckpointActionNoStateChangeHint {}
|
|
671
|
+
export class AvmContractDbCommitCheckpointHint extends AvmCheckpointActionNoStateChangeHint {}
|
|
672
|
+
export class AvmContractDbRevertCheckpointHint extends AvmCheckpointActionNoStateChangeHint {}
|
|
672
673
|
|
|
673
674
|
////////////////////////////////////////////////////////////////////////////
|
|
674
675
|
// Hints (other)
|
|
@@ -858,9 +859,9 @@ export class AvmExecutionHints {
|
|
|
858
859
|
public readonly contractClasses: AvmContractClassHint[] = [],
|
|
859
860
|
public readonly bytecodeCommitments: AvmBytecodeCommitmentHint[] = [],
|
|
860
861
|
public readonly debugFunctionNames: AvmDebugFunctionNameHint[] = [],
|
|
861
|
-
public readonly
|
|
862
|
-
public readonly
|
|
863
|
-
public readonly
|
|
862
|
+
public readonly contractDbCreateCheckpointHints: AvmContractDbCreateCheckpointHint[] = [],
|
|
863
|
+
public readonly contractDbCommitCheckpointHints: AvmContractDbCommitCheckpointHint[] = [],
|
|
864
|
+
public readonly contractDbRevertCheckpointHints: AvmContractDbRevertCheckpointHint[] = [],
|
|
864
865
|
// Merkle DB hints.
|
|
865
866
|
public startingTreeRoots: TreeSnapshots = TreeSnapshots.empty(),
|
|
866
867
|
public readonly getSiblingPathHints: AvmGetSiblingPathHint[] = [],
|
|
@@ -895,9 +896,9 @@ export class AvmExecutionHints {
|
|
|
895
896
|
obj.contractClasses?.map((c: any) => AvmContractClassHint.fromPlainObject(c)) || [],
|
|
896
897
|
obj.bytecodeCommitments?.map((b: any) => AvmBytecodeCommitmentHint.fromPlainObject(b)) || [],
|
|
897
898
|
obj.debugFunctionNames?.map((d: any) => AvmDebugFunctionNameHint.fromPlainObject(d)) || [],
|
|
898
|
-
obj.
|
|
899
|
-
obj.
|
|
900
|
-
obj.
|
|
899
|
+
obj.contractDbCreateCheckpointHints?.map((h: any) => AvmContractDbCreateCheckpointHint.fromPlainObject(h)) || [],
|
|
900
|
+
obj.contractDbCommitCheckpointHints?.map((h: any) => AvmContractDbCommitCheckpointHint.fromPlainObject(h)) || [],
|
|
901
|
+
obj.contractDbRevertCheckpointHints?.map((h: any) => AvmContractDbRevertCheckpointHint.fromPlainObject(h)) || [],
|
|
901
902
|
obj.startingTreeRoots ? TreeSnapshots.fromPlainObject(obj.startingTreeRoots) : TreeSnapshots.empty(),
|
|
902
903
|
obj.getSiblingPathHints?.map((h: any) => AvmGetSiblingPathHint.fromPlainObject(h)) || [],
|
|
903
904
|
obj.getPreviousValueIndexHints?.map((h: any) => AvmGetPreviousValueIndexHint.fromPlainObject(h)) || [],
|
|
@@ -934,9 +935,9 @@ export class AvmExecutionHints {
|
|
|
934
935
|
contractClasses: AvmContractClassHint.schema.array(),
|
|
935
936
|
bytecodeCommitments: AvmBytecodeCommitmentHint.schema.array(),
|
|
936
937
|
debugFunctionNames: AvmDebugFunctionNameHint.schema.array(),
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
938
|
+
contractDbCreateCheckpointHints: AvmContractDbCreateCheckpointHint.schema.array(),
|
|
939
|
+
contractDbCommitCheckpointHints: AvmContractDbCommitCheckpointHint.schema.array(),
|
|
940
|
+
contractDbRevertCheckpointHints: AvmContractDbRevertCheckpointHint.schema.array(),
|
|
940
941
|
startingTreeRoots: TreeSnapshots.schema,
|
|
941
942
|
getSiblingPathHints: AvmGetSiblingPathHint.schema.array(),
|
|
942
943
|
getPreviousValueIndexHints: AvmGetPreviousValueIndexHint.schema.array(),
|
|
@@ -959,9 +960,9 @@ export class AvmExecutionHints {
|
|
|
959
960
|
contractClasses,
|
|
960
961
|
bytecodeCommitments,
|
|
961
962
|
debugFunctionNames,
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
963
|
+
contractDbCreateCheckpointHints,
|
|
964
|
+
contractDbCommitCheckpointHints,
|
|
965
|
+
contractDbRevertCheckpointHints,
|
|
965
966
|
startingTreeRoots,
|
|
966
967
|
getSiblingPathHints,
|
|
967
968
|
getPreviousValueIndexHints,
|
|
@@ -983,9 +984,9 @@ export class AvmExecutionHints {
|
|
|
983
984
|
contractClasses,
|
|
984
985
|
bytecodeCommitments,
|
|
985
986
|
debugFunctionNames,
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
987
|
+
contractDbCreateCheckpointHints,
|
|
988
|
+
contractDbCommitCheckpointHints,
|
|
989
|
+
contractDbRevertCheckpointHints,
|
|
989
990
|
startingTreeRoots,
|
|
990
991
|
getSiblingPathHints,
|
|
991
992
|
getPreviousValueIndexHints,
|
|
@@ -1056,7 +1057,7 @@ export class PublicTxResult {
|
|
|
1056
1057
|
public gasUsed: GasUsed,
|
|
1057
1058
|
public revertCode: RevertCode,
|
|
1058
1059
|
public revertReason: SimulationError | undefined, // Revert reason, if any
|
|
1059
|
-
// These are only guaranteed to be present
|
|
1060
|
+
// These are only guaranteed to be present if the simulator is configured to collect them.
|
|
1060
1061
|
public processedPhases: ProcessedPhase[] | undefined,
|
|
1061
1062
|
public logs: DebugLog[] | undefined,
|
|
1062
1063
|
// For the proving request.
|
|
@@ -1121,17 +1122,52 @@ export class PublicTxResult {
|
|
|
1121
1122
|
}
|
|
1122
1123
|
}
|
|
1123
1124
|
|
|
1124
|
-
export
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1125
|
+
export class PublicSimulatorConfig {
|
|
1126
|
+
constructor(
|
|
1127
|
+
public readonly proverId: Fr,
|
|
1128
|
+
public readonly skipFeeEnforcement: boolean,
|
|
1129
|
+
public readonly collectCallMetadata: boolean, // processedPhases.
|
|
1130
|
+
public readonly collectHints: boolean, // hints.
|
|
1131
|
+
public readonly collectDebugLogs: boolean, // logs.
|
|
1132
|
+
public readonly maxDebugLogMemoryReads: number,
|
|
1133
|
+
public readonly collectStatistics: boolean, // timings etc.
|
|
1134
|
+
) {}
|
|
1135
|
+
|
|
1136
|
+
static from(obj: Partial<PublicSimulatorConfig>): PublicSimulatorConfig {
|
|
1137
|
+
return new PublicSimulatorConfig(
|
|
1138
|
+
obj.proverId ?? Fr.ZERO,
|
|
1139
|
+
obj.skipFeeEnforcement ?? false,
|
|
1140
|
+
obj.collectCallMetadata ?? false,
|
|
1141
|
+
obj.collectHints ?? false,
|
|
1142
|
+
obj.collectDebugLogs ?? false,
|
|
1143
|
+
obj.maxDebugLogMemoryReads ?? DEFAULT_MAX_DEBUG_LOG_MEMORY_READS,
|
|
1144
|
+
obj.collectStatistics ?? false,
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
static empty() {
|
|
1149
|
+
return PublicSimulatorConfig.from({});
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
static get schema() {
|
|
1153
|
+
return z
|
|
1154
|
+
.object({
|
|
1155
|
+
proverId: Fr.schema,
|
|
1156
|
+
skipFeeEnforcement: z.boolean(),
|
|
1157
|
+
collectCallMetadata: z.boolean(),
|
|
1158
|
+
collectHints: z.boolean(),
|
|
1159
|
+
collectDebugLogs: z.boolean(),
|
|
1160
|
+
maxDebugLogMemoryReads: z.number(),
|
|
1161
|
+
collectStatistics: z.boolean(),
|
|
1162
|
+
})
|
|
1163
|
+
.transform(PublicSimulatorConfig.from);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1131
1166
|
|
|
1132
1167
|
export class AvmFastSimulationInputs {
|
|
1133
1168
|
constructor(
|
|
1134
1169
|
public readonly wsRevision: WorldStateRevision,
|
|
1170
|
+
public readonly config: PublicSimulatorConfig,
|
|
1135
1171
|
public tx: AvmTxHint,
|
|
1136
1172
|
public globalVariables: GlobalVariables,
|
|
1137
1173
|
public protocolContracts: ProtocolContracts,
|
|
@@ -1140,6 +1176,7 @@ export class AvmFastSimulationInputs {
|
|
|
1140
1176
|
static empty() {
|
|
1141
1177
|
return new AvmFastSimulationInputs(
|
|
1142
1178
|
WorldStateRevision.empty(),
|
|
1179
|
+
PublicSimulatorConfig.empty(),
|
|
1143
1180
|
AvmTxHint.empty(),
|
|
1144
1181
|
GlobalVariables.empty(),
|
|
1145
1182
|
ProtocolContracts.empty(),
|
|
@@ -1150,13 +1187,14 @@ export class AvmFastSimulationInputs {
|
|
|
1150
1187
|
return z
|
|
1151
1188
|
.object({
|
|
1152
1189
|
wsRevision: WorldStateRevision.schema,
|
|
1190
|
+
config: PublicSimulatorConfig.schema,
|
|
1153
1191
|
tx: AvmTxHint.schema,
|
|
1154
1192
|
globalVariables: GlobalVariables.schema,
|
|
1155
1193
|
protocolContracts: ProtocolContracts.schema,
|
|
1156
1194
|
})
|
|
1157
1195
|
.transform(
|
|
1158
|
-
({ wsRevision, tx, globalVariables, protocolContracts }) =>
|
|
1159
|
-
new AvmFastSimulationInputs(wsRevision, tx, globalVariables, protocolContracts),
|
|
1196
|
+
({ wsRevision, config, tx, globalVariables, protocolContracts }) =>
|
|
1197
|
+
new AvmFastSimulationInputs(wsRevision, config, tx, globalVariables, protocolContracts),
|
|
1160
1198
|
);
|
|
1161
1199
|
}
|
|
1162
1200
|
|
package/src/avm/revert_code.ts
CHANGED
|
@@ -115,11 +115,15 @@ export class RevertCode {
|
|
|
115
115
|
return this.toBuffer().length;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
public static
|
|
119
|
-
if (!isRevertCodeEnum(
|
|
120
|
-
throw new Error(`Invalid RevertCode: ${
|
|
118
|
+
public static fromNumber(code: number): RevertCode {
|
|
119
|
+
if (!isRevertCodeEnum(code)) {
|
|
120
|
+
throw new Error(`Invalid RevertCode: ${code}`);
|
|
121
121
|
}
|
|
122
|
-
return new RevertCode(
|
|
122
|
+
return new RevertCode(code);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public static fromField(field: Fr): RevertCode {
|
|
126
|
+
return RevertCode.fromNumber(field.toNumber());
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
public static fromFields(fields: Fr[] | FieldReader): RevertCode {
|
|
@@ -130,10 +134,7 @@ export class RevertCode {
|
|
|
130
134
|
public static fromBuffer(buffer: Buffer | BufferReader): RevertCode {
|
|
131
135
|
const reader = BufferReader.asReader(buffer);
|
|
132
136
|
const code = reader.readBytes(RevertCode.PACKED_SIZE_IN_BYTES).readUInt8(0);
|
|
133
|
-
|
|
134
|
-
throw new Error(`Invalid RevertCode: ${code}`);
|
|
135
|
-
}
|
|
136
|
-
return new RevertCode(code);
|
|
137
|
+
return RevertCode.fromNumber(code);
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
private static readonly NUM_OPTIONS = 4;
|
package/src/block/body.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TxBlobData } from '@aztec/blob-lib/encoding';
|
|
2
2
|
import { timesParallel } from '@aztec/foundation/collection';
|
|
3
|
-
import {
|
|
4
|
-
import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
3
|
+
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
5
4
|
|
|
6
5
|
import { inspect } from 'util';
|
|
7
6
|
import { z } from 'zod';
|
|
@@ -9,14 +8,6 @@ import { z } from 'zod';
|
|
|
9
8
|
import type { ZodFor } from '../schemas/index.js';
|
|
10
9
|
import { TxEffect } from '../tx/tx_effect.js';
|
|
11
10
|
|
|
12
|
-
export { createBlockEndMarker };
|
|
13
|
-
|
|
14
|
-
export function getBlockBlobFields(txEffects: TxEffect[]) {
|
|
15
|
-
const blobFields = txEffects.flatMap(txEffect => txEffect.toBlobFields());
|
|
16
|
-
blobFields.push(createBlockEndMarker(txEffects.length));
|
|
17
|
-
return blobFields;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
11
|
export class Body {
|
|
21
12
|
constructor(public txEffects: TxEffect[]) {}
|
|
22
13
|
|
|
@@ -55,32 +46,16 @@ export class Body {
|
|
|
55
46
|
/**
|
|
56
47
|
* Returns a flat packed array of fields of all tx effects - used for blobs.
|
|
57
48
|
*/
|
|
58
|
-
|
|
59
|
-
return
|
|
49
|
+
toTxBlobData(): TxBlobData[] {
|
|
50
|
+
return this.txEffects.map(txEffect => txEffect.toTxBlobData());
|
|
60
51
|
}
|
|
61
52
|
|
|
62
53
|
/**
|
|
63
54
|
* Decodes a block from blob fields.
|
|
64
55
|
*/
|
|
65
|
-
static
|
|
66
|
-
const txEffects
|
|
67
|
-
|
|
68
|
-
while (!reader.isFinished()) {
|
|
69
|
-
txEffects.push(TxEffect.fromBlobFields(reader));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// If the fields are from a proven block, or are constructed by calling `toBlobFields`, the following errors should never throw.
|
|
73
|
-
|
|
74
|
-
if (!isBlockEndMarker(fields[fields.length - 1])) {
|
|
75
|
-
throw new Error('Block end marker not found');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const numTxs = getNumTxsFromBlockEndMarker(fields[fields.length - 1]);
|
|
79
|
-
if (numTxs !== txEffects.length) {
|
|
80
|
-
throw new Error(`Expected ${numTxs} txs, but got ${txEffects.length}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return new this(txEffects);
|
|
56
|
+
static fromTxBlobData(txBlobData: TxBlobData[]): Body {
|
|
57
|
+
const txEffects = txBlobData.map(data => TxEffect.fromTxBlobData(data));
|
|
58
|
+
return new Body(txEffects);
|
|
84
59
|
}
|
|
85
60
|
|
|
86
61
|
[inspect.custom]() {
|
package/src/block/index.ts
CHANGED
package/src/block/l2_block.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { type BlockBlobData, encodeBlockBlobData } from '@aztec/blob-lib/encoding';
|
|
1
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
3
4
|
import { bufferToHex, hexToBuffer } from '@aztec/foundation/string';
|
|
4
5
|
|
|
5
6
|
import { z } from 'zod';
|
|
6
7
|
|
|
7
|
-
import { getCheckpointBlobFields } from '../checkpoint/checkpoint_body.js';
|
|
8
8
|
import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js';
|
|
9
9
|
import type { BlockHeader } from '../tx/block_header.js';
|
|
10
10
|
import { Body } from './body.js';
|
|
@@ -14,6 +14,8 @@ import type { L2BlockInfo } from './l2_block_info.js';
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The data that makes up the rollup proof, with encoder decoder functions.
|
|
17
|
+
*
|
|
18
|
+
* @deprecated Use `L2BlockNew` instead.
|
|
17
19
|
*/
|
|
18
20
|
export class L2Block {
|
|
19
21
|
constructor(
|
|
@@ -152,7 +154,36 @@ export class L2Block {
|
|
|
152
154
|
* TODO(#17027): Remove this method from L2Block and create a dedicated Checkpoint class.
|
|
153
155
|
*/
|
|
154
156
|
public getCheckpointBlobFields() {
|
|
155
|
-
|
|
157
|
+
const blockBlobData = this.toBlobFields(true);
|
|
158
|
+
return [new Fr(blockBlobData.length + 1)].concat(blockBlobData);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public toBlobFields(isFirstBlock: boolean): Fr[] {
|
|
162
|
+
const blockBlobData = this.toBlockBlobData(isFirstBlock);
|
|
163
|
+
return encodeBlockBlobData(blockBlobData);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
public toBlockBlobData(isFirstBlock: boolean): BlockBlobData {
|
|
167
|
+
return {
|
|
168
|
+
blockEndMarker: {
|
|
169
|
+
numTxs: this.body.txEffects.length,
|
|
170
|
+
timestamp: this.header.globalVariables.timestamp,
|
|
171
|
+
blockNumber: this.number,
|
|
172
|
+
},
|
|
173
|
+
blockEndStateField: {
|
|
174
|
+
l1ToL2MessageNextAvailableLeafIndex: this.header.state.l1ToL2MessageTree.nextAvailableLeafIndex,
|
|
175
|
+
noteHashNextAvailableLeafIndex: this.header.state.partial.noteHashTree.nextAvailableLeafIndex,
|
|
176
|
+
nullifierNextAvailableLeafIndex: this.header.state.partial.nullifierTree.nextAvailableLeafIndex,
|
|
177
|
+
publicDataNextAvailableLeafIndex: this.header.state.partial.publicDataTree.nextAvailableLeafIndex,
|
|
178
|
+
totalManaUsed: this.header.totalManaUsed.toBigInt(),
|
|
179
|
+
},
|
|
180
|
+
lastArchiveRoot: this.header.lastArchive.root,
|
|
181
|
+
noteHashRoot: this.header.state.partial.noteHashTree.root,
|
|
182
|
+
nullifierRoot: this.header.state.partial.nullifierTree.root,
|
|
183
|
+
publicDataRoot: this.header.state.partial.publicDataTree.root,
|
|
184
|
+
l1ToL2MessageRoot: isFirstBlock ? this.header.state.l1ToL2MessageTree.root : undefined,
|
|
185
|
+
txs: this.body.toTxBlobData(),
|
|
186
|
+
};
|
|
156
187
|
}
|
|
157
188
|
|
|
158
189
|
/**
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { type BlockBlobData, encodeBlockBlobData } from '@aztec/blob-lib/encoding';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js';
|
|
8
|
+
import { BlockHeader } from '../tx/block_header.js';
|
|
9
|
+
import { Body } from './body.js';
|
|
10
|
+
import type { L2BlockInfo } from './l2_block_info.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* An L2 block with a header and a body.
|
|
14
|
+
* TODO: Delete the existing `L2Block` class and rename this to `L2Block`.
|
|
15
|
+
*/
|
|
16
|
+
export class L2BlockNew {
|
|
17
|
+
constructor(
|
|
18
|
+
/** Snapshot of archive tree after the block is applied. */
|
|
19
|
+
public archive: AppendOnlyTreeSnapshot,
|
|
20
|
+
/** Header of the block. */
|
|
21
|
+
public header: BlockHeader,
|
|
22
|
+
/** L2 block body. */
|
|
23
|
+
public body: Body,
|
|
24
|
+
private blockHash: Fr | undefined = undefined,
|
|
25
|
+
) {}
|
|
26
|
+
|
|
27
|
+
get number(): number {
|
|
28
|
+
return this.header.globalVariables.blockNumber;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get timestamp(): bigint {
|
|
32
|
+
return this.header.globalVariables.timestamp;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static get schema() {
|
|
36
|
+
return z
|
|
37
|
+
.object({
|
|
38
|
+
archive: AppendOnlyTreeSnapshot.schema,
|
|
39
|
+
header: BlockHeader.schema,
|
|
40
|
+
body: Body.schema,
|
|
41
|
+
})
|
|
42
|
+
.transform(({ archive, header, body }) => new L2BlockNew(archive, header, body));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Deserializes a block from a buffer
|
|
47
|
+
* @returns A deserialized L2 block.
|
|
48
|
+
*/
|
|
49
|
+
static fromBuffer(buf: Buffer | BufferReader) {
|
|
50
|
+
const reader = BufferReader.asReader(buf);
|
|
51
|
+
const header = reader.readObject(BlockHeader);
|
|
52
|
+
const archive = reader.readObject(AppendOnlyTreeSnapshot);
|
|
53
|
+
const body = reader.readObject(Body);
|
|
54
|
+
|
|
55
|
+
return new L2BlockNew(archive, header, body);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Serializes a block
|
|
60
|
+
* @returns A serialized L2 block as a Buffer.
|
|
61
|
+
*/
|
|
62
|
+
toBuffer() {
|
|
63
|
+
return serializeToBuffer(this.header, this.archive, this.body);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns the block's hash (hash of block header).
|
|
68
|
+
* @returns The block's hash.
|
|
69
|
+
*/
|
|
70
|
+
public async hash(): Promise<Fr> {
|
|
71
|
+
if (this.blockHash === undefined) {
|
|
72
|
+
this.blockHash = await this.header.hash();
|
|
73
|
+
}
|
|
74
|
+
return this.blockHash;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public toBlobFields(isFirstBlock: boolean): Fr[] {
|
|
78
|
+
const blockBlobData = this.toBlockBlobData(isFirstBlock);
|
|
79
|
+
return encodeBlockBlobData(blockBlobData);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public toBlockBlobData(isFirstBlock: boolean): BlockBlobData {
|
|
83
|
+
return {
|
|
84
|
+
blockEndMarker: {
|
|
85
|
+
numTxs: this.body.txEffects.length,
|
|
86
|
+
timestamp: this.header.globalVariables.timestamp,
|
|
87
|
+
blockNumber: this.number,
|
|
88
|
+
},
|
|
89
|
+
blockEndStateField: {
|
|
90
|
+
l1ToL2MessageNextAvailableLeafIndex: this.header.state.l1ToL2MessageTree.nextAvailableLeafIndex,
|
|
91
|
+
noteHashNextAvailableLeafIndex: this.header.state.partial.noteHashTree.nextAvailableLeafIndex,
|
|
92
|
+
nullifierNextAvailableLeafIndex: this.header.state.partial.nullifierTree.nextAvailableLeafIndex,
|
|
93
|
+
publicDataNextAvailableLeafIndex: this.header.state.partial.publicDataTree.nextAvailableLeafIndex,
|
|
94
|
+
totalManaUsed: this.header.totalManaUsed.toBigInt(),
|
|
95
|
+
},
|
|
96
|
+
lastArchiveRoot: this.header.lastArchive.root,
|
|
97
|
+
noteHashRoot: this.header.state.partial.noteHashTree.root,
|
|
98
|
+
nullifierRoot: this.header.state.partial.nullifierTree.root,
|
|
99
|
+
publicDataRoot: this.header.state.partial.publicDataTree.root,
|
|
100
|
+
l1ToL2MessageRoot: isFirstBlock ? this.header.state.l1ToL2MessageTree.root : undefined,
|
|
101
|
+
txs: this.body.toTxBlobData(),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Returns stats used for logging.
|
|
107
|
+
* @returns Stats on tx count, number, and log size and count.
|
|
108
|
+
*/
|
|
109
|
+
getStats() {
|
|
110
|
+
const logsStats = {
|
|
111
|
+
privateLogCount: this.body.txEffects.reduce((logCount, txEffect) => logCount + txEffect.privateLogs.length, 0),
|
|
112
|
+
publicLogCount: this.body.txEffects.reduce((logCount, txEffect) => logCount + txEffect.publicLogs.length, 0),
|
|
113
|
+
contractClassLogCount: this.body.txEffects.reduce(
|
|
114
|
+
(logCount, txEffect) => logCount + txEffect.contractClassLogs.length,
|
|
115
|
+
0,
|
|
116
|
+
),
|
|
117
|
+
contractClassLogSize: this.body.txEffects.reduce(
|
|
118
|
+
(totalLogSize, txEffect) =>
|
|
119
|
+
totalLogSize + txEffect.contractClassLogs.reduce((acc, log) => acc + log.emittedLength, 0),
|
|
120
|
+
0,
|
|
121
|
+
),
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
txCount: this.body.txEffects.length,
|
|
126
|
+
blockNumber: this.number,
|
|
127
|
+
blockTimestamp: Number(this.header.globalVariables.timestamp),
|
|
128
|
+
...logsStats,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
toBlockInfo(): L2BlockInfo {
|
|
133
|
+
return {
|
|
134
|
+
blockHash: this.blockHash,
|
|
135
|
+
archive: this.archive.root,
|
|
136
|
+
lastArchive: this.header.lastArchive.root,
|
|
137
|
+
blockNumber: this.number,
|
|
138
|
+
slotNumber: Number(this.header.getSlot()),
|
|
139
|
+
txCount: this.body.txEffects.length,
|
|
140
|
+
timestamp: this.header.globalVariables.timestamp,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
3
|
+
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
import { L2BlockNew } from '../block/l2_block_new.js';
|
|
7
|
+
import { CheckpointHeader } from '../rollup/checkpoint_header.js';
|
|
8
|
+
import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js';
|
|
9
|
+
|
|
10
|
+
export class Checkpoint {
|
|
11
|
+
constructor(
|
|
12
|
+
/** Snapshot of archive tree after the checkpoint is added. */
|
|
13
|
+
public archive: AppendOnlyTreeSnapshot,
|
|
14
|
+
/** Header of the checkpoint. */
|
|
15
|
+
public header: CheckpointHeader,
|
|
16
|
+
/** L2 blocks in the checkpoint. */
|
|
17
|
+
public blocks: L2BlockNew[],
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
static get schema() {
|
|
21
|
+
return z
|
|
22
|
+
.object({
|
|
23
|
+
archive: AppendOnlyTreeSnapshot.schema,
|
|
24
|
+
header: CheckpointHeader.schema,
|
|
25
|
+
blocks: z.array(L2BlockNew.schema),
|
|
26
|
+
})
|
|
27
|
+
.transform(({ archive, header, blocks }) => new Checkpoint(archive, header, blocks));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static fromBuffer(buf: Buffer | BufferReader) {
|
|
31
|
+
const reader = BufferReader.asReader(buf);
|
|
32
|
+
const archive = reader.readObject(AppendOnlyTreeSnapshot);
|
|
33
|
+
const header = reader.readObject(CheckpointHeader);
|
|
34
|
+
const blocks = reader.readVector(L2BlockNew);
|
|
35
|
+
return new Checkpoint(archive, header, blocks);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
toBuffer() {
|
|
39
|
+
return serializeToBuffer(this.archive, this.header, this.blocks.length, this.blocks);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public toBlobFields() {
|
|
43
|
+
const blocksBlobFields = this.blocks.flatMap((block, i) => block.toBlobFields(i === 0));
|
|
44
|
+
return [new Fr(blocksBlobFields.length + 1)].concat(blocksBlobFields);
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/checkpoint/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './checkpoint.js';
|
package/src/logs/private_log.ts
CHANGED
|
@@ -49,12 +49,11 @@ export class PrivateLog {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
toBlobFields(): Fr[] {
|
|
52
|
-
return
|
|
52
|
+
return this.getEmittedFields();
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
static fromBlobFields(fields: Fr[] | FieldReader) {
|
|
55
|
+
static fromBlobFields(emittedLength: number, fields: Fr[] | FieldReader) {
|
|
56
56
|
const reader = FieldReader.asReader(fields);
|
|
57
|
-
const emittedLength = reader.readU32();
|
|
58
57
|
const emittedFields = reader.readFieldArray(emittedLength);
|
|
59
58
|
return new PrivateLog(padArrayEnd(emittedFields, Fr.ZERO, PRIVATE_LOG_SIZE_IN_FIELDS), emittedLength);
|
|
60
59
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
3
|
+
import { sha256Trunc } from '@aztec/foundation/crypto';
|
|
4
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
+
import { MerkleTreeCalculator } from '@aztec/foundation/trees';
|
|
6
|
+
|
|
7
|
+
/** Computes the inHash for a block's ContentCommitment given its l1 to l2 messages. */
|
|
8
|
+
export async function computeInHashFromL1ToL2Messages(unpaddedL1ToL2Messages: Fr[]): Promise<Fr> {
|
|
9
|
+
const l1ToL2Messages = padArrayEnd<Fr, number>(unpaddedL1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
10
|
+
const hasher = (left: Buffer, right: Buffer) =>
|
|
11
|
+
Promise.resolve(sha256Trunc(Buffer.concat([left, right])) as Buffer<ArrayBuffer>);
|
|
12
|
+
const parityHeight = Math.ceil(Math.log2(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP));
|
|
13
|
+
const parityCalculator = await MerkleTreeCalculator.create(parityHeight, Fr.ZERO.toBuffer(), hasher);
|
|
14
|
+
return new Fr(await parityCalculator.computeTreeRoot(l1ToL2Messages.map(msg => msg.toBuffer())));
|
|
15
|
+
}
|
package/src/messaging/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './in_hash.js';
|
|
1
2
|
export * from './inbox_leaf.js';
|
|
2
3
|
export * from './l1_to_l2_message.js';
|
|
3
4
|
export * from './l1_to_l2_message_source.js';
|
|
@@ -5,3 +6,4 @@ export * from './l1_actor.js';
|
|
|
5
6
|
export * from './l2_actor.js';
|
|
6
7
|
export * from './l2_to_l1_message.js';
|
|
7
8
|
export * from './l2_to_l1_membership.js';
|
|
9
|
+
export * from './out_hash.js';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { UnbalancedMerkleTreeCalculator, computeUnbalancedMerkleTreeRoot } from '@aztec/foundation/trees';
|
|
3
|
+
|
|
4
|
+
export function computeTxOutHash(messages: Fr[]): Fr {
|
|
5
|
+
if (!messages.length) {
|
|
6
|
+
return Fr.ZERO;
|
|
7
|
+
}
|
|
8
|
+
// Tx out hash is the root of the unbalanced merkle tree of all the messages.
|
|
9
|
+
// Zero hashes (which should not happen) are not compressed.
|
|
10
|
+
return Fr.fromBuffer(computeUnbalancedMerkleTreeRoot(messages.map(msg => msg.toBuffer())));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function computeBlockOutHash(messagesPerBlock: Fr[][]): Fr {
|
|
14
|
+
const txOutHashes = messagesPerBlock.map(messages => computeTxOutHash(messages));
|
|
15
|
+
return aggregateOutHashes(txOutHashes);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function computeCheckpointOutHash(messagesForAllTxs: Fr[][][]): Fr {
|
|
19
|
+
const blockOutHashes = messagesForAllTxs.map(block => computeBlockOutHash(block));
|
|
20
|
+
return aggregateOutHashes(blockOutHashes);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// The root of this tree should match the `out_hash` calculated in the circuits. Zero hashes are compressed to reduce
|
|
24
|
+
// cost if the non-zero leaves result in a shorter path.
|
|
25
|
+
function aggregateOutHashes(outHashes: Fr[]): Fr {
|
|
26
|
+
if (!outHashes.length) {
|
|
27
|
+
return Fr.ZERO;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const valueToCompress = Buffer.alloc(32);
|
|
31
|
+
const tree = UnbalancedMerkleTreeCalculator.create(
|
|
32
|
+
outHashes.map(hash => hash.toBuffer()),
|
|
33
|
+
valueToCompress,
|
|
34
|
+
);
|
|
35
|
+
return Fr.fromBuffer(tree.getRoot());
|
|
36
|
+
}
|
|
@@ -3,6 +3,8 @@ import { Fr } from '@aztec/foundation/fields';
|
|
|
3
3
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
4
4
|
import type { FieldsOf } from '@aztec/foundation/types';
|
|
5
5
|
|
|
6
|
+
import { inspect } from 'util';
|
|
7
|
+
|
|
6
8
|
import { AztecAddress } from '../aztec-address/index.js';
|
|
7
9
|
import { GasFees } from '../gas/gas_fees.js';
|
|
8
10
|
|
|
@@ -81,4 +83,22 @@ export class CheckpointConstantData {
|
|
|
81
83
|
reader.readObject(GasFees),
|
|
82
84
|
);
|
|
83
85
|
}
|
|
86
|
+
|
|
87
|
+
toInspect() {
|
|
88
|
+
return {
|
|
89
|
+
chainId: this.chainId.toNumber(),
|
|
90
|
+
version: this.version.toNumber(),
|
|
91
|
+
vkTreeRoot: this.vkTreeRoot.toString(),
|
|
92
|
+
protocolContractsHash: this.protocolContractsHash.toString(),
|
|
93
|
+
proverId: this.proverId.toString(),
|
|
94
|
+
slotNumber: this.slotNumber.toNumber(),
|
|
95
|
+
coinbase: this.coinbase.toString(),
|
|
96
|
+
feeRecipient: this.feeRecipient.toString(),
|
|
97
|
+
gasFees: this.gasFees.toInspect(),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
[inspect.custom]() {
|
|
102
|
+
return `CheckpointConstantData ${inspect(this.toInspect())}`;
|
|
103
|
+
}
|
|
84
104
|
}
|