@aztec/sequencer-client 0.7.2 → 0.7.3
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/.tsbuildinfo +1 -0
- package/dest/block_builder/index.d.ts +19 -0
- package/dest/block_builder/index.d.ts.map +1 -0
- package/dest/block_builder/index.js +2 -0
- package/dest/block_builder/solo_block_builder.d.ts +77 -0
- package/dest/block_builder/solo_block_builder.d.ts.map +1 -0
- package/dest/block_builder/solo_block_builder.js +464 -0
- package/dest/block_builder/solo_block_builder.test.d.ts +3 -0
- package/dest/block_builder/solo_block_builder.test.d.ts.map +1 -0
- package/dest/block_builder/solo_block_builder.test.js +277 -0
- package/dest/block_builder/types.d.ts +12 -0
- package/dest/block_builder/types.d.ts.map +1 -0
- package/dest/block_builder/types.js +2 -0
- package/dest/client/index.d.ts +2 -0
- package/dest/client/index.d.ts.map +1 -0
- package/dest/client/index.js +2 -0
- package/dest/client/sequencer-client.d.ts +32 -0
- package/dest/client/sequencer-client.d.ts.map +1 -0
- package/dest/client/sequencer-client.js +47 -0
- package/dest/config.d.ts +12 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +28 -0
- package/dest/global_variable_builder/config.d.ts +19 -0
- package/dest/global_variable_builder/config.d.ts.map +1 -0
- package/dest/global_variable_builder/config.js +2 -0
- package/dest/global_variable_builder/global_builder.d.ts +58 -0
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -0
- package/dest/global_variable_builder/global_builder.js +36 -0
- package/dest/global_variable_builder/index.d.ts +12 -0
- package/dest/global_variable_builder/index.d.ts.map +1 -0
- package/dest/global_variable_builder/index.js +12 -0
- package/dest/global_variable_builder/viem-reader.d.ts +16 -0
- package/dest/global_variable_builder/viem-reader.d.ts.map +1 -0
- package/dest/global_variable_builder/viem-reader.js +37 -0
- package/dest/index.d.ts +12 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +14 -0
- package/dest/mocks/verification_keys.d.ts +28 -0
- package/dest/mocks/verification_keys.d.ts.map +1 -0
- package/dest/mocks/verification_keys.js +14 -0
- package/dest/prover/empty.d.ts +41 -0
- package/dest/prover/empty.d.ts.map +1 -0
- package/dest/prover/empty.js +57 -0
- package/dest/prover/index.d.ts +40 -0
- package/dest/prover/index.d.ts.map +1 -0
- package/dest/prover/index.js +2 -0
- package/dest/publisher/config.d.ts +32 -0
- package/dest/publisher/config.d.ts.map +1 -0
- package/dest/publisher/config.js +2 -0
- package/dest/publisher/index.d.ts +10 -0
- package/dest/publisher/index.d.ts.map +1 -0
- package/dest/publisher/index.js +11 -0
- package/dest/publisher/l1-publisher.d.ts +105 -0
- package/dest/publisher/l1-publisher.d.ts.map +1 -0
- package/dest/publisher/l1-publisher.js +156 -0
- package/dest/publisher/l1-publisher.test.d.ts +2 -0
- package/dest/publisher/l1-publisher.test.d.ts.map +1 -0
- package/dest/publisher/l1-publisher.test.js +58 -0
- package/dest/publisher/viem-tx-sender.d.ts +42 -0
- package/dest/publisher/viem-tx-sender.d.ts.map +1 -0
- package/dest/publisher/viem-tx-sender.js +121 -0
- package/dest/receiver.d.ts +13 -0
- package/dest/receiver.d.ts.map +1 -0
- package/dest/receiver.js +2 -0
- package/dest/sequencer/config.d.ts +26 -0
- package/dest/sequencer/config.d.ts.map +1 -0
- package/dest/sequencer/config.js +2 -0
- package/dest/sequencer/index.d.ts +4 -0
- package/dest/sequencer/index.d.ts.map +1 -0
- package/dest/sequencer/index.js +4 -0
- package/dest/sequencer/processed_tx.d.ts +51 -0
- package/dest/sequencer/processed_tx.d.ts.map +1 -0
- package/dest/sequencer/processed_tx.js +40 -0
- package/dest/sequencer/public_processor.d.ts +75 -0
- package/dest/sequencer/public_processor.d.ts.map +1 -0
- package/dest/sequencer/public_processor.js +269 -0
- package/dest/sequencer/public_processor.test.d.ts +2 -0
- package/dest/sequencer/public_processor.test.d.ts.map +1 -0
- package/dest/sequencer/public_processor.test.js +164 -0
- package/dest/sequencer/sequencer.d.ts +134 -0
- package/dest/sequencer/sequencer.d.ts.map +1 -0
- package/dest/sequencer/sequencer.js +306 -0
- package/dest/sequencer/sequencer.test.d.ts +2 -0
- package/dest/sequencer/sequencer.test.d.ts.map +1 -0
- package/dest/sequencer/sequencer.test.js +99 -0
- package/dest/sequencer/utils.d.ts +7 -0
- package/dest/sequencer/utils.d.ts.map +1 -0
- package/dest/sequencer/utils.js +12 -0
- package/dest/simulator/index.d.ts +43 -0
- package/dest/simulator/index.d.ts.map +1 -0
- package/dest/simulator/index.js +2 -0
- package/dest/simulator/public_executor.d.ts +22 -0
- package/dest/simulator/public_executor.d.ts.map +1 -0
- package/dest/simulator/public_executor.js +87 -0
- package/dest/simulator/public_kernel.d.ts +20 -0
- package/dest/simulator/public_kernel.d.ts.map +1 -0
- package/dest/simulator/public_kernel.js +27 -0
- package/dest/simulator/rollup.d.ts +33 -0
- package/dest/simulator/rollup.d.ts.map +1 -0
- package/dest/simulator/rollup.js +53 -0
- package/dest/utils.d.ts +12 -0
- package/dest/utils.d.ts.map +1 -0
- package/dest/utils.js +16 -0
- package/package.json +10 -10
- package/Dockerfile +0 -21
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { PublicExecutionResult, PublicExecutor } from '@aztec/acir-simulator';
|
|
2
|
+
import { Fr, GlobalVariables, HistoricBlockData, KernelCircuitPublicInputs, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, PreviousKernelData, Proof, PublicCallData, PublicCallStackItem, PublicCircuitPublicInputs, PublicKernelPublicInputs } from '@aztec/circuits.js';
|
|
3
|
+
import { Tuple } from '@aztec/foundation/serialize';
|
|
4
|
+
import { ContractDataSource, FunctionL2Logs, L1ToL2MessageSource, Tx } from '@aztec/types';
|
|
5
|
+
import { MerkleTreeOperations } from '@aztec/world-state';
|
|
6
|
+
import { PublicProver } from '../prover/index.js';
|
|
7
|
+
import { PublicKernelCircuitSimulator } from '../simulator/index.js';
|
|
8
|
+
import { FailedTx, ProcessedTx } from './processed_tx.js';
|
|
9
|
+
/**
|
|
10
|
+
* Creates new instances of PublicProcessor given the provided merkle tree db and contract data source.
|
|
11
|
+
*/
|
|
12
|
+
export declare class PublicProcessorFactory {
|
|
13
|
+
private merkleTree;
|
|
14
|
+
private contractDataSource;
|
|
15
|
+
private l1Tol2MessagesDataSource;
|
|
16
|
+
constructor(merkleTree: MerkleTreeOperations, contractDataSource: ContractDataSource, l1Tol2MessagesDataSource: L1ToL2MessageSource);
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new instance of a PublicProcessor.
|
|
19
|
+
* @param prevGlobalVariables - The global variables for the previous block, used to calculate the prev global variables hash.
|
|
20
|
+
* @param globalVariables - The global variables for the block being processed.
|
|
21
|
+
* @returns A new instance of a PublicProcessor.
|
|
22
|
+
*/
|
|
23
|
+
create(prevGlobalVariables: GlobalVariables, globalVariables: GlobalVariables): Promise<PublicProcessor>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Converts Txs lifted from the P2P module into ProcessedTx objects by executing
|
|
27
|
+
* any public function calls in them. Txs with private calls only are unaffected.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PublicProcessor {
|
|
30
|
+
protected db: MerkleTreeOperations;
|
|
31
|
+
protected publicExecutor: PublicExecutor;
|
|
32
|
+
protected publicKernel: PublicKernelCircuitSimulator;
|
|
33
|
+
protected publicProver: PublicProver;
|
|
34
|
+
protected contractDataSource: ContractDataSource;
|
|
35
|
+
protected globalVariables: GlobalVariables;
|
|
36
|
+
protected blockData: HistoricBlockData;
|
|
37
|
+
private log;
|
|
38
|
+
constructor(db: MerkleTreeOperations, publicExecutor: PublicExecutor, publicKernel: PublicKernelCircuitSimulator, publicProver: PublicProver, contractDataSource: ContractDataSource, globalVariables: GlobalVariables, blockData: HistoricBlockData, log?: import("@aztec/foundation/log").DebugLogger);
|
|
39
|
+
/**
|
|
40
|
+
* Run each tx through the public circuit and the public kernel circuit if needed.
|
|
41
|
+
* @param txs - Txs to process.
|
|
42
|
+
* @returns The list of processed txs with their circuit simulation outputs.
|
|
43
|
+
*/
|
|
44
|
+
process(txs: Tx[]): Promise<[ProcessedTx[], FailedTx[]]>;
|
|
45
|
+
/**
|
|
46
|
+
* Makes an empty processed tx. Useful for padding a block to a power of two number of txs.
|
|
47
|
+
* @returns A processed tx with empty data.
|
|
48
|
+
*/
|
|
49
|
+
makeEmptyProcessedTx(): Promise<ProcessedTx>;
|
|
50
|
+
protected processTx(tx: Tx): Promise<ProcessedTx>;
|
|
51
|
+
protected processEnqueuedPublicCalls(tx: Tx): Promise<[PublicKernelPublicInputs, Proof, FunctionL2Logs[]]>;
|
|
52
|
+
protected runKernelCircuit(callData: PublicCallData, previousOutput: KernelCircuitPublicInputs, previousProof: Proof): Promise<[KernelCircuitPublicInputs, Proof]>;
|
|
53
|
+
protected getKernelCircuitOutput(callData: PublicCallData, previousOutput: KernelCircuitPublicInputs, previousProof: Proof): Promise<KernelCircuitPublicInputs>;
|
|
54
|
+
protected getPreviousKernelData(previousOutput: KernelCircuitPublicInputs, previousProof: Proof): PreviousKernelData;
|
|
55
|
+
protected getPublicCircuitPublicInputs(result: PublicExecutionResult): Promise<PublicCircuitPublicInputs>;
|
|
56
|
+
protected getPublicCallStackItem(result: PublicExecutionResult, isExecutionRequest?: boolean): Promise<PublicCallStackItem>;
|
|
57
|
+
protected getPublicCallStackPreimages(result: PublicExecutionResult): Promise<[PublicCallStackItem, PublicCallStackItem, PublicCallStackItem, PublicCallStackItem]>;
|
|
58
|
+
protected getBytecodeHash(_result: PublicExecutionResult): Promise<Fr>;
|
|
59
|
+
/**
|
|
60
|
+
* Calculates the PublicCircuitOutput for this execution result along with its proof,
|
|
61
|
+
* and assembles a PublicCallData object from it.
|
|
62
|
+
* @param result - The execution result.
|
|
63
|
+
* @param preimages - The preimages of the callstack items.
|
|
64
|
+
* @param isExecutionRequest - Whether the current callstack item should be considered a public fn execution request.
|
|
65
|
+
* @returns A corresponding PublicCallData object.
|
|
66
|
+
*/
|
|
67
|
+
protected getPublicCallData(result: PublicExecutionResult, preimages: Tuple<PublicCallStackItem, typeof MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL>, isExecutionRequest?: boolean): Promise<PublicCallData>;
|
|
68
|
+
/**
|
|
69
|
+
* Patch the ordering of storage actions output from the public kernel.
|
|
70
|
+
* @param publicInputs - to be patched here: public inputs to the kernel iteration up to this point
|
|
71
|
+
* @param execResult - result of the top/first execution for this enqueued public call
|
|
72
|
+
*/
|
|
73
|
+
private patchPublicStorageActionOrdering;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=public_processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public_processor.d.ts","sourceRoot":"","sources":["../../src/sequencer/public_processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { collectPublicDataReads, collectPublicDataUpdateRequests, isPublicExecutionResult, } from '@aztec/acir-simulator';
|
|
2
|
+
import { AztecAddress, CircuitsWasm, CombinedAccumulatedData, ContractStorageRead, ContractStorageUpdateRequest, Fr, KernelCircuitPublicInputs, MAX_NEW_COMMITMENTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, PreviousKernelData, PublicCallData, PublicCallStackItem, PublicCircuitPublicInputs, PublicDataRead, PublicDataUpdateRequest, PublicKernelInputs, RETURN_VALUES_LENGTH, VK_TREE_HEIGHT, } from '@aztec/circuits.js';
|
|
3
|
+
import { computeCallStackItemHash, computeVarArgsHash } from '@aztec/circuits.js/abis';
|
|
4
|
+
import { arrayNonEmptyLength, isArrayEmpty, padArrayEnd, padArrayStart } from '@aztec/foundation/collection';
|
|
5
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
6
|
+
import { mapTuple, to2Fields } from '@aztec/foundation/serialize';
|
|
7
|
+
import { MerkleTreeId, Tx } from '@aztec/types';
|
|
8
|
+
import { getVerificationKeys } from '../index.js';
|
|
9
|
+
import { EmptyPublicProver } from '../prover/empty.js';
|
|
10
|
+
import { getPublicExecutor } from '../simulator/index.js';
|
|
11
|
+
import { WasmPublicKernelCircuitSimulator } from '../simulator/public_kernel.js';
|
|
12
|
+
import { makeEmptyProcessedTx, makeProcessedTx } from './processed_tx.js';
|
|
13
|
+
import { getHistoricBlockData } from './utils.js';
|
|
14
|
+
/**
|
|
15
|
+
* Creates new instances of PublicProcessor given the provided merkle tree db and contract data source.
|
|
16
|
+
*/
|
|
17
|
+
export class PublicProcessorFactory {
|
|
18
|
+
constructor(merkleTree, contractDataSource, l1Tol2MessagesDataSource) {
|
|
19
|
+
this.merkleTree = merkleTree;
|
|
20
|
+
this.contractDataSource = contractDataSource;
|
|
21
|
+
this.l1Tol2MessagesDataSource = l1Tol2MessagesDataSource;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new instance of a PublicProcessor.
|
|
25
|
+
* @param prevGlobalVariables - The global variables for the previous block, used to calculate the prev global variables hash.
|
|
26
|
+
* @param globalVariables - The global variables for the block being processed.
|
|
27
|
+
* @returns A new instance of a PublicProcessor.
|
|
28
|
+
*/
|
|
29
|
+
async create(prevGlobalVariables, globalVariables) {
|
|
30
|
+
const blockData = await getHistoricBlockData(this.merkleTree, prevGlobalVariables);
|
|
31
|
+
return new PublicProcessor(this.merkleTree, getPublicExecutor(this.merkleTree, this.contractDataSource, this.l1Tol2MessagesDataSource, blockData), new WasmPublicKernelCircuitSimulator(), new EmptyPublicProver(), this.contractDataSource, globalVariables, blockData);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Converts Txs lifted from the P2P module into ProcessedTx objects by executing
|
|
36
|
+
* any public function calls in them. Txs with private calls only are unaffected.
|
|
37
|
+
*/
|
|
38
|
+
export class PublicProcessor {
|
|
39
|
+
constructor(db, publicExecutor, publicKernel, publicProver, contractDataSource, globalVariables, blockData, log = createDebugLogger('aztec:sequencer:public-processor')) {
|
|
40
|
+
this.db = db;
|
|
41
|
+
this.publicExecutor = publicExecutor;
|
|
42
|
+
this.publicKernel = publicKernel;
|
|
43
|
+
this.publicProver = publicProver;
|
|
44
|
+
this.contractDataSource = contractDataSource;
|
|
45
|
+
this.globalVariables = globalVariables;
|
|
46
|
+
this.blockData = blockData;
|
|
47
|
+
this.log = log;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run each tx through the public circuit and the public kernel circuit if needed.
|
|
51
|
+
* @param txs - Txs to process.
|
|
52
|
+
* @returns The list of processed txs with their circuit simulation outputs.
|
|
53
|
+
*/
|
|
54
|
+
async process(txs) {
|
|
55
|
+
// The processor modifies the tx objects in place, so we need to clone them.
|
|
56
|
+
txs = txs.map(tx => Tx.clone(tx));
|
|
57
|
+
const result = [];
|
|
58
|
+
const failed = [];
|
|
59
|
+
for (const tx of txs) {
|
|
60
|
+
this.log(`Processing tx ${await tx.getTxHash()}`);
|
|
61
|
+
try {
|
|
62
|
+
result.push(await this.processTx(tx));
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
this.log.warn(`Error processing tx ${await tx.getTxHash()}: ${err}`);
|
|
66
|
+
failed.push({
|
|
67
|
+
tx,
|
|
68
|
+
error: err instanceof Error ? err : new Error('Unknown error'),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return [result, failed];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Makes an empty processed tx. Useful for padding a block to a power of two number of txs.
|
|
76
|
+
* @returns A processed tx with empty data.
|
|
77
|
+
*/
|
|
78
|
+
makeEmptyProcessedTx() {
|
|
79
|
+
const { chainId, version } = this.globalVariables;
|
|
80
|
+
return makeEmptyProcessedTx(this.blockData, chainId, version);
|
|
81
|
+
}
|
|
82
|
+
async processTx(tx) {
|
|
83
|
+
if (!isArrayEmpty(tx.data.end.publicCallStack, item => item.isZero())) {
|
|
84
|
+
const [publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs] = await this.processEnqueuedPublicCalls(tx);
|
|
85
|
+
tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
|
|
86
|
+
return makeProcessedTx(tx, publicKernelOutput, publicKernelProof);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
return makeProcessedTx(tx);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async processEnqueuedPublicCalls(tx) {
|
|
93
|
+
this.log(`Executing enqueued public calls for tx ${await tx.getTxHash()}`);
|
|
94
|
+
if (!tx.enqueuedPublicFunctionCalls)
|
|
95
|
+
throw new Error(`Missing preimages for enqueued public calls`);
|
|
96
|
+
let kernelOutput = new KernelCircuitPublicInputs(CombinedAccumulatedData.fromFinalAccumulatedData(tx.data.end), tx.data.constants, tx.data.isPrivate);
|
|
97
|
+
let kernelProof = tx.proof;
|
|
98
|
+
const newUnencryptedFunctionLogs = [];
|
|
99
|
+
// TODO(#1684): Should multiple separately enqueued public calls be treated as
|
|
100
|
+
// separate public callstacks to be proven by separate public kernel sequences
|
|
101
|
+
// and submitted separately to the base rollup?
|
|
102
|
+
// TODO(dbanks12): why must these be reversed?
|
|
103
|
+
const enqueuedCallsReversed = tx.enqueuedPublicFunctionCalls.slice().reverse();
|
|
104
|
+
for (const enqueuedCall of enqueuedCallsReversed) {
|
|
105
|
+
const executionStack = [enqueuedCall];
|
|
106
|
+
// Keep track of which result is for the top/enqueued call
|
|
107
|
+
let enqueuedExecutionResult;
|
|
108
|
+
while (executionStack.length) {
|
|
109
|
+
const current = executionStack.pop();
|
|
110
|
+
const isExecutionRequest = !isPublicExecutionResult(current);
|
|
111
|
+
const result = isExecutionRequest ? await this.publicExecutor.simulate(current, this.globalVariables) : current;
|
|
112
|
+
newUnencryptedFunctionLogs.push(result.unencryptedLogs);
|
|
113
|
+
const functionSelector = result.execution.functionData.selector.toString();
|
|
114
|
+
this.log(`Running public kernel circuit for ${functionSelector}@${result.execution.contractAddress.toString()}`);
|
|
115
|
+
executionStack.push(...result.nestedExecutions);
|
|
116
|
+
const preimages = await this.getPublicCallStackPreimages(result);
|
|
117
|
+
const callData = await this.getPublicCallData(result, preimages, isExecutionRequest);
|
|
118
|
+
[kernelOutput, kernelProof] = await this.runKernelCircuit(callData, kernelOutput, kernelProof);
|
|
119
|
+
if (!enqueuedExecutionResult)
|
|
120
|
+
enqueuedExecutionResult = result;
|
|
121
|
+
}
|
|
122
|
+
// HACK(#1622): Manually patches the ordering of public state actions
|
|
123
|
+
// TODO(#757): Enforce proper ordering of public state actions
|
|
124
|
+
await this.patchPublicStorageActionOrdering(kernelOutput, enqueuedExecutionResult);
|
|
125
|
+
}
|
|
126
|
+
return [kernelOutput, kernelProof, newUnencryptedFunctionLogs];
|
|
127
|
+
}
|
|
128
|
+
async runKernelCircuit(callData, previousOutput, previousProof) {
|
|
129
|
+
const output = await this.getKernelCircuitOutput(callData, previousOutput, previousProof);
|
|
130
|
+
const proof = await this.publicProver.getPublicKernelCircuitProof(output);
|
|
131
|
+
return [output, proof];
|
|
132
|
+
}
|
|
133
|
+
getKernelCircuitOutput(callData, previousOutput, previousProof) {
|
|
134
|
+
if (previousOutput?.isPrivate && previousProof) {
|
|
135
|
+
// Run the public kernel circuit with previous private kernel
|
|
136
|
+
const previousKernel = this.getPreviousKernelData(previousOutput, previousProof);
|
|
137
|
+
const inputs = new PublicKernelInputs(previousKernel, callData);
|
|
138
|
+
return this.publicKernel.publicKernelCircuitPrivateInput(inputs);
|
|
139
|
+
}
|
|
140
|
+
else if (previousOutput && previousProof) {
|
|
141
|
+
// Run the public kernel circuit with previous public kernel
|
|
142
|
+
const previousKernel = this.getPreviousKernelData(previousOutput, previousProof);
|
|
143
|
+
const inputs = new PublicKernelInputs(previousKernel, callData);
|
|
144
|
+
return this.publicKernel.publicKernelCircuitNonFirstIteration(inputs);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
throw new Error(`No public kernel circuit for inputs`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
getPreviousKernelData(previousOutput, previousProof) {
|
|
151
|
+
const vk = getVerificationKeys().publicKernelCircuit;
|
|
152
|
+
const vkIndex = 0;
|
|
153
|
+
const vkSiblingPath = MembershipWitness.random(VK_TREE_HEIGHT).siblingPath;
|
|
154
|
+
return new PreviousKernelData(previousOutput, previousProof, vk, vkIndex, vkSiblingPath);
|
|
155
|
+
}
|
|
156
|
+
async getPublicCircuitPublicInputs(result) {
|
|
157
|
+
const publicDataTreeInfo = await this.db.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE);
|
|
158
|
+
this.blockData.publicDataTreeRoot = Fr.fromBuffer(publicDataTreeInfo.root);
|
|
159
|
+
const callStackPreimages = await this.getPublicCallStackPreimages(result);
|
|
160
|
+
const wasm = await CircuitsWasm.get();
|
|
161
|
+
const publicCallStack = mapTuple(callStackPreimages, item => item.isEmpty() ? Fr.zero() : computeCallStackItemHash(wasm, item));
|
|
162
|
+
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) --> set this in Noir
|
|
163
|
+
const unencryptedLogsHash = to2Fields(result.unencryptedLogs.hash());
|
|
164
|
+
const unencryptedLogPreimagesLength = new Fr(result.unencryptedLogs.getSerializedLength());
|
|
165
|
+
return PublicCircuitPublicInputs.from({
|
|
166
|
+
callContext: result.execution.callContext,
|
|
167
|
+
proverAddress: AztecAddress.ZERO,
|
|
168
|
+
argsHash: await computeVarArgsHash(wasm, result.execution.args),
|
|
169
|
+
newCommitments: padArrayEnd(result.newCommitments, Fr.ZERO, MAX_NEW_COMMITMENTS_PER_CALL),
|
|
170
|
+
newNullifiers: padArrayEnd(result.newNullifiers, Fr.ZERO, MAX_NEW_NULLIFIERS_PER_CALL),
|
|
171
|
+
newL2ToL1Msgs: padArrayEnd(result.newL2ToL1Messages, Fr.ZERO, MAX_NEW_L2_TO_L1_MSGS_PER_CALL),
|
|
172
|
+
returnValues: padArrayEnd(result.returnValues, Fr.ZERO, RETURN_VALUES_LENGTH),
|
|
173
|
+
contractStorageReads: padArrayEnd(result.contractStorageReads, ContractStorageRead.empty(), MAX_PUBLIC_DATA_READS_PER_CALL),
|
|
174
|
+
contractStorageUpdateRequests: padArrayEnd(result.contractStorageUpdateRequests, ContractStorageUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL),
|
|
175
|
+
publicCallStack,
|
|
176
|
+
unencryptedLogsHash,
|
|
177
|
+
unencryptedLogPreimagesLength,
|
|
178
|
+
historicBlockData: this.blockData,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
async getPublicCallStackItem(result, isExecutionRequest = false) {
|
|
182
|
+
return new PublicCallStackItem(result.execution.contractAddress, result.execution.functionData, await this.getPublicCircuitPublicInputs(result), isExecutionRequest);
|
|
183
|
+
}
|
|
184
|
+
async getPublicCallStackPreimages(result) {
|
|
185
|
+
const nested = result.nestedExecutions;
|
|
186
|
+
const preimages = await Promise.all(nested.map(n => this.getPublicCallStackItem(n)));
|
|
187
|
+
if (preimages.length > MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL) {
|
|
188
|
+
throw new Error(`Public call stack size exceeded (max ${MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}, got ${preimages.length})`);
|
|
189
|
+
}
|
|
190
|
+
// Top of the stack is at the end of the array, so we padStart
|
|
191
|
+
return padArrayStart(preimages, PublicCallStackItem.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL);
|
|
192
|
+
}
|
|
193
|
+
getBytecodeHash(_result) {
|
|
194
|
+
// TODO: Determine how to calculate bytecode hash. Circuits just check it isn't zero for now.
|
|
195
|
+
// See https://github.com/AztecProtocol/aztec3-packages/issues/378
|
|
196
|
+
const bytecodeHash = new Fr(1n);
|
|
197
|
+
return Promise.resolve(bytecodeHash);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Calculates the PublicCircuitOutput for this execution result along with its proof,
|
|
201
|
+
* and assembles a PublicCallData object from it.
|
|
202
|
+
* @param result - The execution result.
|
|
203
|
+
* @param preimages - The preimages of the callstack items.
|
|
204
|
+
* @param isExecutionRequest - Whether the current callstack item should be considered a public fn execution request.
|
|
205
|
+
* @returns A corresponding PublicCallData object.
|
|
206
|
+
*/
|
|
207
|
+
async getPublicCallData(result, preimages, isExecutionRequest = false) {
|
|
208
|
+
const bytecodeHash = await this.getBytecodeHash(result);
|
|
209
|
+
const callStackItem = await this.getPublicCallStackItem(result, isExecutionRequest);
|
|
210
|
+
const portalContractAddress = result.execution.callContext.portalContractAddress.toField();
|
|
211
|
+
const proof = await this.publicProver.getPublicCircuitProof(callStackItem.publicInputs);
|
|
212
|
+
return new PublicCallData(callStackItem, preimages, proof, portalContractAddress, bytecodeHash);
|
|
213
|
+
}
|
|
214
|
+
// HACK(#1622): this is a hack to fix ordering of public state in the call stack. Since the private kernel
|
|
215
|
+
// cannot keep track of side effects that happen after or before a nested call, we override the public
|
|
216
|
+
// state actions it emits with whatever we got from the simulator. As a sanity check, we at least verify
|
|
217
|
+
// that the elements are the same, so we are only tweaking their ordering.
|
|
218
|
+
// See yarn-project/end-to-end/src/e2e_ordering.test.ts
|
|
219
|
+
// See https://github.com/AztecProtocol/aztec-packages/issues/1616
|
|
220
|
+
// TODO(#757): Enforce proper ordering of public state actions
|
|
221
|
+
/**
|
|
222
|
+
* Patch the ordering of storage actions output from the public kernel.
|
|
223
|
+
* @param publicInputs - to be patched here: public inputs to the kernel iteration up to this point
|
|
224
|
+
* @param execResult - result of the top/first execution for this enqueued public call
|
|
225
|
+
*/
|
|
226
|
+
async patchPublicStorageActionOrdering(publicInputs, execResult) {
|
|
227
|
+
// Convert ContractStorage* objects to PublicData* objects and sort them in execution order
|
|
228
|
+
const wasm = await CircuitsWasm.get();
|
|
229
|
+
const simPublicDataReads = collectPublicDataReads(wasm, execResult);
|
|
230
|
+
const simPublicDataUpdateRequests = collectPublicDataUpdateRequests(wasm, execResult);
|
|
231
|
+
const { publicDataReads, publicDataUpdateRequests } = publicInputs.end; // from kernel
|
|
232
|
+
// Validate all items in enqueued public calls are in the kernel emitted stack
|
|
233
|
+
const readsAreEqual = simPublicDataReads.reduce((accum, read) => accum && !!publicDataReads.find(item => item.leafIndex.equals(read.leafIndex) && item.value.equals(read.value)), true);
|
|
234
|
+
const updatesAreEqual = simPublicDataUpdateRequests.reduce((accum, update) => accum &&
|
|
235
|
+
!!publicDataUpdateRequests.find(item => item.leafIndex.equals(update.leafIndex) &&
|
|
236
|
+
item.oldValue.equals(update.oldValue) &&
|
|
237
|
+
item.newValue.equals(update.newValue)), true);
|
|
238
|
+
if (!readsAreEqual) {
|
|
239
|
+
throw new Error(`Public data reads from simulator do not match those from public kernel.\nFrom simulator: ${simPublicDataReads
|
|
240
|
+
.map(p => p.toFriendlyJSON())
|
|
241
|
+
.join(', ')}\nFrom public kernel: ${publicDataReads.map(i => i.toFriendlyJSON()).join(', ')}`);
|
|
242
|
+
}
|
|
243
|
+
if (!updatesAreEqual) {
|
|
244
|
+
throw new Error(`Public data update requests from simulator do not match those from public kernel.\nFrom simulator: ${simPublicDataUpdateRequests
|
|
245
|
+
.map(p => p.toFriendlyJSON())
|
|
246
|
+
.join(', ')}\nFrom public kernel: ${publicDataUpdateRequests.map(i => i.toFriendlyJSON()).join(', ')}`);
|
|
247
|
+
}
|
|
248
|
+
// Assume that kernel public inputs has the right number of items.
|
|
249
|
+
// We only want to reorder the items from the public inputs of the
|
|
250
|
+
// most recently processed top/enqueued call.
|
|
251
|
+
const numTotalReadsInKernel = arrayNonEmptyLength(publicInputs.end.publicDataReads, f => f.leafIndex.equals(Fr.ZERO) && f.value.equals(Fr.ZERO));
|
|
252
|
+
const numTotalUpdatesInKernel = arrayNonEmptyLength(publicInputs.end.publicDataUpdateRequests, f => f.leafIndex.equals(Fr.ZERO) && f.oldValue.equals(Fr.ZERO) && f.newValue.equals(Fr.ZERO));
|
|
253
|
+
const numReadsBeforeThisEnqueuedCall = numTotalReadsInKernel - simPublicDataReads.length;
|
|
254
|
+
const numUpdatesBeforeThisEnqueuedCall = numTotalUpdatesInKernel - simPublicDataUpdateRequests.length;
|
|
255
|
+
// Override kernel output
|
|
256
|
+
publicInputs.end.publicDataReads = padArrayEnd([
|
|
257
|
+
// do not mess with items from previous top/enqueued calls in kernel output
|
|
258
|
+
...publicDataReads.slice(0, numReadsBeforeThisEnqueuedCall),
|
|
259
|
+
...simPublicDataReads,
|
|
260
|
+
], PublicDataRead.empty(), MAX_PUBLIC_DATA_READS_PER_TX);
|
|
261
|
+
// Override kernel output
|
|
262
|
+
publicInputs.end.publicDataUpdateRequests = padArrayEnd([
|
|
263
|
+
// do not mess with items from previous top/enqueued calls in kernel output
|
|
264
|
+
...publicDataUpdateRequests.slice(0, numUpdatesBeforeThisEnqueuedCall),
|
|
265
|
+
...simPublicDataUpdateRequests,
|
|
266
|
+
], PublicDataUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljX3Byb2Nlc3Nvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXF1ZW5jZXIvcHVibGljX3Byb2Nlc3Nvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBSUwsc0JBQXNCLEVBQ3RCLCtCQUErQixFQUMvQix1QkFBdUIsR0FDeEIsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQixPQUFPLEVBQ0wsWUFBWSxFQUNaLFlBQVksRUFDWix1QkFBdUIsRUFDdkIsbUJBQW1CLEVBQ25CLDRCQUE0QixFQUM1QixFQUFFLEVBR0YseUJBQXlCLEVBQ3pCLDRCQUE0QixFQUM1Qiw4QkFBOEIsRUFDOUIsMkJBQTJCLEVBQzNCLHFDQUFxQyxFQUNyQyw4QkFBOEIsRUFDOUIsNEJBQTRCLEVBQzVCLHdDQUF3QyxFQUN4QyxzQ0FBc0MsRUFDdEMsaUJBQWlCLEVBQ2pCLGtCQUFrQixFQUVsQixjQUFjLEVBQ2QsbUJBQW1CLEVBQ25CLHlCQUF5QixFQUN6QixjQUFjLEVBQ2QsdUJBQXVCLEVBQ3ZCLGtCQUFrQixFQUVsQixvQkFBb0IsRUFDcEIsY0FBYyxHQUNmLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLHdCQUF3QixFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdkYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDN0csT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUFTLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN6RSxPQUFPLEVBQTJELFlBQVksRUFBRSxFQUFFLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHekcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxN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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public_processor.test.d.ts","sourceRoot":"","sources":["../../src/sequencer/public_processor.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { ARGS_LENGTH, CallContext, CircuitsWasm, CombinedAccumulatedData, EthAddress, Fr, FunctionData, GlobalVariables, HistoricBlockData, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PUBLIC_DATA_TREE_HEIGHT, PublicKernelPublicInputs, makeEmptyProof, makeTuple, } from '@aztec/circuits.js';
|
|
2
|
+
import { computeCallStackItemHash } from '@aztec/circuits.js/abis';
|
|
3
|
+
import { makeAztecAddress, makePrivateKernelPublicInputsFinal, makePublicCallRequest, makeSelector, } from '@aztec/circuits.js/factories';
|
|
4
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
5
|
+
import { EncodedContractFunction, ExtendedContractData, FunctionL2Logs, SiblingPath, Tx, TxL2Logs, mockTx, } from '@aztec/types';
|
|
6
|
+
import { mock } from 'jest-mock-extended';
|
|
7
|
+
import times from 'lodash.times';
|
|
8
|
+
import { WasmPublicKernelCircuitSimulator } from '../simulator/public_kernel.js';
|
|
9
|
+
import { PublicProcessor } from './public_processor.js';
|
|
10
|
+
describe('public_processor', () => {
|
|
11
|
+
let db;
|
|
12
|
+
let publicExecutor;
|
|
13
|
+
let publicProver;
|
|
14
|
+
let contractDataSource;
|
|
15
|
+
let publicFunction;
|
|
16
|
+
let contractData;
|
|
17
|
+
let proof;
|
|
18
|
+
let root;
|
|
19
|
+
let processor;
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
db = mock();
|
|
22
|
+
publicExecutor = mock();
|
|
23
|
+
publicProver = mock();
|
|
24
|
+
contractDataSource = mock();
|
|
25
|
+
contractData = ExtendedContractData.random();
|
|
26
|
+
publicFunction = EncodedContractFunction.random();
|
|
27
|
+
proof = makeEmptyProof();
|
|
28
|
+
root = Buffer.alloc(32, 5);
|
|
29
|
+
publicProver.getPublicCircuitProof.mockResolvedValue(proof);
|
|
30
|
+
publicProver.getPublicKernelCircuitProof.mockResolvedValue(proof);
|
|
31
|
+
db.getTreeInfo.mockResolvedValue({ root });
|
|
32
|
+
contractDataSource.getExtendedContractData.mockResolvedValue(contractData);
|
|
33
|
+
contractDataSource.getPublicFunction.mockResolvedValue(publicFunction);
|
|
34
|
+
});
|
|
35
|
+
describe('with mock circuits', () => {
|
|
36
|
+
let publicKernel;
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
publicKernel = mock();
|
|
39
|
+
processor = new PublicProcessor(db, publicExecutor, publicKernel, publicProver, contractDataSource, GlobalVariables.empty(), HistoricBlockData.empty());
|
|
40
|
+
});
|
|
41
|
+
it('skips txs without public execution requests', async function () {
|
|
42
|
+
const tx = mockTx();
|
|
43
|
+
tx.data.end.publicCallStack = makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, Fr.zero);
|
|
44
|
+
const hash = await tx.getTxHash();
|
|
45
|
+
const [processed, failed] = await processor.process([tx]);
|
|
46
|
+
expect(processed).toEqual([
|
|
47
|
+
{
|
|
48
|
+
isEmpty: false,
|
|
49
|
+
hash,
|
|
50
|
+
data: new PublicKernelPublicInputs(CombinedAccumulatedData.fromFinalAccumulatedData(tx.data.end), tx.data.constants),
|
|
51
|
+
proof: tx.proof,
|
|
52
|
+
encryptedLogs: tx.encryptedLogs,
|
|
53
|
+
unencryptedLogs: tx.unencryptedLogs,
|
|
54
|
+
},
|
|
55
|
+
]);
|
|
56
|
+
expect(failed).toEqual([]);
|
|
57
|
+
});
|
|
58
|
+
it('returns failed txs without aborting entire operation', async function () {
|
|
59
|
+
publicExecutor.simulate.mockRejectedValue(new Error(`Failed`));
|
|
60
|
+
const tx = mockTx();
|
|
61
|
+
const [processed, failed] = await processor.process([tx]);
|
|
62
|
+
expect(processed).toEqual([]);
|
|
63
|
+
expect(failed[0].tx).toEqual(tx);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('with actual circuits', () => {
|
|
67
|
+
let publicKernel;
|
|
68
|
+
let wasm;
|
|
69
|
+
beforeAll(async () => {
|
|
70
|
+
wasm = await CircuitsWasm.get();
|
|
71
|
+
});
|
|
72
|
+
beforeEach(() => {
|
|
73
|
+
const path = times(PUBLIC_DATA_TREE_HEIGHT, i => Buffer.alloc(32, i));
|
|
74
|
+
db.getSiblingPath.mockResolvedValue(new SiblingPath(PUBLIC_DATA_TREE_HEIGHT, path));
|
|
75
|
+
publicKernel = new WasmPublicKernelCircuitSimulator();
|
|
76
|
+
processor = new PublicProcessor(db, publicExecutor, publicKernel, publicProver, contractDataSource, GlobalVariables.empty(), HistoricBlockData.empty());
|
|
77
|
+
});
|
|
78
|
+
const expectedTxByHash = async (tx) => expect.objectContaining({
|
|
79
|
+
hash: await tx.getTxHash(),
|
|
80
|
+
proof,
|
|
81
|
+
});
|
|
82
|
+
it('runs a tx with enqueued public calls', async function () {
|
|
83
|
+
const callRequests = [makePublicCallRequest(0x100), makePublicCallRequest(0x100)];
|
|
84
|
+
const callStackItems = await Promise.all(callRequests.map(call => call.toPublicCallStackItem()));
|
|
85
|
+
const callStackHashes = callStackItems.map(call => computeCallStackItemHash(wasm, call));
|
|
86
|
+
const kernelOutput = makePrivateKernelPublicInputsFinal(0x10);
|
|
87
|
+
kernelOutput.end.publicCallStack = padArrayEnd(callStackHashes, Fr.ZERO, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX);
|
|
88
|
+
kernelOutput.end.privateCallStack = padArrayEnd([], Fr.ZERO, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX);
|
|
89
|
+
const tx = new Tx(kernelOutput, proof, TxL2Logs.random(2, 3), TxL2Logs.random(3, 2), callRequests, [
|
|
90
|
+
ExtendedContractData.random(),
|
|
91
|
+
]);
|
|
92
|
+
publicExecutor.simulate.mockImplementation(execution => {
|
|
93
|
+
for (const request of callRequests) {
|
|
94
|
+
if (execution.contractAddress.equals(request.contractAddress)) {
|
|
95
|
+
return Promise.resolve(makePublicExecutionResultFromRequest(request));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
throw new Error(`Unexpected execution request: ${execution}`);
|
|
99
|
+
});
|
|
100
|
+
const [processed, failed] = await processor.process([tx]);
|
|
101
|
+
expect(processed).toHaveLength(1);
|
|
102
|
+
expect(processed).toEqual([await expectedTxByHash(tx)]);
|
|
103
|
+
expect(failed).toHaveLength(0);
|
|
104
|
+
expect(publicExecutor.simulate).toHaveBeenCalledTimes(2);
|
|
105
|
+
});
|
|
106
|
+
it('runs a tx with an enqueued public call with nested execution', async function () {
|
|
107
|
+
const callRequest = makePublicCallRequest(0x100);
|
|
108
|
+
const callStackItem = await callRequest.toPublicCallStackItem();
|
|
109
|
+
const callStackHash = computeCallStackItemHash(wasm, callStackItem);
|
|
110
|
+
const kernelOutput = makePrivateKernelPublicInputsFinal(0x10);
|
|
111
|
+
kernelOutput.end.publicCallStack = padArrayEnd([callStackHash], Fr.ZERO, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX);
|
|
112
|
+
kernelOutput.end.privateCallStack = padArrayEnd([], Fr.ZERO, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX);
|
|
113
|
+
const tx = new Tx(kernelOutput, proof, TxL2Logs.random(2, 3), TxL2Logs.random(3, 2), [callRequest], [ExtendedContractData.random()]);
|
|
114
|
+
const publicExecutionResult = makePublicExecutionResultFromRequest(callRequest);
|
|
115
|
+
publicExecutionResult.nestedExecutions = [
|
|
116
|
+
makePublicExecutionResult(publicExecutionResult.execution.contractAddress, {
|
|
117
|
+
to: makeAztecAddress(30),
|
|
118
|
+
functionData: new FunctionData(makeSelector(5), false, false, false),
|
|
119
|
+
args: new Array(ARGS_LENGTH).fill(Fr.ZERO),
|
|
120
|
+
}),
|
|
121
|
+
];
|
|
122
|
+
publicExecutor.simulate.mockResolvedValue(publicExecutionResult);
|
|
123
|
+
const [processed, failed] = await processor.process([tx]);
|
|
124
|
+
expect(processed).toHaveLength(1);
|
|
125
|
+
expect(processed).toEqual([await expectedTxByHash(tx)]);
|
|
126
|
+
expect(failed).toHaveLength(0);
|
|
127
|
+
expect(publicExecutor.simulate).toHaveBeenCalledTimes(1);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
function makePublicExecutionResultFromRequest(item) {
|
|
132
|
+
return {
|
|
133
|
+
execution: item,
|
|
134
|
+
nestedExecutions: [],
|
|
135
|
+
returnValues: [new Fr(1n)],
|
|
136
|
+
newCommitments: [],
|
|
137
|
+
newL2ToL1Messages: [],
|
|
138
|
+
newNullifiers: [],
|
|
139
|
+
contractStorageReads: [],
|
|
140
|
+
contractStorageUpdateRequests: [],
|
|
141
|
+
unencryptedLogs: new FunctionL2Logs([]),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function makePublicExecutionResult(from, tx, nestedExecutions = []) {
|
|
145
|
+
const callContext = new CallContext(from, tx.to, EthAddress.ZERO, false, false, false);
|
|
146
|
+
const execution = {
|
|
147
|
+
callContext,
|
|
148
|
+
contractAddress: tx.to,
|
|
149
|
+
functionData: tx.functionData,
|
|
150
|
+
args: tx.args,
|
|
151
|
+
};
|
|
152
|
+
return {
|
|
153
|
+
execution,
|
|
154
|
+
nestedExecutions,
|
|
155
|
+
returnValues: [],
|
|
156
|
+
newCommitments: [],
|
|
157
|
+
newNullifiers: [],
|
|
158
|
+
newL2ToL1Messages: [],
|
|
159
|
+
contractStorageReads: [],
|
|
160
|
+
contractStorageUpdateRequests: [],
|
|
161
|
+
unencryptedLogs: new FunctionL2Logs([]),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljX3Byb2Nlc3Nvci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9wdWJsaWNfcHJvY2Vzc29yLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUNMLFdBQVcsRUFFWCxXQUFXLEVBQ1gsWUFBWSxFQUNaLHVCQUF1QixFQUN2QixVQUFVLEVBQ1YsRUFBRSxFQUNGLFlBQVksRUFDWixlQUFlLEVBQ2YsaUJBQWlCLEVBQ2pCLG9DQUFvQyxFQUNwQyxtQ0FBbUMsRUFDbkMsdUJBQXVCLEVBR3ZCLHdCQUF3QixFQUN4QixjQUFjLEVBQ2QsU0FBUyxHQUNWLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixrQ0FBa0MsRUFDbEMscUJBQXFCLEVBQ3JCLFlBQVksR0FDYixNQUFNLDhCQUE4QixDQUFDO0FBQ3RDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMzRCxPQUFPLEVBRUwsdUJBQXVCLEVBQ3ZCLG9CQUFvQixFQUVwQixjQUFjLEVBQ2QsV0FBVyxFQUNYLEVBQUUsRUFDRixRQUFRLEVBQ1IsTUFBTSxHQUNQLE1BQU0sY0FBYyxDQUFDO0FBR3RCLE9BQU8sRUFBYSxJQUFJLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssTUFBTSxjQUFjLENBQUM7QUFJakMsT0FBTyxFQUFFLGdDQUFnQyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDakYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXhELFFBQVEsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLEVBQUU7SUFDaEMsSUFBSSxFQUFtQyxDQUFDO0lBQ3hDLElBQUksY0FBeUMsQ0FBQztJQUM5QyxJQUFJLFlBQXFDLENBQUM7SUFDMUMsSUFBSSxr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
|