@aztec/sequencer-client 0.32.0 → 0.33.0
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/client/sequencer-client.d.ts +8 -8
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +1 -1
- package/dest/config.d.ts +3 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +1 -1
- package/dest/global_variable_builder/config.d.ts +1 -1
- package/dest/global_variable_builder/config.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.d.ts +1 -1
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +1 -1
- package/dest/global_variable_builder/index.d.ts +2 -2
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/global_variable_builder/index.js +1 -1
- package/dest/global_variable_builder/viem-reader.d.ts +2 -2
- package/dest/global_variable_builder/viem-reader.d.ts.map +1 -1
- package/dest/publisher/config.d.ts +1 -1
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/index.d.ts +1 -1
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.d.ts +3 -3
- package/dest/publisher/l1-publisher.d.ts.map +1 -1
- package/dest/publisher/viem-tx-sender.d.ts +3 -3
- package/dest/publisher/viem-tx-sender.d.ts.map +1 -1
- package/dest/publisher/viem-tx-sender.js +1 -1
- package/dest/receiver.d.ts +1 -1
- package/dest/receiver.d.ts.map +1 -1
- package/dest/sequencer/abstract_phase_manager.d.ts +21 -9
- package/dest/sequencer/abstract_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/abstract_phase_manager.js +38 -39
- package/dest/sequencer/app_logic_phase_manager.d.ts +7 -6
- package/dest/sequencer/app_logic_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/app_logic_phase_manager.js +3 -3
- package/dest/sequencer/hints_builder.d.ts +9 -5
- package/dest/sequencer/hints_builder.d.ts.map +1 -1
- package/dest/sequencer/hints_builder.js +24 -4
- package/dest/sequencer/phase_manager_factory.d.ts +7 -7
- package/dest/sequencer/phase_manager_factory.d.ts.map +1 -1
- package/dest/sequencer/phase_manager_factory.js +5 -4
- package/dest/sequencer/public_processor.d.ts +10 -7
- package/dest/sequencer/public_processor.d.ts.map +1 -1
- package/dest/sequencer/public_processor.js +65 -27
- package/dest/sequencer/sequencer.d.ts +11 -21
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +33 -38
- package/dest/sequencer/setup_phase_manager.d.ts +7 -6
- package/dest/sequencer/setup_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/setup_phase_manager.js +2 -2
- package/dest/sequencer/tail_phase_manager.d.ts +11 -6
- package/dest/sequencer/tail_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/tail_phase_manager.js +28 -3
- package/dest/sequencer/teardown_phase_manager.d.ts +7 -6
- package/dest/sequencer/teardown_phase_manager.d.ts.map +1 -1
- package/dest/sequencer/teardown_phase_manager.js +2 -2
- package/dest/sequencer/tx_validator.d.ts +3 -3
- package/dest/sequencer/tx_validator.d.ts.map +1 -1
- package/dest/sequencer/tx_validator.js +9 -8
- package/dest/sequencer/tx_validator_factory.d.ts +3 -3
- package/dest/sequencer/tx_validator_factory.d.ts.map +1 -1
- package/dest/sequencer/utils.d.ts +1 -1
- package/dest/sequencer/utils.d.ts.map +1 -1
- package/dest/sequencer/utils.js +8 -7
- package/dest/simulator/index.d.ts +2 -2
- package/dest/simulator/index.d.ts.map +1 -1
- package/dest/simulator/public_executor.d.ts +5 -5
- package/dest/simulator/public_executor.d.ts.map +1 -1
- package/dest/simulator/public_executor.js +2 -2
- package/dest/simulator/public_kernel.d.ts +4 -4
- package/dest/simulator/public_kernel.d.ts.map +1 -1
- package/dest/simulator/public_kernel.js +1 -1
- package/package.json +32 -15
- package/src/client/sequencer-client.ts +8 -8
- package/src/config.ts +5 -5
- package/src/global_variable_builder/config.ts +1 -1
- package/src/global_variable_builder/global_builder.ts +1 -1
- package/src/global_variable_builder/index.ts +2 -2
- package/src/global_variable_builder/viem-reader.ts +6 -6
- package/src/publisher/config.ts +1 -1
- package/src/publisher/index.ts +1 -1
- package/src/publisher/l1-publisher.ts +4 -4
- package/src/publisher/viem-tx-sender.ts +12 -12
- package/src/receiver.ts +1 -1
- package/src/sequencer/abstract_phase_manager.ts +88 -77
- package/src/sequencer/app_logic_phase_manager.ts +13 -8
- package/src/sequencer/hints_builder.ts +49 -16
- package/src/sequencer/phase_manager_factory.ts +11 -10
- package/src/sequencer/public_processor.ts +105 -59
- package/src/sequencer/sequencer.ts +52 -61
- package/src/sequencer/setup_phase_manager.ts +12 -7
- package/src/sequencer/tail_phase_manager.ts +77 -8
- package/src/sequencer/teardown_phase_manager.ts +12 -7
- package/src/sequencer/tx_validator.ts +18 -10
- package/src/sequencer/tx_validator_factory.ts +3 -3
- package/src/sequencer/utils.ts +8 -7
- package/src/simulator/index.ts +5 -4
- package/src/simulator/public_executor.ts +20 -11
- package/src/simulator/public_kernel.ts +8 -7
- package/dest/utils.d.ts +0 -12
- package/dest/utils.d.ts.map +0 -1
- package/dest/utils.js +0 -16
- package/src/utils.ts +0 -16
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
type BlockProver,
|
|
3
|
+
type FailedTx,
|
|
4
|
+
type ProcessedTx,
|
|
5
|
+
type SimulationError,
|
|
5
6
|
Tx,
|
|
6
|
-
getPreviousOutputAndProof,
|
|
7
7
|
makeEmptyProcessedTx,
|
|
8
8
|
makeProcessedTx,
|
|
9
9
|
toTxEffect,
|
|
10
10
|
validateProcessedTx,
|
|
11
11
|
} from '@aztec/circuit-types';
|
|
12
|
-
import { TxSequencerProcessingStats } from '@aztec/circuit-types/stats';
|
|
13
|
-
import { GlobalVariables, Header } from '@aztec/circuits.js';
|
|
12
|
+
import { type TxSequencerProcessingStats } from '@aztec/circuit-types/stats';
|
|
13
|
+
import { type GlobalVariables, type Header, type KernelCircuitPublicInputs } from '@aztec/circuits.js';
|
|
14
|
+
import { type ProcessReturnValues } from '@aztec/foundation/abi';
|
|
14
15
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
15
16
|
import { Timer } from '@aztec/foundation/timer';
|
|
16
|
-
import { PublicExecutor, PublicStateDB, SimulationProvider } from '@aztec/simulator';
|
|
17
|
-
import { ContractDataSource } from '@aztec/types/contracts';
|
|
18
|
-
import { MerkleTreeOperations } from '@aztec/world-state';
|
|
17
|
+
import { PublicExecutor, type PublicStateDB, type SimulationProvider } from '@aztec/simulator';
|
|
18
|
+
import { type ContractDataSource } from '@aztec/types/contracts';
|
|
19
|
+
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
19
20
|
|
|
20
|
-
import { PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
21
|
+
import { type PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
21
22
|
import { ContractsDataSourcePublicDB, WorldStateDB, WorldStatePublicDB } from '../simulator/public_executor.js';
|
|
22
23
|
import { RealPublicKernelCircuitSimulator } from '../simulator/public_kernel.js';
|
|
23
|
-
import { AbstractPhaseManager } from './abstract_phase_manager.js';
|
|
24
|
+
import { type AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
24
25
|
import { PhaseManagerFactory } from './phase_manager_factory.js';
|
|
26
|
+
import { type TxValidator } from './tx_validator.js';
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Creates new instances of PublicProcessor given the provided merkle tree db and contract data source.
|
|
@@ -84,60 +86,45 @@ export class PublicProcessor {
|
|
|
84
86
|
* @param txs - Txs to process.
|
|
85
87
|
* @returns The list of processed txs with their circuit simulation outputs.
|
|
86
88
|
*/
|
|
87
|
-
public async process(
|
|
89
|
+
public async process(
|
|
90
|
+
txs: Tx[],
|
|
91
|
+
maxTransactions = txs.length,
|
|
92
|
+
blockProver?: BlockProver,
|
|
93
|
+
txValidator?: TxValidator,
|
|
94
|
+
): Promise<[ProcessedTx[], FailedTx[], ProcessReturnValues[]]> {
|
|
88
95
|
// The processor modifies the tx objects in place, so we need to clone them.
|
|
89
96
|
txs = txs.map(tx => Tx.clone(tx));
|
|
90
97
|
const result: ProcessedTx[] = [];
|
|
91
98
|
const failed: FailedTx[] = [];
|
|
99
|
+
const returns: ProcessReturnValues[] = [];
|
|
92
100
|
|
|
93
101
|
for (const tx of txs) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.publicKernel,
|
|
99
|
-
this.globalVariables,
|
|
100
|
-
this.historicalHeader,
|
|
101
|
-
this.publicContractsDB,
|
|
102
|
-
this.publicStateDB,
|
|
103
|
-
);
|
|
104
|
-
this.log(`Beginning processing in phase ${phase?.phase} for tx ${tx.getTxHash()}`);
|
|
105
|
-
let { publicKernelPublicInput, previousProof: proof } = getPreviousOutputAndProof(tx, undefined, undefined);
|
|
106
|
-
let revertReason: SimulationError | undefined;
|
|
107
|
-
const timer = new Timer();
|
|
102
|
+
// only process up to the limit of the block
|
|
103
|
+
if (result.length >= maxTransactions) {
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
108
106
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.publicStateDB,
|
|
124
|
-
);
|
|
107
|
+
const [processedTx, returnValues] = !tx.hasPublicCalls()
|
|
108
|
+
? [makeProcessedTx(tx, tx.data.toKernelCircuitPublicInputs(), tx.proof)]
|
|
109
|
+
: await this.processTxWithPublicCalls(tx);
|
|
110
|
+
validateProcessedTx(processedTx);
|
|
111
|
+
// Re-validate the transaction
|
|
112
|
+
if (txValidator) {
|
|
113
|
+
// Only accept processed transactions that are not double-spends,
|
|
114
|
+
// public functions emitting nullifiers would pass earlier check but fail here.
|
|
115
|
+
// Note that we're checking all nullifiers generated in the private execution twice,
|
|
116
|
+
// we could store the ones already checked and skip them here as an optimization.
|
|
117
|
+
const [_, invalid] = await txValidator.validateTxs([processedTx]);
|
|
118
|
+
if (invalid.length) {
|
|
119
|
+
throw new Error(`Transaction ${invalid[0].hash} invalid after processing public functions`);
|
|
120
|
+
}
|
|
125
121
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
result.push(
|
|
131
|
-
|
|
132
|
-
this.log(`Processed public part of ${tx.data.endNonRevertibleData.newNullifiers[0].value}`, {
|
|
133
|
-
eventName: 'tx-sequencer-processing',
|
|
134
|
-
duration: timer.ms(),
|
|
135
|
-
effectsSize: toTxEffect(processedTransaction).toBuffer().length,
|
|
136
|
-
publicDataUpdateRequests:
|
|
137
|
-
processedTransaction.data.combinedData.publicDataUpdateRequests.filter(x => !x.leafSlot.isZero()).length ??
|
|
138
|
-
0,
|
|
139
|
-
...tx.getStats(),
|
|
140
|
-
} satisfies TxSequencerProcessingStats);
|
|
122
|
+
// if we were given a prover then send the transaction to it for proving
|
|
123
|
+
if (blockProver) {
|
|
124
|
+
await blockProver.addNewTx(processedTx);
|
|
125
|
+
}
|
|
126
|
+
result.push(processedTx);
|
|
127
|
+
returns.push(returnValues);
|
|
141
128
|
} catch (err: any) {
|
|
142
129
|
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
143
130
|
this.log.warn(`Failed to process tx ${tx.getTxHash()}: ${errorMessage}`);
|
|
@@ -146,10 +133,11 @@ export class PublicProcessor {
|
|
|
146
133
|
tx,
|
|
147
134
|
error: err instanceof Error ? err : new Error(errorMessage),
|
|
148
135
|
});
|
|
136
|
+
returns.push([]);
|
|
149
137
|
}
|
|
150
138
|
}
|
|
151
139
|
|
|
152
|
-
return [result, failed];
|
|
140
|
+
return [result, failed, returns];
|
|
153
141
|
}
|
|
154
142
|
|
|
155
143
|
/**
|
|
@@ -158,6 +146,64 @@ export class PublicProcessor {
|
|
|
158
146
|
*/
|
|
159
147
|
public makeEmptyProcessedTx(): ProcessedTx {
|
|
160
148
|
const { chainId, version } = this.globalVariables;
|
|
161
|
-
return makeEmptyProcessedTx(this.historicalHeader, chainId, version);
|
|
149
|
+
return makeEmptyProcessedTx(this.historicalHeader.clone(), chainId, version);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private async processTxWithPublicCalls(tx: Tx): Promise<[ProcessedTx, ProcessReturnValues | undefined]> {
|
|
153
|
+
let returnValues: ProcessReturnValues = undefined;
|
|
154
|
+
let phase: AbstractPhaseManager | undefined = PhaseManagerFactory.phaseFromTx(
|
|
155
|
+
tx,
|
|
156
|
+
this.db,
|
|
157
|
+
this.publicExecutor,
|
|
158
|
+
this.publicKernel,
|
|
159
|
+
this.globalVariables,
|
|
160
|
+
this.historicalHeader,
|
|
161
|
+
this.publicContractsDB,
|
|
162
|
+
this.publicStateDB,
|
|
163
|
+
);
|
|
164
|
+
this.log(`Beginning processing in phase ${phase?.phase} for tx ${tx.getTxHash()}`);
|
|
165
|
+
let proof = tx.proof;
|
|
166
|
+
let publicKernelPublicInput = tx.data.toPublicKernelCircuitPublicInputs();
|
|
167
|
+
let finalKernelOutput: KernelCircuitPublicInputs | undefined;
|
|
168
|
+
let revertReason: SimulationError | undefined;
|
|
169
|
+
const timer = new Timer();
|
|
170
|
+
while (phase) {
|
|
171
|
+
const output = await phase.handle(tx, publicKernelPublicInput, proof);
|
|
172
|
+
if (phase.phase === PublicKernelPhase.APP_LOGIC) {
|
|
173
|
+
returnValues = output.returnValues;
|
|
174
|
+
}
|
|
175
|
+
publicKernelPublicInput = output.publicKernelOutput;
|
|
176
|
+
finalKernelOutput = output.finalKernelOutput;
|
|
177
|
+
proof = output.publicKernelProof;
|
|
178
|
+
revertReason ??= output.revertReason;
|
|
179
|
+
phase = PhaseManagerFactory.phaseFromOutput(
|
|
180
|
+
publicKernelPublicInput,
|
|
181
|
+
phase,
|
|
182
|
+
this.db,
|
|
183
|
+
this.publicExecutor,
|
|
184
|
+
this.publicKernel,
|
|
185
|
+
this.globalVariables,
|
|
186
|
+
this.historicalHeader,
|
|
187
|
+
this.publicContractsDB,
|
|
188
|
+
this.publicStateDB,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!finalKernelOutput) {
|
|
193
|
+
throw new Error('Final public kernel was not executed.');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const processedTx = makeProcessedTx(tx, finalKernelOutput, proof, revertReason);
|
|
197
|
+
|
|
198
|
+
this.log(`Processed public part of ${tx.getTxHash()}`, {
|
|
199
|
+
eventName: 'tx-sequencer-processing',
|
|
200
|
+
duration: timer.ms(),
|
|
201
|
+
effectsSize: toTxEffect(processedTx).toBuffer().length,
|
|
202
|
+
publicDataUpdateRequests:
|
|
203
|
+
processedTx.data.end.publicDataUpdateRequests.filter(x => !x.leafSlot.isZero()).length ?? 0,
|
|
204
|
+
...tx.getStats(),
|
|
205
|
+
} satisfies TxSequencerProcessingStats);
|
|
206
|
+
|
|
207
|
+
return [processedTx, returnValues];
|
|
162
208
|
}
|
|
163
209
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { L1ToL2MessageSource, L2Block, L2BlockSource, ProcessedTx, Tx } from '@aztec/circuit-types';
|
|
2
|
-
import { BlockProver, PROVING_STATUS } from '@aztec/circuit-types/interfaces';
|
|
3
|
-
import { L2BlockBuiltStats } from '@aztec/circuit-types/stats';
|
|
4
|
-
import { AztecAddress, EthAddress
|
|
1
|
+
import { type L1ToL2MessageSource, type L2Block, type L2BlockSource, type ProcessedTx, Tx } from '@aztec/circuit-types';
|
|
2
|
+
import { type BlockProver, PROVING_STATUS } from '@aztec/circuit-types/interfaces';
|
|
3
|
+
import { type L2BlockBuiltStats } from '@aztec/circuit-types/stats';
|
|
4
|
+
import { AztecAddress, EthAddress } from '@aztec/circuits.js';
|
|
5
5
|
import { Fr } from '@aztec/foundation/fields';
|
|
6
6
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
7
7
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
8
8
|
import { Timer, elapsed } from '@aztec/foundation/timer';
|
|
9
|
-
import { P2P } from '@aztec/p2p';
|
|
10
|
-
import { WorldStateStatus, WorldStateSynchronizer } from '@aztec/world-state';
|
|
9
|
+
import { type P2P } from '@aztec/p2p';
|
|
10
|
+
import { type WorldStateStatus, type WorldStateSynchronizer } from '@aztec/world-state';
|
|
11
11
|
|
|
12
|
-
import { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
|
|
13
|
-
import { L1Publisher } from '../publisher/l1-publisher.js';
|
|
14
|
-
import { SequencerConfig } from './config.js';
|
|
15
|
-
import { PublicProcessorFactory } from './public_processor.js';
|
|
16
|
-
import { TxValidator } from './tx_validator.js';
|
|
17
|
-
import { TxValidatorFactory } from './tx_validator_factory.js';
|
|
12
|
+
import { type GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
|
|
13
|
+
import { type L1Publisher } from '../publisher/l1-publisher.js';
|
|
14
|
+
import { type SequencerConfig } from './config.js';
|
|
15
|
+
import { type PublicProcessorFactory } from './public_processor.js';
|
|
16
|
+
import { type TxValidator } from './tx_validator.js';
|
|
17
|
+
import { type TxValidatorFactory } from './tx_validator_factory.js';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Sequencer client
|
|
@@ -193,57 +193,75 @@ export class Sequencer {
|
|
|
193
193
|
this.log.info(`Building block ${newBlockNumber} with ${validTxs.length} transactions`);
|
|
194
194
|
this.state = SequencerState.CREATING_BLOCK;
|
|
195
195
|
|
|
196
|
+
// Get l1 to l2 messages from the contract
|
|
197
|
+
this.log('Requesting L1 to L2 messages from contract');
|
|
198
|
+
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(BigInt(newBlockNumber));
|
|
199
|
+
this.log(`Retrieved ${l1ToL2Messages.length} L1 to L2 messages for block ${newBlockNumber}`);
|
|
200
|
+
|
|
196
201
|
// We create a fresh processor each time to reset any cached state (eg storage writes)
|
|
197
202
|
const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables);
|
|
198
|
-
|
|
203
|
+
|
|
204
|
+
const emptyTx = processor.makeEmptyProcessedTx();
|
|
205
|
+
|
|
206
|
+
const blockBuildingTimer = new Timer();
|
|
207
|
+
|
|
208
|
+
// We must initialise the block to be a power of 2 in size
|
|
209
|
+
const numRealTxs = validTxs.length;
|
|
210
|
+
const pow2 = Math.log2(numRealTxs);
|
|
211
|
+
const totalTxs = 2 ** Math.ceil(pow2);
|
|
212
|
+
const blockSize = Math.max(2, totalTxs);
|
|
213
|
+
const blockTicket = await this.prover.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages, emptyTx);
|
|
214
|
+
|
|
215
|
+
const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() =>
|
|
216
|
+
processor.process(validTxs, blockSize, this.prover, txValidator),
|
|
217
|
+
);
|
|
199
218
|
if (failedTxs.length > 0) {
|
|
200
219
|
const failedTxData = failedTxs.map(fail => fail.tx);
|
|
201
220
|
this.log(`Dropping failed txs ${Tx.getHashes(failedTxData).join(', ')}`);
|
|
202
221
|
await this.p2pClient.deleteTxs(Tx.getHashes(failedTxData));
|
|
203
222
|
}
|
|
204
223
|
|
|
205
|
-
|
|
206
|
-
// public functions emitting nullifiers would pass earlier check but fail here.
|
|
207
|
-
// Note that we're checking all nullifiers generated in the private execution twice,
|
|
208
|
-
// we could store the ones already checked and skip them here as an optimization.
|
|
209
|
-
const processedValidTxs = await this.takeValidTxs(processedTxs, txValidator);
|
|
210
|
-
|
|
211
|
-
if (processedValidTxs.length === 0) {
|
|
224
|
+
if (processedTxs.length === 0) {
|
|
212
225
|
this.log('No txs processed correctly to build block. Exiting');
|
|
226
|
+
this.prover.cancelBlock();
|
|
213
227
|
return;
|
|
214
228
|
}
|
|
215
229
|
|
|
216
230
|
await assertBlockHeight();
|
|
217
231
|
|
|
218
|
-
//
|
|
219
|
-
this.
|
|
220
|
-
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(BigInt(newBlockNumber));
|
|
221
|
-
this.log(`Retrieved ${l1ToL2Messages.length} L1 to L2 messages for block ${newBlockNumber}`);
|
|
232
|
+
// All real transactions have been added, set the block as full and complete the proving.
|
|
233
|
+
await this.prover.setBlockCompleted();
|
|
222
234
|
|
|
223
|
-
//
|
|
224
|
-
|
|
235
|
+
// Here we are now waiting for the block to be proven.
|
|
236
|
+
// TODO(@PhilWindle) We should probably periodically check for things like another
|
|
237
|
+
// block being published before ours instead of just waiting on our block
|
|
238
|
+
const result = await blockTicket.provingPromise;
|
|
239
|
+
if (result.status === PROVING_STATUS.FAILURE) {
|
|
240
|
+
throw new Error(`Block proving failed, reason: ${result.reason}`);
|
|
241
|
+
}
|
|
225
242
|
|
|
226
243
|
await assertBlockHeight();
|
|
227
244
|
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
245
|
+
// Block is proven, now finalise and publish!
|
|
246
|
+
const blockResult = await this.prover.finaliseBlock();
|
|
247
|
+
const block = blockResult.block;
|
|
248
|
+
|
|
249
|
+
await assertBlockHeight();
|
|
232
250
|
|
|
233
251
|
this.log(`Assembled block ${block.number}`, {
|
|
234
252
|
eventName: 'l2-block-built',
|
|
235
253
|
duration: workTimer.ms(),
|
|
236
254
|
publicProcessDuration: publicProcessorDuration,
|
|
237
|
-
rollupCircuitsDuration:
|
|
255
|
+
rollupCircuitsDuration: blockBuildingTimer.ms(),
|
|
238
256
|
...block.getStats(),
|
|
239
257
|
} satisfies L2BlockBuiltStats);
|
|
240
258
|
|
|
241
|
-
await assertBlockHeight();
|
|
242
|
-
|
|
243
259
|
await this.publishL2Block(block);
|
|
244
|
-
this.log.info(`Submitted rollup block ${block.number} with ${
|
|
260
|
+
this.log.info(`Submitted rollup block ${block.number} with ${processedTxs.length} transactions`);
|
|
245
261
|
} catch (err) {
|
|
246
262
|
this.log.error(`Rolling back world state DB due to error assembling block`, (err as any).stack);
|
|
263
|
+
// Cancel any further proving on the block
|
|
264
|
+
this.prover?.cancelBlock();
|
|
247
265
|
await this.worldState.getLatest().rollback();
|
|
248
266
|
}
|
|
249
267
|
}
|
|
@@ -289,33 +307,6 @@ export class Sequencer {
|
|
|
289
307
|
return min >= this.lastPublishedBlock;
|
|
290
308
|
}
|
|
291
309
|
|
|
292
|
-
/**
|
|
293
|
-
* Pads the set of txs to a power of two and assembles a block by calling the block builder.
|
|
294
|
-
* @param txs - Processed txs to include in the next block.
|
|
295
|
-
* @param l1ToL2Messages - L1 to L2 messages to be part of the block.
|
|
296
|
-
* @param emptyTx - Empty tx to repeat at the end of the block to pad to a power of two.
|
|
297
|
-
* @param globalVariables - Global variables to use in the block.
|
|
298
|
-
* @returns The new block.
|
|
299
|
-
*/
|
|
300
|
-
protected async buildBlock(
|
|
301
|
-
txs: ProcessedTx[],
|
|
302
|
-
l1ToL2Messages: Fr[],
|
|
303
|
-
emptyTx: ProcessedTx,
|
|
304
|
-
globalVariables: GlobalVariables,
|
|
305
|
-
) {
|
|
306
|
-
const blockTicket = await this.prover.startNewBlock(txs.length, globalVariables, l1ToL2Messages, emptyTx);
|
|
307
|
-
|
|
308
|
-
for (const tx of txs) {
|
|
309
|
-
await this.prover.addNewTx(tx);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const result = await blockTicket.provingPromise;
|
|
313
|
-
if (result.status === PROVING_STATUS.FAILURE) {
|
|
314
|
-
throw new Error(`Block proving failed, reason: ${result.reason}`);
|
|
315
|
-
}
|
|
316
|
-
return result.block;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
310
|
get coinbase(): EthAddress {
|
|
320
311
|
return this._coinbase;
|
|
321
312
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { Tx } from '@aztec/circuit-types';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type Tx } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
type GlobalVariables,
|
|
4
|
+
type Header,
|
|
5
|
+
type Proof,
|
|
6
|
+
type PublicKernelCircuitPublicInputs,
|
|
7
|
+
} from '@aztec/circuits.js';
|
|
8
|
+
import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator';
|
|
9
|
+
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
5
10
|
|
|
6
|
-
import { PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
7
|
-
import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
|
|
11
|
+
import { type PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
12
|
+
import { type ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
|
|
8
13
|
import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
9
14
|
|
|
10
15
|
/**
|
|
@@ -40,6 +45,6 @@ export class SetupPhaseManager extends AbstractPhaseManager {
|
|
|
40
45
|
);
|
|
41
46
|
tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
|
|
42
47
|
await this.publicStateDB.checkpoint();
|
|
43
|
-
return { publicKernelOutput, publicKernelProof, revertReason };
|
|
48
|
+
return { publicKernelOutput, publicKernelProof, revertReason, returnValues: undefined };
|
|
44
49
|
}
|
|
45
50
|
}
|
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
import { Tx } from '@aztec/circuit-types';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type Tx } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
type Fr,
|
|
4
|
+
type GlobalVariables,
|
|
5
|
+
type Header,
|
|
6
|
+
type KernelCircuitPublicInputs,
|
|
7
|
+
MAX_NEW_NOTE_HASHES_PER_TX,
|
|
8
|
+
type Proof,
|
|
9
|
+
type PublicKernelCircuitPublicInputs,
|
|
10
|
+
PublicKernelTailCircuitPrivateInputs,
|
|
11
|
+
type SideEffect,
|
|
12
|
+
makeEmptyProof,
|
|
13
|
+
mergeAccumulatedData,
|
|
14
|
+
sortByCounter,
|
|
15
|
+
} from '@aztec/circuits.js';
|
|
16
|
+
import { type Tuple } from '@aztec/foundation/serialize';
|
|
17
|
+
import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator';
|
|
18
|
+
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
5
19
|
|
|
6
|
-
import { PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
7
|
-
import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
|
|
20
|
+
import { type PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
21
|
+
import { type ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
|
|
8
22
|
import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
9
23
|
|
|
10
24
|
export class TailPhaseManager extends AbstractPhaseManager {
|
|
@@ -23,7 +37,7 @@ export class TailPhaseManager extends AbstractPhaseManager {
|
|
|
23
37
|
|
|
24
38
|
async handle(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs, previousPublicKernelProof: Proof) {
|
|
25
39
|
this.log(`Processing tx ${tx.getTxHash()}`);
|
|
26
|
-
const [
|
|
40
|
+
const [finalKernelOutput, publicKernelProof] = await this.runTailKernelCircuit(
|
|
27
41
|
previousPublicKernelOutput,
|
|
28
42
|
previousPublicKernelProof,
|
|
29
43
|
).catch(
|
|
@@ -37,6 +51,61 @@ export class TailPhaseManager extends AbstractPhaseManager {
|
|
|
37
51
|
// commit the state updates from this transaction
|
|
38
52
|
await this.publicStateDB.commit();
|
|
39
53
|
|
|
40
|
-
return {
|
|
54
|
+
return {
|
|
55
|
+
publicKernelOutput: previousPublicKernelOutput,
|
|
56
|
+
finalKernelOutput,
|
|
57
|
+
publicKernelProof,
|
|
58
|
+
revertReason: undefined,
|
|
59
|
+
returnValues: undefined,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private async runTailKernelCircuit(
|
|
64
|
+
previousOutput: PublicKernelCircuitPublicInputs,
|
|
65
|
+
previousProof: Proof,
|
|
66
|
+
): Promise<[KernelCircuitPublicInputs, Proof]> {
|
|
67
|
+
const output = await this.simulate(previousOutput, previousProof);
|
|
68
|
+
|
|
69
|
+
// Temporary hack. Should sort them in the tail circuit.
|
|
70
|
+
const noteHashes = mergeAccumulatedData(
|
|
71
|
+
MAX_NEW_NOTE_HASHES_PER_TX,
|
|
72
|
+
previousOutput.endNonRevertibleData.newNoteHashes,
|
|
73
|
+
previousOutput.end.newNoteHashes,
|
|
74
|
+
);
|
|
75
|
+
output.end.newNoteHashes = this.sortNoteHashes<typeof MAX_NEW_NOTE_HASHES_PER_TX>(noteHashes);
|
|
76
|
+
|
|
77
|
+
return [output, makeEmptyProof()];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async simulate(
|
|
81
|
+
previousOutput: PublicKernelCircuitPublicInputs,
|
|
82
|
+
previousProof: Proof,
|
|
83
|
+
): Promise<KernelCircuitPublicInputs> {
|
|
84
|
+
const previousKernel = this.getPreviousKernelData(previousOutput, previousProof);
|
|
85
|
+
|
|
86
|
+
const { validationRequests, endNonRevertibleData, end } = previousOutput;
|
|
87
|
+
const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints(
|
|
88
|
+
validationRequests.nullifierReadRequests,
|
|
89
|
+
endNonRevertibleData.newNullifiers,
|
|
90
|
+
end.newNullifiers,
|
|
91
|
+
);
|
|
92
|
+
const nullifierNonExistentReadRequestHints = await this.hintsBuilder.getNullifierNonExistentReadRequestHints(
|
|
93
|
+
validationRequests.nullifierNonExistentReadRequests,
|
|
94
|
+
endNonRevertibleData.newNullifiers,
|
|
95
|
+
end.newNullifiers,
|
|
96
|
+
);
|
|
97
|
+
const inputs = new PublicKernelTailCircuitPrivateInputs(
|
|
98
|
+
previousKernel,
|
|
99
|
+
nullifierReadRequestHints,
|
|
100
|
+
nullifierNonExistentReadRequestHints,
|
|
101
|
+
);
|
|
102
|
+
return this.publicKernel.publicKernelCircuitTail(inputs);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private sortNoteHashes<N extends number>(noteHashes: Tuple<SideEffect, N>): Tuple<Fr, N> {
|
|
106
|
+
return sortByCounter(noteHashes.map(n => ({ ...n, counter: n.counter.toNumber() }))).map(n => n.value) as Tuple<
|
|
107
|
+
Fr,
|
|
108
|
+
N
|
|
109
|
+
>;
|
|
41
110
|
}
|
|
42
111
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { Tx } from '@aztec/circuit-types';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type Tx } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
type GlobalVariables,
|
|
4
|
+
type Header,
|
|
5
|
+
type Proof,
|
|
6
|
+
type PublicKernelCircuitPublicInputs,
|
|
7
|
+
} from '@aztec/circuits.js';
|
|
8
|
+
import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator';
|
|
9
|
+
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
5
10
|
|
|
6
|
-
import { PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
7
|
-
import { ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
|
|
11
|
+
import { type PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
12
|
+
import { type ContractsDataSourcePublicDB } from '../simulator/public_executor.js';
|
|
8
13
|
import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
9
14
|
|
|
10
15
|
/**
|
|
@@ -40,6 +45,6 @@ export class TeardownPhaseManager extends AbstractPhaseManager {
|
|
|
40
45
|
);
|
|
41
46
|
tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
|
|
42
47
|
await this.publicStateDB.checkpoint();
|
|
43
|
-
return { publicKernelOutput, publicKernelProof, revertReason };
|
|
48
|
+
return { publicKernelOutput, publicKernelProof, revertReason, returnValues: undefined };
|
|
44
49
|
}
|
|
45
50
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { ProcessedTx, Tx } from '@aztec/circuit-types';
|
|
2
|
-
import {
|
|
1
|
+
import { type ProcessedTx, Tx } from '@aztec/circuit-types';
|
|
2
|
+
import {
|
|
3
|
+
type AztecAddress,
|
|
4
|
+
type EthAddress,
|
|
5
|
+
Fr,
|
|
6
|
+
type GlobalVariables,
|
|
7
|
+
type PublicCallRequest,
|
|
8
|
+
} from '@aztec/circuits.js';
|
|
3
9
|
import { pedersenHash } from '@aztec/foundation/crypto';
|
|
4
|
-
import { Logger, createDebugLogger } from '@aztec/foundation/log';
|
|
10
|
+
import { type Logger, createDebugLogger } from '@aztec/foundation/log';
|
|
5
11
|
import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token';
|
|
6
|
-
import { ContractDataSource } from '@aztec/types/contracts';
|
|
12
|
+
import { type ContractDataSource } from '@aztec/types/contracts';
|
|
7
13
|
|
|
8
14
|
import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
|
|
9
15
|
|
|
@@ -132,9 +138,7 @@ export class TxValidator {
|
|
|
132
138
|
* @returns Whether this is a problematic double spend that the L1 contract would reject.
|
|
133
139
|
*/
|
|
134
140
|
async #validateNullifiers(tx: Tx | ProcessedTx, thisBlockNullifiers: Set<bigint>): Promise<TxValidationStatus> {
|
|
135
|
-
const newNullifiers =
|
|
136
|
-
.filter(x => !x.isEmpty())
|
|
137
|
-
.map(x => x.value.toBigInt());
|
|
141
|
+
const newNullifiers = tx.data.getNonEmptyNullifiers().map(x => x.toBigInt());
|
|
138
142
|
|
|
139
143
|
// Ditch this tx if it has repeated nullifiers
|
|
140
144
|
const uniqueNullifiers = new Set(newNullifiers);
|
|
@@ -166,7 +170,7 @@ export class TxValidator {
|
|
|
166
170
|
}
|
|
167
171
|
|
|
168
172
|
async #validateGasBalance(tx: Tx): Promise<TxValidationStatus> {
|
|
169
|
-
if (!tx.data.needsTeardown) {
|
|
173
|
+
if (!tx.data.forPublic || !tx.data.forPublic.needsTeardown) {
|
|
170
174
|
return VALID_TX;
|
|
171
175
|
}
|
|
172
176
|
|
|
@@ -194,7 +198,11 @@ export class TxValidator {
|
|
|
194
198
|
}
|
|
195
199
|
|
|
196
200
|
#validateMaxBlockNumber(tx: Tx | ProcessedTx): TxValidationStatus {
|
|
197
|
-
const
|
|
201
|
+
const target =
|
|
202
|
+
tx instanceof Tx
|
|
203
|
+
? tx.data.forRollup?.rollupValidationRequests || tx.data.forPublic!.validationRequests.forRollup
|
|
204
|
+
: tx.data.rollupValidationRequests;
|
|
205
|
+
const maxBlockNumber = target.maxBlockNumber;
|
|
198
206
|
|
|
199
207
|
if (maxBlockNumber.isSome && maxBlockNumber.value < this.#globalVariables.blockNumber) {
|
|
200
208
|
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for low max block number`);
|
|
@@ -205,7 +213,7 @@ export class TxValidator {
|
|
|
205
213
|
}
|
|
206
214
|
|
|
207
215
|
async #validateFee(tx: Tx): Promise<TxValidationStatus> {
|
|
208
|
-
if (!tx.data.needsTeardown) {
|
|
216
|
+
if (!tx.data.forPublic || !tx.data.forPublic.needsTeardown) {
|
|
209
217
|
// TODO check if fees are mandatory and reject this tx
|
|
210
218
|
this.#log.debug(`Tx ${Tx.getHash(tx)} doesn't pay for gas`);
|
|
211
219
|
return VALID_TX;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AztecAddress, EthAddress, Fr, GlobalVariables } from '@aztec/circuits.js';
|
|
2
|
-
import { ContractDataSource } from '@aztec/types/contracts';
|
|
3
|
-
import { MerkleTreeOperations } from '@aztec/world-state';
|
|
1
|
+
import { type AztecAddress, type EthAddress, type Fr, type GlobalVariables } from '@aztec/circuits.js';
|
|
2
|
+
import { type ContractDataSource } from '@aztec/types/contracts';
|
|
3
|
+
import { type MerkleTreeOperations } from '@aztec/world-state';
|
|
4
4
|
|
|
5
5
|
import { WorldStateDB, WorldStatePublicDB } from '../simulator/public_executor.js';
|
|
6
6
|
import { TxValidator } from './tx_validator.js';
|
package/src/sequencer/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Tx } from '@aztec/circuit-types';
|
|
1
|
+
import { type Tx } from '@aztec/circuit-types';
|
|
2
2
|
import { CallRequest } from '@aztec/circuits.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -7,13 +7,14 @@ import { CallRequest } from '@aztec/circuits.js';
|
|
|
7
7
|
* @returns The highest side effect counter in the transaction so far
|
|
8
8
|
*/
|
|
9
9
|
export function lastSideEffectCounter(tx: Tx): number {
|
|
10
|
+
const data = tx.data.forPublic!;
|
|
10
11
|
const sideEffectCounters = [
|
|
11
|
-
...
|
|
12
|
-
...
|
|
13
|
-
...
|
|
14
|
-
...
|
|
15
|
-
...
|
|
16
|
-
...
|
|
12
|
+
...data.endNonRevertibleData.newNoteHashes,
|
|
13
|
+
...data.endNonRevertibleData.newNullifiers,
|
|
14
|
+
...data.endNonRevertibleData.publicCallStack,
|
|
15
|
+
...data.end.newNoteHashes,
|
|
16
|
+
...data.end.newNullifiers,
|
|
17
|
+
...data.end.publicCallStack,
|
|
17
18
|
];
|
|
18
19
|
|
|
19
20
|
let max = 0;
|
package/src/simulator/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
type KernelCircuitPublicInputs,
|
|
3
|
+
type PublicKernelCircuitPrivateInputs,
|
|
4
|
+
type PublicKernelCircuitPublicInputs,
|
|
5
|
+
type PublicKernelTailCircuitPrivateInputs,
|
|
5
6
|
} from '@aztec/circuits.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -31,5 +32,5 @@ export interface PublicKernelCircuitSimulator {
|
|
|
31
32
|
* @param inputs - Inputs to the circuit.
|
|
32
33
|
* @returns The public inputs as outputs of the simulation.
|
|
33
34
|
*/
|
|
34
|
-
publicKernelCircuitTail(inputs: PublicKernelTailCircuitPrivateInputs): Promise<
|
|
35
|
+
publicKernelCircuitTail(inputs: PublicKernelTailCircuitPrivateInputs): Promise<KernelCircuitPublicInputs>;
|
|
35
36
|
}
|