@aztec/txe 0.71.0 → 0.73.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/index.d.ts.map +1 -1
- package/dest/index.js +5 -3
- package/dest/node/txe_node.d.ts +12 -11
- package/dest/node/txe_node.d.ts.map +1 -1
- package/dest/node/txe_node.js +42 -41
- package/dest/oracle/txe_oracle.d.ts +19 -19
- package/dest/oracle/txe_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_oracle.js +185 -163
- package/dest/txe_service/txe_service.d.ts +2 -11
- package/dest/txe_service/txe_service.d.ts.map +1 -1
- package/dest/txe_service/txe_service.js +19 -43
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +9 -5
- package/dest/util/txe_world_state_db.d.ts +3 -1
- package/dest/util/txe_world_state_db.d.ts.map +1 -1
- package/dest/util/txe_world_state_db.js +8 -5
- package/package.json +14 -14
- package/src/index.ts +4 -2
- package/src/node/txe_node.ts +57 -54
- package/src/oracle/txe_oracle.ts +294 -185
- package/src/txe_service/txe_service.ts +24 -52
- package/src/util/txe_public_contract_data_source.ts +10 -5
- package/src/util/txe_world_state_db.ts +9 -8
package/src/oracle/txe_oracle.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AuthWitness,
|
|
3
|
+
Body,
|
|
4
|
+
L2Block,
|
|
3
5
|
MerkleTreeId,
|
|
6
|
+
type MerkleTreeReadOperations,
|
|
7
|
+
type MerkleTreeWriteOperations,
|
|
4
8
|
Note,
|
|
5
9
|
type NoteStatus,
|
|
6
10
|
NullifierMembershipWitness,
|
|
@@ -13,6 +17,7 @@ import {
|
|
|
13
17
|
} from '@aztec/circuit-types';
|
|
14
18
|
import { type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
|
|
15
19
|
import {
|
|
20
|
+
AppendOnlyTreeSnapshot,
|
|
16
21
|
BlockHeader,
|
|
17
22
|
CallContext,
|
|
18
23
|
type ContractInstance,
|
|
@@ -24,8 +29,11 @@ import {
|
|
|
24
29
|
IndexedTaggingSecret,
|
|
25
30
|
type KeyValidationRequest,
|
|
26
31
|
type L1_TO_L2_MSG_TREE_HEIGHT,
|
|
32
|
+
MAX_NOTE_HASHES_PER_TX,
|
|
33
|
+
MAX_NULLIFIERS_PER_TX,
|
|
27
34
|
NULLIFIER_SUBTREE_HEIGHT,
|
|
28
35
|
type NULLIFIER_TREE_HEIGHT,
|
|
36
|
+
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
29
37
|
type NullifierLeafPreimage,
|
|
30
38
|
PRIVATE_CONTEXT_INPUTS_LENGTH,
|
|
31
39
|
type PUBLIC_DATA_TREE_HEIGHT,
|
|
@@ -34,7 +42,8 @@ import {
|
|
|
34
42
|
type PrivateLog,
|
|
35
43
|
PublicDataTreeLeaf,
|
|
36
44
|
type PublicDataTreeLeafPreimage,
|
|
37
|
-
|
|
45
|
+
PublicDataWrite,
|
|
46
|
+
type PublicLog,
|
|
38
47
|
computeContractClassId,
|
|
39
48
|
computeTaggingSecretPoint,
|
|
40
49
|
deriveKeys,
|
|
@@ -48,6 +57,12 @@ import {
|
|
|
48
57
|
siloNoteHash,
|
|
49
58
|
siloNullifier,
|
|
50
59
|
} from '@aztec/circuits.js/hash';
|
|
60
|
+
import {
|
|
61
|
+
makeAppendOnlyTreeSnapshot,
|
|
62
|
+
makeContentCommitment,
|
|
63
|
+
makeGlobalVariables,
|
|
64
|
+
makeHeader,
|
|
65
|
+
} from '@aztec/circuits.js/testing';
|
|
51
66
|
import {
|
|
52
67
|
type ContractArtifact,
|
|
53
68
|
type FunctionAbi,
|
|
@@ -56,6 +71,7 @@ import {
|
|
|
56
71
|
countArgumentsSize,
|
|
57
72
|
} from '@aztec/foundation/abi';
|
|
58
73
|
import { AztecAddress } from '@aztec/foundation/aztec-address';
|
|
74
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
59
75
|
import { poseidon2Hash } from '@aztec/foundation/crypto';
|
|
60
76
|
import { Fr } from '@aztec/foundation/fields';
|
|
61
77
|
import { type LogFn, type Logger, applyStringFormatting, createDebugOnlyLogger } from '@aztec/foundation/log';
|
|
@@ -84,7 +100,7 @@ import {
|
|
|
84
100
|
createSimulationError,
|
|
85
101
|
resolveAssertionMessageFromError,
|
|
86
102
|
} from '@aztec/simulator/server';
|
|
87
|
-
import {
|
|
103
|
+
import { type NativeWorldStateService } from '@aztec/world-state';
|
|
88
104
|
|
|
89
105
|
import { TXENode } from '../node/txe_node.js';
|
|
90
106
|
import { type TXEDatabase } from '../util/txe_database.js';
|
|
@@ -92,9 +108,8 @@ import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_so
|
|
|
92
108
|
import { TXEWorldStateDB } from '../util/txe_world_state_db.js';
|
|
93
109
|
|
|
94
110
|
export class TXE implements TypedOracle {
|
|
95
|
-
private blockNumber =
|
|
111
|
+
private blockNumber = 1;
|
|
96
112
|
private sideEffectCounter = 0;
|
|
97
|
-
private contractAddress: AztecAddress;
|
|
98
113
|
private msgSender: AztecAddress;
|
|
99
114
|
private functionSelector = FunctionSelector.fromField(new Fr(0));
|
|
100
115
|
private isStaticCall = false;
|
|
@@ -104,10 +119,11 @@ export class TXE implements TypedOracle {
|
|
|
104
119
|
private contractDataOracle: ContractDataOracle;
|
|
105
120
|
private simulatorOracle: SimulatorOracle;
|
|
106
121
|
|
|
122
|
+
private publicDataWrites: PublicDataWrite[] = [];
|
|
107
123
|
private uniqueNoteHashesFromPublic: Fr[] = [];
|
|
108
124
|
private siloedNullifiersFromPublic: Fr[] = [];
|
|
109
125
|
private privateLogs: PrivateLog[] = [];
|
|
110
|
-
private publicLogs:
|
|
126
|
+
private publicLogs: PublicLog[] = [];
|
|
111
127
|
|
|
112
128
|
private committedBlocks = new Set<number>();
|
|
113
129
|
|
|
@@ -122,18 +138,19 @@ export class TXE implements TypedOracle {
|
|
|
122
138
|
|
|
123
139
|
debug: LogFn;
|
|
124
140
|
|
|
125
|
-
constructor(
|
|
141
|
+
private constructor(
|
|
126
142
|
private logger: Logger,
|
|
127
|
-
private trees: MerkleTrees,
|
|
128
143
|
private executionCache: HashedValuesCache,
|
|
129
144
|
private keyStore: KeyStore,
|
|
130
145
|
private txeDatabase: TXEDatabase,
|
|
146
|
+
private contractAddress: AztecAddress,
|
|
147
|
+
private nativeWorldStateService: NativeWorldStateService,
|
|
148
|
+
private baseFork: MerkleTreeWriteOperations,
|
|
131
149
|
) {
|
|
132
150
|
this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
|
|
133
151
|
this.contractDataOracle = new ContractDataOracle(txeDatabase);
|
|
134
|
-
this.contractAddress = AztecAddress.random();
|
|
135
152
|
|
|
136
|
-
this.node = new TXENode(this.blockNumber, this.VERSION, this.CHAIN_ID,
|
|
153
|
+
this.node = new TXENode(this.blockNumber, this.VERSION, this.CHAIN_ID, nativeWorldStateService, baseFork);
|
|
137
154
|
|
|
138
155
|
// Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404)
|
|
139
156
|
this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE);
|
|
@@ -148,14 +165,33 @@ export class TXE implements TypedOracle {
|
|
|
148
165
|
this.debug = createDebugOnlyLogger('aztec:kv-pxe-database');
|
|
149
166
|
}
|
|
150
167
|
|
|
168
|
+
static async create(
|
|
169
|
+
logger: Logger,
|
|
170
|
+
executionCache: HashedValuesCache,
|
|
171
|
+
keyStore: KeyStore,
|
|
172
|
+
txeDatabase: TXEDatabase,
|
|
173
|
+
nativeWorldStateService: NativeWorldStateService,
|
|
174
|
+
baseFork: MerkleTreeWriteOperations,
|
|
175
|
+
) {
|
|
176
|
+
return new TXE(
|
|
177
|
+
logger,
|
|
178
|
+
executionCache,
|
|
179
|
+
keyStore,
|
|
180
|
+
txeDatabase,
|
|
181
|
+
await AztecAddress.random(),
|
|
182
|
+
nativeWorldStateService,
|
|
183
|
+
baseFork,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
151
187
|
// Utils
|
|
152
188
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return
|
|
189
|
+
getNativeWorldStateService() {
|
|
190
|
+
return this.nativeWorldStateService;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
getBaseFork() {
|
|
194
|
+
return this.baseFork;
|
|
159
195
|
}
|
|
160
196
|
|
|
161
197
|
getChainId(): Promise<Fr> {
|
|
@@ -199,10 +235,6 @@ export class TXE implements TypedOracle {
|
|
|
199
235
|
this.node.setBlockNumber(blockNumber);
|
|
200
236
|
}
|
|
201
237
|
|
|
202
|
-
getTrees() {
|
|
203
|
-
return this.trees;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
238
|
getContractDataOracle() {
|
|
207
239
|
return this.contractDataOracle;
|
|
208
240
|
}
|
|
@@ -220,8 +252,8 @@ export class TXE implements TypedOracle {
|
|
|
220
252
|
}
|
|
221
253
|
|
|
222
254
|
async addContractArtifact(artifact: ContractArtifact) {
|
|
223
|
-
const contractClass = getContractClassFromArtifact(artifact);
|
|
224
|
-
await this.txeDatabase.addContractArtifact(computeContractClassId(contractClass), artifact);
|
|
255
|
+
const contractClass = await getContractClassFromArtifact(artifact);
|
|
256
|
+
await this.txeDatabase.addContractArtifact(await computeContractClassId(contractClass), artifact);
|
|
225
257
|
}
|
|
226
258
|
|
|
227
259
|
async getPrivateContextInputs(
|
|
@@ -229,10 +261,21 @@ export class TXE implements TypedOracle {
|
|
|
229
261
|
sideEffectsCounter = this.sideEffectCounter,
|
|
230
262
|
isStaticCall = false,
|
|
231
263
|
) {
|
|
232
|
-
|
|
233
|
-
|
|
264
|
+
if (blockNumber > this.blockNumber) {
|
|
265
|
+
throw new Error(
|
|
266
|
+
`Tried to request private context inputs for ${blockNumber}, which is greater than our current block number of ${this.blockNumber}`,
|
|
267
|
+
);
|
|
268
|
+
} else if (blockNumber === this.blockNumber) {
|
|
269
|
+
this.logger.debug(
|
|
270
|
+
`Tried to request private context inputs for ${blockNumber}, equal to current block of ${this.blockNumber}. Clamping to current block - 1.`,
|
|
271
|
+
);
|
|
272
|
+
blockNumber = this.blockNumber - 1;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
276
|
+
const previousBlockState = this.nativeWorldStateService.getSnapshot(blockNumber - 1);
|
|
234
277
|
|
|
235
|
-
const stateReference = await
|
|
278
|
+
const stateReference = await snap.getStateReference();
|
|
236
279
|
const inputs = PrivateContextInputs.empty();
|
|
237
280
|
inputs.txContext.chainId = new Fr(await this.node.getChainId());
|
|
238
281
|
inputs.txContext.version = new Fr(await this.node.getVersion());
|
|
@@ -254,32 +297,23 @@ export class TXE implements TypedOracle {
|
|
|
254
297
|
const account = await this.txeDatabase.getAccount(address);
|
|
255
298
|
const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
|
|
256
299
|
const schnorr = new Schnorr();
|
|
257
|
-
const signature = schnorr.constructSignature(messageHash.toBuffer(), privateKey)
|
|
258
|
-
const authWitness = new AuthWitness(messageHash, [...signature]);
|
|
300
|
+
const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
|
|
301
|
+
const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
|
|
259
302
|
return this.txeDatabase.addAuthWitness(authWitness.requestHash, authWitness.witness);
|
|
260
303
|
}
|
|
261
304
|
|
|
262
305
|
async addPublicDataWrites(writes: PublicDataWrite[]) {
|
|
263
|
-
|
|
264
|
-
|
|
306
|
+
this.publicDataWrites.push(...writes);
|
|
307
|
+
|
|
308
|
+
await this.baseFork.sequentialInsert(
|
|
265
309
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
266
310
|
writes.map(w => new PublicDataTreeLeaf(w.leafSlot, w.value).toBuffer()),
|
|
267
|
-
0,
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
async addSiloedNullifiers(siloedNullifiers: Fr[]) {
|
|
272
|
-
const db = await this.trees.getLatest();
|
|
273
|
-
await db.batchInsert(
|
|
274
|
-
MerkleTreeId.NULLIFIER_TREE,
|
|
275
|
-
siloedNullifiers.map(n => n.toBuffer()),
|
|
276
|
-
NULLIFIER_SUBTREE_HEIGHT,
|
|
277
311
|
);
|
|
278
312
|
}
|
|
279
313
|
|
|
280
314
|
async checkNullifiersNotInTree(contractAddress: AztecAddress, nullifiers: Fr[]) {
|
|
281
|
-
const siloedNullifiers = nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier));
|
|
282
|
-
const db =
|
|
315
|
+
const siloedNullifiers = await Promise.all(nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier)));
|
|
316
|
+
const db = this.baseFork;
|
|
283
317
|
const nullifierIndexesInTree = await db.findLeafIndices(
|
|
284
318
|
MerkleTreeId.NULLIFIER_TREE,
|
|
285
319
|
siloedNullifiers.map(n => n.toBuffer()),
|
|
@@ -289,61 +323,29 @@ export class TXE implements TypedOracle {
|
|
|
289
323
|
}
|
|
290
324
|
}
|
|
291
325
|
|
|
292
|
-
|
|
326
|
+
addSiloedNullifiersFromPublic(siloedNullifiers: Fr[]) {
|
|
293
327
|
this.siloedNullifiersFromPublic.push(...siloedNullifiers);
|
|
294
|
-
|
|
295
|
-
await this.addSiloedNullifiers(siloedNullifiers);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
async addNullifiers(contractAddress: AztecAddress, nullifiers: Fr[]) {
|
|
299
|
-
const siloedNullifiers = nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier));
|
|
300
|
-
await this.addSiloedNullifiers(siloedNullifiers);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
async addUniqueNoteHashes(siloedNoteHashes: Fr[]) {
|
|
304
|
-
const db = await this.trees.getLatest();
|
|
305
|
-
await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, siloedNoteHashes);
|
|
306
328
|
}
|
|
307
329
|
|
|
308
|
-
|
|
330
|
+
addUniqueNoteHashesFromPublic(siloedNoteHashes: Fr[]) {
|
|
309
331
|
this.uniqueNoteHashesFromPublic.push(...siloedNoteHashes);
|
|
310
|
-
await this.addUniqueNoteHashes(siloedNoteHashes);
|
|
311
332
|
}
|
|
312
333
|
|
|
313
|
-
async
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
addPrivateLogs(contractAddress: AztecAddress, privateLogs: PrivateLog[]) {
|
|
320
|
-
privateLogs.forEach(privateLog => {
|
|
321
|
-
privateLog.fields[0] = poseidon2Hash([contractAddress, privateLog.fields[0]]);
|
|
322
|
-
});
|
|
334
|
+
async addPrivateLogs(contractAddress: AztecAddress, privateLogs: PrivateLog[]) {
|
|
335
|
+
for (const privateLog of privateLogs) {
|
|
336
|
+
privateLog.fields[0] = await poseidon2Hash([contractAddress, privateLog.fields[0]]);
|
|
337
|
+
}
|
|
323
338
|
|
|
324
339
|
this.privateLogs.push(...privateLogs);
|
|
325
340
|
}
|
|
326
341
|
|
|
327
|
-
addPublicLogs(logs:
|
|
342
|
+
addPublicLogs(logs: PublicLog[]) {
|
|
328
343
|
logs.forEach(log => {
|
|
329
|
-
if (log.data.length < 32 * 33) {
|
|
330
|
-
// TODO remove when #9835 and #9836 are fixed
|
|
331
|
-
this.logger.warn(`Skipping unencrypted log with insufficient data length: ${log.data.length}`);
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
344
|
try {
|
|
335
|
-
//
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const initialOffset = 32;
|
|
340
|
-
for (let i = 0; i < 32; i++) {
|
|
341
|
-
const byte = Fr.fromBuffer(log.data.subarray(i * 32 + initialOffset, i * 32 + 32 + initialOffset)).toNumber();
|
|
342
|
-
correctedBuffer.writeUInt8(byte, i);
|
|
343
|
-
}
|
|
344
|
-
const tag = new Fr(correctedBuffer);
|
|
345
|
-
|
|
346
|
-
this.logger.verbose(`Found tagged unencrypted log with tag ${tag.toString()} in block ${this.blockNumber}`);
|
|
345
|
+
// The first elt stores lengths => tag is in fields[1]
|
|
346
|
+
const tag = log.log[1];
|
|
347
|
+
|
|
348
|
+
this.logger.verbose(`Found tagged public log with tag ${tag.toString()} in block ${this.blockNumber}`);
|
|
347
349
|
this.publicLogs.push(log);
|
|
348
350
|
} catch (err) {
|
|
349
351
|
this.logger.warn(`Failed to add tagged log to store: ${err}`);
|
|
@@ -373,12 +375,8 @@ export class TXE implements TypedOracle {
|
|
|
373
375
|
return Fr.random();
|
|
374
376
|
}
|
|
375
377
|
|
|
376
|
-
storeArrayInExecutionCache(values: Fr[]) {
|
|
377
|
-
return Promise.resolve(this.executionCache.store(values));
|
|
378
|
-
}
|
|
379
|
-
|
|
380
378
|
storeInExecutionCache(values: Fr[]) {
|
|
381
|
-
return
|
|
379
|
+
return this.executionCache.store(values);
|
|
382
380
|
}
|
|
383
381
|
|
|
384
382
|
loadFromExecutionCache(returnsHash: Fr) {
|
|
@@ -398,34 +396,36 @@ export class TXE implements TypedOracle {
|
|
|
398
396
|
}
|
|
399
397
|
|
|
400
398
|
async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[] | undefined> {
|
|
401
|
-
const
|
|
402
|
-
const index = (await
|
|
399
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
400
|
+
const index = (await snap.findLeafIndices(treeId, [leafValue.toBuffer()]))[0];
|
|
403
401
|
if (index === undefined) {
|
|
404
402
|
throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]} at block ${blockNumber}`);
|
|
405
403
|
}
|
|
406
|
-
const siblingPath = await
|
|
404
|
+
const siblingPath = await snap.getSiblingPath(treeId, index);
|
|
407
405
|
|
|
408
406
|
return [new Fr(index), ...siblingPath.toFields()];
|
|
409
407
|
}
|
|
410
408
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
409
|
+
async getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: Fr) {
|
|
410
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
411
|
+
|
|
412
|
+
const result = await snap.getSiblingPath(treeId, leafIndex.toBigInt());
|
|
413
|
+
return result.toFields();
|
|
414
|
+
}
|
|
416
415
|
|
|
417
416
|
async getNullifierMembershipWitness(
|
|
418
417
|
blockNumber: number,
|
|
419
418
|
nullifier: Fr,
|
|
420
419
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
421
|
-
const
|
|
422
|
-
|
|
420
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
421
|
+
|
|
422
|
+
const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
423
423
|
if (!index) {
|
|
424
424
|
return undefined;
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
const leafPreimagePromise =
|
|
428
|
-
const siblingPathPromise =
|
|
427
|
+
const leafPreimagePromise = snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
|
|
428
|
+
const siblingPathPromise = snap.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
|
|
429
429
|
MerkleTreeId.NULLIFIER_TREE,
|
|
430
430
|
BigInt(index),
|
|
431
431
|
);
|
|
@@ -440,16 +440,17 @@ export class TXE implements TypedOracle {
|
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
async getPublicDataTreeWitness(blockNumber: number, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
|
|
443
|
-
const
|
|
444
|
-
|
|
443
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
444
|
+
|
|
445
|
+
const lowLeafResult = await snap.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
445
446
|
if (!lowLeafResult) {
|
|
446
447
|
return undefined;
|
|
447
448
|
} else {
|
|
448
|
-
const preimage = (await
|
|
449
|
+
const preimage = (await snap.getLeafPreimage(
|
|
449
450
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
450
451
|
lowLeafResult.index,
|
|
451
452
|
)) as PublicDataTreeLeafPreimage;
|
|
452
|
-
const path = await
|
|
453
|
+
const path = await snap.getSiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>(
|
|
453
454
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
454
455
|
lowLeafResult.index,
|
|
455
456
|
);
|
|
@@ -461,8 +462,9 @@ export class TXE implements TypedOracle {
|
|
|
461
462
|
blockNumber: number,
|
|
462
463
|
nullifier: Fr,
|
|
463
464
|
): Promise<NullifierMembershipWitness | undefined> {
|
|
464
|
-
const
|
|
465
|
-
|
|
465
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
466
|
+
|
|
467
|
+
const findResult = await snap.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
466
468
|
if (!findResult) {
|
|
467
469
|
return undefined;
|
|
468
470
|
}
|
|
@@ -470,9 +472,9 @@ export class TXE implements TypedOracle {
|
|
|
470
472
|
if (alreadyPresent) {
|
|
471
473
|
this.logger.warn(`Nullifier ${nullifier.toBigInt()} already exists in the tree`);
|
|
472
474
|
}
|
|
473
|
-
const preimageData = (await
|
|
475
|
+
const preimageData = (await snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))!;
|
|
474
476
|
|
|
475
|
-
const siblingPath = await
|
|
477
|
+
const siblingPath = await snap.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
|
|
476
478
|
MerkleTreeId.NULLIFIER_TREE,
|
|
477
479
|
BigInt(index),
|
|
478
480
|
);
|
|
@@ -480,10 +482,26 @@ export class TXE implements TypedOracle {
|
|
|
480
482
|
}
|
|
481
483
|
|
|
482
484
|
async getBlockHeader(blockNumber: number): Promise<BlockHeader | undefined> {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
485
|
+
if (blockNumber === 1) {
|
|
486
|
+
// TODO: Figure out why native merkle trees cannot get snapshot of 0, as it defaults to latest
|
|
487
|
+
throw new Error('Cannot get the block header of block number 1');
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
491
|
+
const stateReference = await snap.getStateReference();
|
|
492
|
+
|
|
493
|
+
const previousState = this.nativeWorldStateService.getSnapshot(blockNumber - 1);
|
|
494
|
+
const archiveInfo = await previousState.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
495
|
+
|
|
496
|
+
const header = new BlockHeader(
|
|
497
|
+
new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
|
|
498
|
+
makeContentCommitment(),
|
|
499
|
+
stateReference,
|
|
500
|
+
makeGlobalVariables(),
|
|
501
|
+
Fr.ZERO,
|
|
502
|
+
Fr.ZERO,
|
|
503
|
+
);
|
|
504
|
+
|
|
487
505
|
return header;
|
|
488
506
|
}
|
|
489
507
|
|
|
@@ -564,21 +582,20 @@ export class TXE implements TypedOracle {
|
|
|
564
582
|
|
|
565
583
|
async notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
|
|
566
584
|
await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
|
|
567
|
-
this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
|
|
585
|
+
await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
|
|
568
586
|
this.sideEffectCounter = counter + 1;
|
|
569
|
-
return Promise.resolve();
|
|
570
587
|
}
|
|
571
588
|
|
|
572
589
|
async notifyCreatedNullifier(innerNullifier: Fr): Promise<void> {
|
|
573
590
|
await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
|
|
574
|
-
this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
|
|
575
|
-
return Promise.resolve();
|
|
591
|
+
await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
|
|
576
592
|
}
|
|
577
593
|
|
|
578
594
|
async checkNullifierExists(innerNullifier: Fr): Promise<boolean> {
|
|
579
|
-
const
|
|
580
|
-
|
|
581
|
-
const
|
|
595
|
+
const snap = this.nativeWorldStateService.getSnapshot(this.blockNumber - 1);
|
|
596
|
+
|
|
597
|
+
const nullifier = await siloNullifier(this.contractAddress, innerNullifier!);
|
|
598
|
+
const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
|
|
582
599
|
return index !== undefined;
|
|
583
600
|
}
|
|
584
601
|
|
|
@@ -596,11 +613,17 @@ export class TXE implements TypedOracle {
|
|
|
596
613
|
blockNumber: number,
|
|
597
614
|
numberOfElements: number,
|
|
598
615
|
): Promise<Fr[]> {
|
|
599
|
-
|
|
616
|
+
let db: MerkleTreeReadOperations;
|
|
617
|
+
if (blockNumber === this.blockNumber) {
|
|
618
|
+
db = this.baseFork;
|
|
619
|
+
} else {
|
|
620
|
+
db = this.nativeWorldStateService.getSnapshot(blockNumber);
|
|
621
|
+
}
|
|
622
|
+
|
|
600
623
|
const values = [];
|
|
601
624
|
for (let i = 0n; i < numberOfElements; i++) {
|
|
602
625
|
const storageSlot = startStorageSlot.add(new Fr(i));
|
|
603
|
-
const leafSlot = computePublicDataTreeLeafSlot(contractAddress, storageSlot).toBigInt();
|
|
626
|
+
const leafSlot = (await computePublicDataTreeLeafSlot(contractAddress, storageSlot)).toBigInt();
|
|
604
627
|
|
|
605
628
|
const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot);
|
|
606
629
|
|
|
@@ -619,18 +642,15 @@ export class TXE implements TypedOracle {
|
|
|
619
642
|
}
|
|
620
643
|
|
|
621
644
|
async storageWrite(startStorageSlot: Fr, values: Fr[]): Promise<Fr[]> {
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
});
|
|
629
|
-
await db.batchInsert(
|
|
630
|
-
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
631
|
-
publicDataWrites.map(write => write.toBuffer()),
|
|
632
|
-
0,
|
|
645
|
+
const publicDataWrites = await Promise.all(
|
|
646
|
+
values.map(async (value, i) => {
|
|
647
|
+
const storageSlot = startStorageSlot.add(new Fr(i));
|
|
648
|
+
this.logger.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${value}`);
|
|
649
|
+
return new PublicDataWrite(await computePublicDataTreeLeafSlot(this.contractAddress, storageSlot), value);
|
|
650
|
+
}),
|
|
633
651
|
);
|
|
652
|
+
|
|
653
|
+
await this.addPublicDataWrites(publicDataWrites);
|
|
634
654
|
return publicDataWrites.map(write => write.value);
|
|
635
655
|
}
|
|
636
656
|
|
|
@@ -643,35 +663,91 @@ export class TXE implements TypedOracle {
|
|
|
643
663
|
this.committedBlocks.add(blockNumber);
|
|
644
664
|
}
|
|
645
665
|
|
|
666
|
+
const fork = this.baseFork;
|
|
667
|
+
|
|
646
668
|
const txEffect = TxEffect.empty();
|
|
647
669
|
|
|
648
670
|
const nonceGenerator = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
|
|
649
671
|
|
|
650
672
|
let i = 0;
|
|
651
|
-
|
|
652
|
-
|
|
673
|
+
const uniqueNoteHashesFromPrivate = await Promise.all(
|
|
674
|
+
this.noteCache
|
|
653
675
|
.getAllNotes()
|
|
654
|
-
.map(pendingNote =>
|
|
676
|
+
.map(async pendingNote =>
|
|
655
677
|
computeUniqueNoteHash(
|
|
656
|
-
computeNoteHashNonce(nonceGenerator, i++),
|
|
657
|
-
siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption),
|
|
678
|
+
await computeNoteHashNonce(nonceGenerator, i++),
|
|
679
|
+
await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption),
|
|
658
680
|
),
|
|
659
681
|
),
|
|
660
|
-
|
|
661
|
-
];
|
|
682
|
+
);
|
|
683
|
+
txEffect.noteHashes = [...uniqueNoteHashesFromPrivate, ...this.uniqueNoteHashesFromPublic];
|
|
662
684
|
|
|
663
|
-
txEffect.nullifiers = this.noteCache.getAllNullifiers();
|
|
685
|
+
txEffect.nullifiers = [...this.siloedNullifiersFromPublic, ...this.noteCache.getAllNullifiers()];
|
|
664
686
|
if (usedTxRequestHashForNonces) {
|
|
665
687
|
txEffect.nullifiers.unshift(this.getTxRequestHash());
|
|
666
688
|
}
|
|
667
|
-
|
|
689
|
+
|
|
690
|
+
txEffect.publicDataWrites = this.publicDataWrites;
|
|
691
|
+
|
|
692
|
+
const body = new Body([txEffect]);
|
|
693
|
+
|
|
694
|
+
const l2Block = new L2Block(
|
|
695
|
+
makeAppendOnlyTreeSnapshot(blockNumber + 1),
|
|
696
|
+
makeHeader(0, blockNumber, blockNumber),
|
|
697
|
+
body,
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
const paddedTxEffects = l2Block.body.txEffects;
|
|
701
|
+
|
|
702
|
+
const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
|
|
703
|
+
|
|
704
|
+
{
|
|
705
|
+
const noteHashesPadded = paddedTxEffects.flatMap(txEffect =>
|
|
706
|
+
padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
|
|
707
|
+
);
|
|
708
|
+
await fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
|
|
709
|
+
|
|
710
|
+
await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
{
|
|
714
|
+
for (const txEffect of paddedTxEffects) {
|
|
715
|
+
// We do not need to add public data writes because we apply them as we go. We use the sequentialInsert because
|
|
716
|
+
// the batchInsert was not working when updating a previously updated slot.
|
|
717
|
+
|
|
718
|
+
const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
|
|
719
|
+
|
|
720
|
+
await fork.batchInsert(
|
|
721
|
+
MerkleTreeId.NULLIFIER_TREE,
|
|
722
|
+
nullifiersPadded.map(nullifier => nullifier.toBuffer()),
|
|
723
|
+
NULLIFIER_SUBTREE_HEIGHT,
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
await this.node.setTxEffect(blockNumber, new TxHash(new Fr(blockNumber)), txEffect);
|
|
668
729
|
this.node.setNullifiersIndexesWithBlock(blockNumber, txEffect.nullifiers);
|
|
669
730
|
this.node.addNoteLogsByTags(this.blockNumber, this.privateLogs);
|
|
670
731
|
this.node.addPublicLogsByTags(this.blockNumber, this.publicLogs);
|
|
671
732
|
|
|
672
|
-
await
|
|
673
|
-
await
|
|
733
|
+
const stateReference = await fork.getStateReference();
|
|
734
|
+
const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
|
|
735
|
+
const header = new BlockHeader(
|
|
736
|
+
new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
|
|
737
|
+
makeContentCommitment(),
|
|
738
|
+
stateReference,
|
|
739
|
+
makeGlobalVariables(),
|
|
740
|
+
Fr.ZERO,
|
|
741
|
+
Fr.ZERO,
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
l2Block.header = header;
|
|
674
745
|
|
|
746
|
+
await fork.updateArchive(l2Block.header);
|
|
747
|
+
|
|
748
|
+
await this.nativeWorldStateService.handleL2BlockAndMessages(l2Block, l1ToL2Messages);
|
|
749
|
+
|
|
750
|
+
this.publicDataWrites = [];
|
|
675
751
|
this.privateLogs = [];
|
|
676
752
|
this.publicLogs = [];
|
|
677
753
|
this.uniqueNoteHashesFromPublic = [];
|
|
@@ -750,7 +826,7 @@ export class TXE implements TypedOracle {
|
|
|
750
826
|
const endSideEffectCounter = publicInputs.endSideEffectCounter;
|
|
751
827
|
this.sideEffectCounter = endSideEffectCounter.toNumber() + 1;
|
|
752
828
|
|
|
753
|
-
this.addPrivateLogs(
|
|
829
|
+
await this.addPrivateLogs(
|
|
754
830
|
targetContractAddress,
|
|
755
831
|
publicInputs.privateLogs.filter(privateLog => !privateLog.isEmpty()).map(privateLog => privateLog.log),
|
|
756
832
|
);
|
|
@@ -794,22 +870,25 @@ export class TXE implements TypedOracle {
|
|
|
794
870
|
if (!artifact) {
|
|
795
871
|
return undefined;
|
|
796
872
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
873
|
+
const functionSelectorsAndNames = await Promise.all(
|
|
874
|
+
artifact.functions.map(async f => ({
|
|
875
|
+
name: f.name,
|
|
876
|
+
selector: await FunctionSelector.fromNameAndParameters(f.name, f.parameters),
|
|
877
|
+
})),
|
|
800
878
|
);
|
|
801
|
-
|
|
879
|
+
const functionSelectorAndName = functionSelectorsAndNames.find(f => f.selector.equals(selector));
|
|
880
|
+
if (!functionSelectorAndName) {
|
|
802
881
|
return undefined;
|
|
803
882
|
}
|
|
804
883
|
|
|
805
|
-
return `${artifact.name}:${
|
|
884
|
+
return `${artifact.name}:${functionSelectorAndName.name}`;
|
|
806
885
|
}
|
|
807
886
|
|
|
808
887
|
private async executePublicFunction(args: Fr[], callContext: CallContext, isTeardown: boolean = false) {
|
|
809
888
|
const executionRequest = new PublicExecutionRequest(callContext, args);
|
|
810
889
|
|
|
811
|
-
const db =
|
|
812
|
-
const worldStateDb = new TXEWorldStateDB(db, new TXEPublicContractDataSource(this));
|
|
890
|
+
const db = this.baseFork;
|
|
891
|
+
const worldStateDb = new TXEWorldStateDB(db, new TXEPublicContractDataSource(this), this);
|
|
813
892
|
|
|
814
893
|
const globalVariables = GlobalVariables.empty();
|
|
815
894
|
globalVariables.chainId = new Fr(await this.node.getChainId());
|
|
@@ -817,38 +896,65 @@ export class TXE implements TypedOracle {
|
|
|
817
896
|
globalVariables.blockNumber = new Fr(this.blockNumber);
|
|
818
897
|
globalVariables.gasFees = new GasFees(1, 1);
|
|
819
898
|
|
|
899
|
+
const tempFork = await this.nativeWorldStateService.fork();
|
|
900
|
+
// Apply current public data writes
|
|
901
|
+
await tempFork.sequentialInsert(
|
|
902
|
+
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
903
|
+
this.publicDataWrites.map(p => p.toBuffer()),
|
|
904
|
+
);
|
|
905
|
+
|
|
820
906
|
// If the contract instance exists in the TXE's world state, make sure its nullifier is present in the tree
|
|
821
907
|
// so its nullifier check passes.
|
|
822
908
|
if ((await worldStateDb.getContractInstance(callContext.contractAddress)) !== undefined) {
|
|
823
|
-
const contractAddressNullifier = siloNullifier(
|
|
909
|
+
const contractAddressNullifier = await siloNullifier(
|
|
824
910
|
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
825
911
|
callContext.contractAddress.toField(),
|
|
826
912
|
);
|
|
827
913
|
if ((await worldStateDb.getNullifierIndex(contractAddressNullifier)) === undefined) {
|
|
828
|
-
await
|
|
914
|
+
await tempFork.batchInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()], 0);
|
|
829
915
|
}
|
|
830
916
|
}
|
|
831
917
|
|
|
832
918
|
const simulator = new PublicTxSimulator(
|
|
833
|
-
|
|
834
|
-
new TXEWorldStateDB(
|
|
919
|
+
tempFork,
|
|
920
|
+
new TXEWorldStateDB(tempFork, new TXEPublicContractDataSource(this), this),
|
|
835
921
|
globalVariables,
|
|
836
922
|
);
|
|
837
923
|
|
|
924
|
+
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
925
|
+
const firstNullifier = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
|
|
926
|
+
|
|
838
927
|
// When setting up a teardown call, we tell it that
|
|
839
928
|
// private execution used Gas(1, 1) so it can compute a tx fee.
|
|
840
929
|
const gasUsedByPrivate = isTeardown ? new Gas(1, 1) : Gas.empty();
|
|
841
|
-
const tx = createTxForPublicCalls(
|
|
930
|
+
const tx = await createTxForPublicCalls(
|
|
931
|
+
firstNullifier,
|
|
842
932
|
/*setupExecutionRequests=*/ [],
|
|
843
933
|
/*appExecutionRequests=*/ isTeardown ? [] : [executionRequest],
|
|
844
934
|
/*teardownExecutionRequests=*/ isTeardown ? executionRequest : undefined,
|
|
935
|
+
/*feePayer=*/ AztecAddress.zero(),
|
|
845
936
|
gasUsedByPrivate,
|
|
846
937
|
);
|
|
847
938
|
|
|
848
939
|
const result = await simulator.simulate(tx);
|
|
940
|
+
const noteHashes = result.avmProvingRequest.inputs.publicInputs.accumulatedData.noteHashes.filter(
|
|
941
|
+
s => !s.isEmpty(),
|
|
942
|
+
);
|
|
943
|
+
|
|
944
|
+
const publicDataWrites = result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicDataWrites.filter(
|
|
945
|
+
s => !s.isEmpty(),
|
|
946
|
+
);
|
|
947
|
+
await this.addPublicDataWrites(publicDataWrites);
|
|
948
|
+
|
|
949
|
+
this.addUniqueNoteHashesFromPublic(noteHashes);
|
|
849
950
|
|
|
850
|
-
this.addPublicLogs(
|
|
951
|
+
this.addPublicLogs(
|
|
952
|
+
result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicLogs.filter(
|
|
953
|
+
log => !log.contractAddress.equals(AztecAddress.ZERO),
|
|
954
|
+
),
|
|
955
|
+
);
|
|
851
956
|
|
|
957
|
+
await tempFork.close();
|
|
852
958
|
return Promise.resolve(result);
|
|
853
959
|
}
|
|
854
960
|
|
|
@@ -876,7 +982,7 @@ export class TXE implements TypedOracle {
|
|
|
876
982
|
);
|
|
877
983
|
|
|
878
984
|
const args = [this.functionSelector.toField(), ...this.executionCache.getPreimage(argsHash)];
|
|
879
|
-
const newArgsHash = this.executionCache.store(args);
|
|
985
|
+
const newArgsHash = await this.executionCache.store(args);
|
|
880
986
|
|
|
881
987
|
const executionResult = await this.executePublicFunction(args, callContext, isTeardown);
|
|
882
988
|
|
|
@@ -896,13 +1002,14 @@ export class TXE implements TypedOracle {
|
|
|
896
1002
|
}
|
|
897
1003
|
|
|
898
1004
|
// Apply side effects
|
|
899
|
-
const sideEffects = executionResult.avmProvingRequest.inputs.
|
|
900
|
-
|
|
901
|
-
const
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1005
|
+
const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
|
|
1006
|
+
|
|
1007
|
+
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
1008
|
+
const firstNullifier = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
|
|
1009
|
+
const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
|
|
1010
|
+
|
|
1011
|
+
// For some reason we cannot move this up to 'executePublicFunction'. It gives us an error of trying to modify the same nullifier twice.
|
|
1012
|
+
this.addSiloedNullifiersFromPublic(nullifiers);
|
|
906
1013
|
|
|
907
1014
|
this.setContractAddress(currentContractAddress);
|
|
908
1015
|
this.setMsgSender(currentMessageSender);
|
|
@@ -930,8 +1037,8 @@ export class TXE implements TypedOracle {
|
|
|
930
1037
|
);
|
|
931
1038
|
}
|
|
932
1039
|
|
|
933
|
-
notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
934
|
-
this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
1040
|
+
async notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
|
|
1041
|
+
await this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
|
|
935
1042
|
}
|
|
936
1043
|
|
|
937
1044
|
debugLog(message: string, fields: Fr[]): void {
|
|
@@ -953,7 +1060,7 @@ export class TXE implements TypedOracle {
|
|
|
953
1060
|
async #calculateAppTaggingSecret(contractAddress: AztecAddress, sender: AztecAddress, recipient: AztecAddress) {
|
|
954
1061
|
const senderCompleteAddress = await this.getCompleteAddress(sender);
|
|
955
1062
|
const senderIvsk = await this.keyStore.getMasterIncomingViewingSecretKey(sender);
|
|
956
|
-
const secretPoint = computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient);
|
|
1063
|
+
const secretPoint = await computeTaggingSecretPoint(senderCompleteAddress, senderIvsk, recipient);
|
|
957
1064
|
// Silo the secret to the app so it can't be used to track other app's notes
|
|
958
1065
|
const appSecret = poseidon2Hash([secretPoint.x, secretPoint.y, contractAddress]);
|
|
959
1066
|
return appSecret;
|
|
@@ -1010,13 +1117,17 @@ export class TXE implements TypedOracle {
|
|
|
1010
1117
|
|
|
1011
1118
|
// Apply side effects
|
|
1012
1119
|
if (executionResult.revertCode.isOK()) {
|
|
1013
|
-
const sideEffects = executionResult.avmProvingRequest.inputs.
|
|
1120
|
+
const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
|
|
1014
1121
|
const publicDataWrites = sideEffects.publicDataWrites.filter(s => !s.isEmpty());
|
|
1015
1122
|
const noteHashes = sideEffects.noteHashes.filter(s => !s.isEmpty());
|
|
1016
|
-
const
|
|
1123
|
+
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
1124
|
+
const firstNullifier = usedTxRequestHashForNonces
|
|
1125
|
+
? this.getTxRequestHash()
|
|
1126
|
+
: this.noteCache.getAllNullifiers()[0];
|
|
1127
|
+
const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
|
|
1017
1128
|
await this.addPublicDataWrites(publicDataWrites);
|
|
1018
|
-
|
|
1019
|
-
|
|
1129
|
+
this.addUniqueNoteHashesFromPublic(noteHashes);
|
|
1130
|
+
this.addSiloedNullifiersFromPublic(nullifiers);
|
|
1020
1131
|
}
|
|
1021
1132
|
|
|
1022
1133
|
this.setContractAddress(currentContractAddress);
|
|
@@ -1034,37 +1145,35 @@ export class TXE implements TypedOracle {
|
|
|
1034
1145
|
}
|
|
1035
1146
|
|
|
1036
1147
|
async avmOpcodeNullifierExists(innerNullifier: Fr, targetAddress: AztecAddress): Promise<boolean> {
|
|
1037
|
-
const nullifier = siloNullifier(targetAddress, innerNullifier!);
|
|
1038
|
-
const db =
|
|
1148
|
+
const nullifier = await siloNullifier(targetAddress, innerNullifier!);
|
|
1149
|
+
const db = this.baseFork;
|
|
1039
1150
|
const index = (await db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]))[0];
|
|
1040
1151
|
return index !== undefined;
|
|
1041
1152
|
}
|
|
1042
1153
|
|
|
1043
1154
|
async avmOpcodeEmitNullifier(nullifier: Fr) {
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
|
|
1155
|
+
const siloedNullifier = await siloNullifier(this.contractAddress, nullifier);
|
|
1156
|
+
this.addSiloedNullifiersFromPublic([siloedNullifier]);
|
|
1157
|
+
|
|
1047
1158
|
return Promise.resolve();
|
|
1048
1159
|
}
|
|
1049
1160
|
|
|
1161
|
+
// Doesn't this need to get hashed w/ the nonce ?
|
|
1050
1162
|
async avmOpcodeEmitNoteHash(noteHash: Fr) {
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1053
|
-
await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [siloedNoteHash]);
|
|
1163
|
+
const siloedNoteHash = await siloNoteHash(this.contractAddress, noteHash);
|
|
1164
|
+
this.addUniqueNoteHashesFromPublic([siloedNoteHash]);
|
|
1054
1165
|
return Promise.resolve();
|
|
1055
1166
|
}
|
|
1056
1167
|
|
|
1057
1168
|
async avmOpcodeStorageRead(slot: Fr) {
|
|
1058
|
-
const
|
|
1059
|
-
|
|
1060
|
-
const leafSlot = computePublicDataTreeLeafSlot(this.contractAddress, slot);
|
|
1169
|
+
const leafSlot = await computePublicDataTreeLeafSlot(this.contractAddress, slot);
|
|
1061
1170
|
|
|
1062
|
-
const lowLeafResult = await
|
|
1171
|
+
const lowLeafResult = await this.baseFork.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
|
|
1063
1172
|
if (!lowLeafResult || !lowLeafResult.alreadyPresent) {
|
|
1064
1173
|
return Fr.ZERO;
|
|
1065
1174
|
}
|
|
1066
1175
|
|
|
1067
|
-
const preimage = (await
|
|
1176
|
+
const preimage = (await this.baseFork.getLeafPreimage(
|
|
1068
1177
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
1069
1178
|
lowLeafResult.index,
|
|
1070
1179
|
)) as PublicDataTreeLeafPreimage;
|