@aztec/simulator 0.37.0 → 0.38.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/acvm/acvm.d.ts +1 -1
- package/dest/acvm/acvm.d.ts.map +1 -1
- package/dest/acvm/acvm.js +2 -2
- package/dest/acvm/oracle/oracle.d.ts +5 -4
- package/dest/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/oracle.js +19 -8
- package/dest/acvm/oracle/typed_oracle.d.ts +3 -2
- package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/acvm/oracle/typed_oracle.js +6 -3
- package/dest/avm/avm_gas.d.ts.map +1 -1
- package/dest/avm/avm_gas.js +2 -1
- package/dest/avm/avm_memory_types.d.ts +1 -1
- package/dest/avm/avm_memory_types.d.ts.map +1 -1
- package/dest/avm/avm_simulator.d.ts.map +1 -1
- package/dest/avm/avm_simulator.js +3 -1
- package/dest/avm/journal/journal.d.ts +20 -1
- package/dest/avm/journal/journal.d.ts.map +1 -1
- package/dest/avm/journal/journal.js +69 -9
- package/dest/avm/journal/nullifiers.d.ts +3 -1
- package/dest/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/avm/journal/nullifiers.js +14 -6
- package/dest/avm/journal/public_storage.d.ts +10 -1
- package/dest/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/avm/journal/public_storage.js +17 -2
- package/dest/avm/journal/trace.d.ts +1 -4
- package/dest/avm/journal/trace.d.ts.map +1 -1
- package/dest/avm/journal/trace.js +4 -5
- package/dest/avm/journal/trace_types.d.ts +1 -0
- package/dest/avm/journal/trace_types.d.ts.map +1 -1
- package/dest/avm/journal/trace_types.js +1 -1
- package/dest/avm/opcodes/bitwise.d.ts +4 -1
- package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
- package/dest/avm/opcodes/bitwise.js +14 -2
- package/dest/avm/opcodes/environment_getters.d.ts +5 -0
- package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
- package/dest/avm/opcodes/environment_getters.js +8 -1
- package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
- package/dest/avm/opcodes/external_calls.js +14 -13
- package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/bytecode_serialization.js +3 -2
- package/dest/avm/serialization/instruction_serialization.d.ts +39 -38
- package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
- package/dest/avm/serialization/instruction_serialization.js +40 -39
- package/dest/client/client_execution_context.d.ts +31 -18
- package/dest/client/client_execution_context.d.ts.map +1 -1
- package/dest/client/client_execution_context.js +48 -31
- package/dest/client/db_oracle.d.ts +3 -3
- package/dest/client/db_oracle.d.ts.map +1 -1
- package/dest/client/execution_result.d.ts +19 -15
- package/dest/client/execution_result.d.ts.map +1 -1
- package/dest/client/execution_result.js +45 -12
- package/dest/client/logs_cache.d.ts +33 -0
- package/dest/client/logs_cache.d.ts.map +1 -0
- package/dest/client/logs_cache.js +59 -0
- package/dest/client/private_execution.d.ts +2 -2
- package/dest/client/private_execution.d.ts.map +1 -1
- package/dest/client/private_execution.js +3 -7
- package/dest/client/simulator.d.ts +3 -3
- package/dest/client/simulator.d.ts.map +1 -1
- package/dest/client/simulator.js +3 -2
- package/dest/client/unconstrained_execution.d.ts +2 -2
- package/dest/client/unconstrained_execution.d.ts.map +1 -1
- package/dest/client/unconstrained_execution.js +1 -1
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +3 -1
- package/dest/public/abstract_phase_manager.d.ts +2 -0
- package/dest/public/abstract_phase_manager.d.ts.map +1 -1
- package/dest/public/abstract_phase_manager.js +13 -6
- package/dest/public/execution.d.ts +9 -0
- package/dest/public/execution.d.ts.map +1 -1
- package/dest/public/execution.js +1 -1
- package/dest/public/executor.d.ts +2 -2
- package/dest/public/executor.d.ts.map +1 -1
- package/dest/public/executor.js +34 -14
- package/dest/public/public_execution_context.d.ts +10 -4
- package/dest/public/public_execution_context.d.ts.map +1 -1
- package/dest/public/public_execution_context.js +19 -6
- package/dest/public/tail_phase_manager.d.ts +0 -1
- package/dest/public/tail_phase_manager.d.ts.map +1 -1
- package/dest/public/tail_phase_manager.js +3 -26
- package/dest/public/transitional_adaptors.d.ts +4 -17
- package/dest/public/transitional_adaptors.d.ts.map +1 -1
- package/dest/public/transitional_adaptors.js +27 -119
- package/package.json +8 -8
- package/src/acvm/acvm.ts +2 -2
- package/src/acvm/oracle/oracle.ts +39 -9
- package/src/acvm/oracle/typed_oracle.ts +7 -2
- package/src/avm/avm_gas.ts +1 -0
- package/src/avm/avm_memory_types.ts +1 -1
- package/src/avm/avm_simulator.ts +2 -0
- package/src/avm/journal/journal.ts +133 -9
- package/src/avm/journal/nullifiers.ts +19 -8
- package/src/avm/journal/public_storage.ts +23 -2
- package/src/avm/journal/trace.ts +3 -4
- package/src/avm/journal/trace_types.ts +1 -0
- package/src/avm/opcodes/bitwise.ts +18 -7
- package/src/avm/opcodes/environment_getters.ts +9 -0
- package/src/avm/opcodes/external_calls.ts +21 -16
- package/src/avm/serialization/bytecode_serialization.ts +2 -0
- package/src/avm/serialization/instruction_serialization.ts +1 -0
- package/src/client/client_execution_context.ts +55 -31
- package/src/client/db_oracle.ts +3 -9
- package/src/client/execution_result.ts +55 -24
- package/src/client/logs_cache.ts +65 -0
- package/src/client/private_execution.ts +4 -10
- package/src/client/simulator.ts +6 -4
- package/src/client/unconstrained_execution.ts +2 -2
- package/src/mocks/fixtures.ts +2 -0
- package/src/public/abstract_phase_manager.ts +13 -5
- package/src/public/execution.ts +9 -0
- package/src/public/executor.ts +47 -10
- package/src/public/public_execution_context.ts +18 -4
- package/src/public/tail_phase_manager.ts +2 -34
- package/src/public/transitional_adaptors.ts +39 -178
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AztecAddress } from '@aztec/circuits.js';
|
|
1
2
|
import { siloNullifier } from '@aztec/circuits.js/hash';
|
|
2
3
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
4
|
|
|
@@ -10,7 +11,7 @@ import type { CommitmentsDB } from '../../index.js';
|
|
|
10
11
|
*/
|
|
11
12
|
export class Nullifiers {
|
|
12
13
|
/** Cached nullifiers. */
|
|
13
|
-
|
|
14
|
+
public cache: NullifierCache;
|
|
14
15
|
/** Parent's nullifier cache. Checked on cache-miss. */
|
|
15
16
|
private readonly parentCache: NullifierCache | undefined;
|
|
16
17
|
/** Reference to node storage. Checked on parent cache-miss. */
|
|
@@ -95,6 +96,7 @@ export class NullifierCache {
|
|
|
95
96
|
* each entry being a nullifier.
|
|
96
97
|
*/
|
|
97
98
|
private cachePerContract: Map<bigint, Set<bigint>> = new Map();
|
|
99
|
+
private siloedNullifiers: Set<bigint> = new Set();
|
|
98
100
|
|
|
99
101
|
/**
|
|
100
102
|
* Check whether a nullifier exists in the cache.
|
|
@@ -104,8 +106,10 @@ export class NullifierCache {
|
|
|
104
106
|
* @returns whether the nullifier is found in the cache
|
|
105
107
|
*/
|
|
106
108
|
public exists(storageAddress: Fr, nullifier: Fr): boolean {
|
|
107
|
-
const exists =
|
|
108
|
-
|
|
109
|
+
const exists =
|
|
110
|
+
this.cachePerContract.get(storageAddress.toBigInt())?.has(nullifier.toBigInt()) ||
|
|
111
|
+
this.siloedNullifiers.has(siloNullifier(AztecAddress.fromField(storageAddress), nullifier).toBigInt());
|
|
112
|
+
return !!exists;
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
/**
|
|
@@ -115,20 +119,25 @@ export class NullifierCache {
|
|
|
115
119
|
* @param nullifier - the nullifier to stage
|
|
116
120
|
*/
|
|
117
121
|
public append(storageAddress: Fr, nullifier: Fr) {
|
|
122
|
+
if (this.exists(storageAddress, nullifier)) {
|
|
123
|
+
throw new NullifierCollisionError(
|
|
124
|
+
`Nullifier ${nullifier} at contract ${storageAddress} already exists in cache.`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
118
128
|
let nullifiersForContract = this.cachePerContract.get(storageAddress.toBigInt());
|
|
119
129
|
// If this contract's nullifier set has no cached nullifiers, create a new Set to store them
|
|
120
130
|
if (!nullifiersForContract) {
|
|
121
131
|
nullifiersForContract = new Set();
|
|
122
132
|
this.cachePerContract.set(storageAddress.toBigInt(), nullifiersForContract);
|
|
123
133
|
}
|
|
124
|
-
if (nullifiersForContract.has(nullifier.toBigInt())) {
|
|
125
|
-
throw new NullifierCollisionError(
|
|
126
|
-
`Nullifier ${nullifier} at contract ${storageAddress} already exists in cache.`,
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
134
|
nullifiersForContract.add(nullifier.toBigInt());
|
|
130
135
|
}
|
|
131
136
|
|
|
137
|
+
public appendSiloed(siloedNullifier: Fr) {
|
|
138
|
+
this.siloedNullifiers.add(siloedNullifier.toBigInt());
|
|
139
|
+
}
|
|
140
|
+
|
|
132
141
|
/**
|
|
133
142
|
* Merge another cache's nullifiers into this instance's.
|
|
134
143
|
*
|
|
@@ -139,6 +148,8 @@ export class NullifierCache {
|
|
|
139
148
|
* @param incomingNullifiers - the incoming cached nullifiers to merge into this instance's
|
|
140
149
|
*/
|
|
141
150
|
public acceptAndMerge(incomingNullifiers: NullifierCache) {
|
|
151
|
+
// Merge siloed nullifiers.
|
|
152
|
+
this.siloedNullifiers = new Set([...this.siloedNullifiers, ...incomingNullifiers.siloedNullifiers]);
|
|
142
153
|
// Iterate over all contracts with staged writes in the child.
|
|
143
154
|
for (const [incomingAddress, incomingCacheAtContract] of incomingNullifiers.cachePerContract) {
|
|
144
155
|
const thisCacheAtContract = this.cachePerContract.get(incomingAddress);
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import { AztecAddress } from '@aztec/circuits.js';
|
|
1
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
|
|
3
4
|
import type { PublicStateDB } from '../../index.js';
|
|
4
5
|
|
|
6
|
+
type PublicStorageReadResult = {
|
|
7
|
+
value: Fr;
|
|
8
|
+
exists: boolean;
|
|
9
|
+
cached: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
5
12
|
/**
|
|
6
13
|
* A class to manage public storage reads and writes during a contract call's AVM simulation.
|
|
7
14
|
* Maintains a storage write cache, and ensures that reads fall back to the correct source.
|
|
@@ -39,7 +46,8 @@ export class PublicStorage {
|
|
|
39
46
|
* @param slot - the slot in the contract's storage being read from
|
|
40
47
|
* @returns exists: whether the slot has EVER been written to before, value: the latest value written to slot, or 0 if never written to before
|
|
41
48
|
*/
|
|
42
|
-
public async read(storageAddress: Fr, slot: Fr): Promise<
|
|
49
|
+
public async read(storageAddress: Fr, slot: Fr): Promise<PublicStorageReadResult> {
|
|
50
|
+
let cached = false;
|
|
43
51
|
// First try check this storage cache
|
|
44
52
|
let value = this.cache.read(storageAddress, slot);
|
|
45
53
|
// Then try parent's storage cache (if it exists / written to earlier in this TX)
|
|
@@ -49,11 +57,13 @@ export class PublicStorage {
|
|
|
49
57
|
// Finally try the host's Aztec state (a trip to the database)
|
|
50
58
|
if (!value) {
|
|
51
59
|
value = await this.hostPublicStorage.storageRead(storageAddress, slot);
|
|
60
|
+
} else {
|
|
61
|
+
cached = true;
|
|
52
62
|
}
|
|
53
63
|
// if value is undefined, that means this slot has never been written to!
|
|
54
64
|
const exists = value !== undefined;
|
|
55
65
|
const valueOrZero = exists ? value : Fr.ZERO;
|
|
56
|
-
return Promise.resolve(
|
|
66
|
+
return Promise.resolve({ value: valueOrZero, exists, cached });
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
/**
|
|
@@ -75,6 +85,17 @@ export class PublicStorage {
|
|
|
75
85
|
public acceptAndMerge(incomingPublicStorage: PublicStorage) {
|
|
76
86
|
this.cache.acceptAndMerge(incomingPublicStorage.cache);
|
|
77
87
|
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Commits ALL staged writes to the host's state.
|
|
91
|
+
*/
|
|
92
|
+
public async commitToDB() {
|
|
93
|
+
for (const [storageAddress, cacheAtContract] of this.cache.cachePerContract) {
|
|
94
|
+
for (const [slot, value] of cacheAtContract) {
|
|
95
|
+
await this.hostPublicStorage.storageWrite(AztecAddress.fromBigInt(storageAddress), new Fr(slot), value);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
78
99
|
}
|
|
79
100
|
|
|
80
101
|
/**
|
package/src/avm/journal/trace.ts
CHANGED
|
@@ -29,13 +29,14 @@ export class WorldStateAccessTrace {
|
|
|
29
29
|
|
|
30
30
|
constructor(parentTrace?: WorldStateAccessTrace) {
|
|
31
31
|
this.accessCounter = parentTrace ? parentTrace.accessCounter : 0;
|
|
32
|
+
// TODO(4805): consider tracking the parent's trace vector lengths so we can enforce limits
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
public getAccessCounter() {
|
|
35
36
|
return this.accessCounter;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
public tracePublicStorageRead(storageAddress: Fr, slot: Fr, value: Fr, exists: boolean) {
|
|
39
|
+
public tracePublicStorageRead(storageAddress: Fr, slot: Fr, value: Fr, exists: boolean, cached: boolean) {
|
|
39
40
|
// TODO(4805): check if some threshold is reached for max storage reads
|
|
40
41
|
// (need access to parent length, or trace needs to be initialized with parent's contents)
|
|
41
42
|
const traced: TracedPublicStorageRead = {
|
|
@@ -44,6 +45,7 @@ export class WorldStateAccessTrace {
|
|
|
44
45
|
slot,
|
|
45
46
|
value,
|
|
46
47
|
exists,
|
|
48
|
+
cached,
|
|
47
49
|
counter: new Fr(this.accessCounter),
|
|
48
50
|
// endLifetime: Fr.ZERO,
|
|
49
51
|
};
|
|
@@ -151,9 +153,6 @@ export class WorldStateAccessTrace {
|
|
|
151
153
|
/**
|
|
152
154
|
* Merges another trace into this one
|
|
153
155
|
*
|
|
154
|
-
* - Public state journals (r/w logs), with the accessing being appended in chronological order
|
|
155
|
-
* - Utxo objects are concatenated
|
|
156
|
-
*
|
|
157
156
|
* @param incomingTrace - the incoming trace to merge into this instance
|
|
158
157
|
*/
|
|
159
158
|
public acceptAndMerge(incomingTrace: WorldStateAccessTrace) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AvmContext } from '../avm_context.js';
|
|
2
|
-
import { type IntegralValue } from '../avm_memory_types.js';
|
|
2
|
+
import { type IntegralValue, type TaggedMemoryInterface, TypeTag } from '../avm_memory_types.js';
|
|
3
3
|
import { Opcode } from '../serialization/instruction_serialization.js';
|
|
4
4
|
import { ThreeOperandInstruction, TwoOperandInstruction } from './instruction_impl.js';
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
|
|
|
9
9
|
const memory = context.machineState.memory.track(this.type);
|
|
10
10
|
context.machineState.consumeGas(this.gasCost(memoryOperations));
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
this.checkTags(memory, this.inTag, this.aOffset, this.bOffset);
|
|
13
13
|
|
|
14
14
|
const a = memory.getAs<IntegralValue>(this.aOffset);
|
|
15
15
|
const b = memory.getAs<IntegralValue>(this.bOffset);
|
|
@@ -22,13 +22,16 @@ abstract class ThreeOperandBitwiseInstruction extends ThreeOperandInstruction {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
protected abstract compute(a: IntegralValue, b: IntegralValue): IntegralValue;
|
|
25
|
+
protected checkTags(memory: TaggedMemoryInterface, inTag: number, aOffset: number, bOffset: number) {
|
|
26
|
+
memory.checkTags(inTag, aOffset, bOffset);
|
|
27
|
+
}
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
export class And extends ThreeOperandBitwiseInstruction {
|
|
28
31
|
static readonly type: string = 'AND';
|
|
29
32
|
static readonly opcode = Opcode.AND;
|
|
30
33
|
|
|
31
|
-
protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
34
|
+
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
32
35
|
return a.and(b);
|
|
33
36
|
}
|
|
34
37
|
}
|
|
@@ -37,7 +40,7 @@ export class Or extends ThreeOperandBitwiseInstruction {
|
|
|
37
40
|
static readonly type: string = 'OR';
|
|
38
41
|
static readonly opcode = Opcode.OR;
|
|
39
42
|
|
|
40
|
-
protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
43
|
+
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
41
44
|
return a.or(b);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -46,7 +49,7 @@ export class Xor extends ThreeOperandBitwiseInstruction {
|
|
|
46
49
|
static readonly type: string = 'XOR';
|
|
47
50
|
static readonly opcode = Opcode.XOR;
|
|
48
51
|
|
|
49
|
-
protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
52
|
+
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
50
53
|
return a.xor(b);
|
|
51
54
|
}
|
|
52
55
|
}
|
|
@@ -55,18 +58,26 @@ export class Shl extends ThreeOperandBitwiseInstruction {
|
|
|
55
58
|
static readonly type: string = 'SHL';
|
|
56
59
|
static readonly opcode = Opcode.SHL;
|
|
57
60
|
|
|
58
|
-
protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
61
|
+
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
59
62
|
return a.shl(b);
|
|
60
63
|
}
|
|
64
|
+
protected override checkTags(memory: TaggedMemoryInterface, inTag: number, aOffset: number, bOffset: number) {
|
|
65
|
+
memory.checkTag(inTag, aOffset);
|
|
66
|
+
memory.checkTag(TypeTag.UINT8, bOffset);
|
|
67
|
+
}
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
export class Shr extends ThreeOperandBitwiseInstruction {
|
|
64
71
|
static readonly type: string = 'SHR';
|
|
65
72
|
static readonly opcode = Opcode.SHR;
|
|
66
73
|
|
|
67
|
-
protected compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
74
|
+
protected override compute(a: IntegralValue, b: IntegralValue): IntegralValue {
|
|
68
75
|
return a.shr(b);
|
|
69
76
|
}
|
|
77
|
+
protected override checkTags(memory: TaggedMemoryInterface, inTag: number, aOffset: number, bOffset: number) {
|
|
78
|
+
memory.checkTag(inTag, aOffset);
|
|
79
|
+
memory.checkTag(TypeTag.UINT8, bOffset);
|
|
80
|
+
}
|
|
70
81
|
}
|
|
71
82
|
|
|
72
83
|
export class Not extends TwoOperandInstruction {
|
|
@@ -59,6 +59,15 @@ export class FeePerDAGas extends EnvironmentGetterInstruction {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
export class TransactionFee extends EnvironmentGetterInstruction {
|
|
63
|
+
static type: string = 'TRANSACTIONFEE';
|
|
64
|
+
static readonly opcode: Opcode = Opcode.TRANSACTIONFEE;
|
|
65
|
+
|
|
66
|
+
protected getEnvironmentValue(env: AvmExecutionEnvironment) {
|
|
67
|
+
return env.transactionFee;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
62
71
|
export class ChainId extends EnvironmentGetterInstruction {
|
|
63
72
|
static type: string = 'CHAINID';
|
|
64
73
|
static readonly opcode: Opcode = Opcode.CHAINID;
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import { FunctionSelector } from '@aztec/circuits.js';
|
|
1
|
+
import { FunctionSelector, Gas } from '@aztec/circuits.js';
|
|
2
2
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
convertPublicExecutionResult,
|
|
7
|
-
createPublicExecutionContext,
|
|
8
|
-
updateAvmContextFromPublicExecutionResult,
|
|
9
|
-
} from '../../public/transitional_adaptors.js';
|
|
4
|
+
import { convertAvmResultsToPxResult, createPublicExecution } from '../../public/transitional_adaptors.js';
|
|
10
5
|
import type { AvmContext } from '../avm_context.js';
|
|
11
6
|
import { gasLeftToGas, sumGas } from '../avm_gas.js';
|
|
12
7
|
import { Field, Uint8 } from '../avm_memory_types.js';
|
|
13
8
|
import { type AvmContractCallResults } from '../avm_message_call_result.js';
|
|
9
|
+
import { AvmSimulator } from '../avm_simulator.js';
|
|
14
10
|
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
|
|
15
11
|
import { Addressing } from './addressing_mode.js';
|
|
16
12
|
import { Instruction } from './instruction.js';
|
|
@@ -69,7 +65,7 @@ abstract class ExternalCall extends Instruction {
|
|
|
69
65
|
const totalGas = sumGas(this.gasCost(memoryOperations), allocatedGas);
|
|
70
66
|
context.machineState.consumeGas(totalGas);
|
|
71
67
|
|
|
72
|
-
// TRANSITIONAL: This should be removed once the
|
|
68
|
+
// TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit
|
|
73
69
|
const nestedContext = context.createNestedContractCallContext(
|
|
74
70
|
callAddress.toFr(),
|
|
75
71
|
calldata,
|
|
@@ -77,11 +73,21 @@ abstract class ExternalCall extends Instruction {
|
|
|
77
73
|
this.type,
|
|
78
74
|
FunctionSelector.fromField(functionSelector),
|
|
79
75
|
);
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
const
|
|
76
|
+
const startSideEffectCounter = nestedContext.persistableState.trace.accessCounter;
|
|
77
|
+
|
|
78
|
+
const oldStyleExecution = createPublicExecution(startSideEffectCounter, nestedContext.environment, calldata);
|
|
79
|
+
const nestedCallResults: AvmContractCallResults = await new AvmSimulator(nestedContext).execute();
|
|
80
|
+
const pxResults = convertAvmResultsToPxResult(
|
|
81
|
+
nestedCallResults,
|
|
82
|
+
startSideEffectCounter,
|
|
83
|
+
oldStyleExecution,
|
|
84
|
+
Gas.from(allocatedGas),
|
|
85
|
+
nestedContext,
|
|
86
|
+
);
|
|
87
|
+
// store the old PublicExecutionResult object to maintain a recursive data structure for the old kernel
|
|
88
|
+
context.persistableState.transitionalExecutionResult.nestedExecutions.push(pxResults);
|
|
89
|
+
// END TRANSITIONAL
|
|
90
|
+
|
|
85
91
|
// const nestedContext = context.createNestedContractCallContext(
|
|
86
92
|
// callAddress.toFr(),
|
|
87
93
|
// calldata,
|
|
@@ -90,7 +96,6 @@ abstract class ExternalCall extends Instruction {
|
|
|
90
96
|
// FunctionSelector.fromField(functionSelector),
|
|
91
97
|
// );
|
|
92
98
|
// const nestedCallResults: AvmContractCallResults = await new AvmSimulator(nestedContext).execute();
|
|
93
|
-
// const nestedPersistableState = nestedContext.persistableState;
|
|
94
99
|
|
|
95
100
|
const success = !nestedCallResults.reverted;
|
|
96
101
|
|
|
@@ -112,9 +117,9 @@ abstract class ExternalCall extends Instruction {
|
|
|
112
117
|
|
|
113
118
|
// TODO: Should we merge the changes from a nested call in the case of a STATIC call?
|
|
114
119
|
if (success) {
|
|
115
|
-
context.persistableState.acceptNestedCallState(
|
|
120
|
+
context.persistableState.acceptNestedCallState(nestedContext.persistableState);
|
|
116
121
|
} else {
|
|
117
|
-
context.persistableState.rejectNestedCallState(
|
|
122
|
+
context.persistableState.rejectNestedCallState(nestedContext.persistableState);
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
memory.assert(memoryOperations);
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
StorageAddress,
|
|
47
47
|
Sub,
|
|
48
48
|
Timestamp,
|
|
49
|
+
TransactionFee,
|
|
49
50
|
Version,
|
|
50
51
|
Xor,
|
|
51
52
|
} from '../opcodes/index.js';
|
|
@@ -82,6 +83,7 @@ const INSTRUCTION_SET = () =>
|
|
|
82
83
|
[Sender.opcode, Sender],
|
|
83
84
|
[FeePerL2Gas.opcode, FeePerL2Gas],
|
|
84
85
|
[FeePerDAGas.opcode, FeePerDAGas],
|
|
86
|
+
[TransactionFee.opcode, TransactionFee],
|
|
85
87
|
//[Contractcalldepth.opcode, Contractcalldepth],
|
|
86
88
|
// Execution Environment - Globals
|
|
87
89
|
[ChainId.opcode, ChainId],
|
|
@@ -15,10 +15,8 @@ import {
|
|
|
15
15
|
FunctionData,
|
|
16
16
|
FunctionSelector,
|
|
17
17
|
type Header,
|
|
18
|
-
NoteHashReadRequestMembershipWitness,
|
|
19
18
|
PrivateContextInputs,
|
|
20
19
|
PublicCallRequest,
|
|
21
|
-
type SideEffect,
|
|
22
20
|
type TxContext,
|
|
23
21
|
} from '@aztec/circuits.js';
|
|
24
22
|
import { Aes128 } from '@aztec/circuits.js/barretenberg';
|
|
@@ -32,7 +30,8 @@ import { type NoteData, toACVMWitness } from '../acvm/index.js';
|
|
|
32
30
|
import { type PackedValuesCache } from '../common/packed_values_cache.js';
|
|
33
31
|
import { type DBOracle } from './db_oracle.js';
|
|
34
32
|
import { type ExecutionNoteCache } from './execution_note_cache.js';
|
|
35
|
-
import { type ExecutionResult, type NoteAndSlot
|
|
33
|
+
import { CountedLog, type ExecutionResult, type NoteAndSlot } from './execution_result.js';
|
|
34
|
+
import { type LogsCache } from './logs_cache.js';
|
|
36
35
|
import { pickNotes } from './pick_notes.js';
|
|
37
36
|
import { executePrivateFunction } from './private_execution.js';
|
|
38
37
|
import { ViewDataOracle } from './view_data_oracle.js';
|
|
@@ -58,10 +57,10 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
58
57
|
* because these notes are meant to be maintained on a per-call basis
|
|
59
58
|
* They should act as references for the read requests output by an app circuit via public inputs.
|
|
60
59
|
*/
|
|
61
|
-
private
|
|
62
|
-
private nullifiedNoteHashCounters:
|
|
63
|
-
private encryptedLogs: EncryptedL2Log[] = [];
|
|
64
|
-
private unencryptedLogs: UnencryptedL2Log[] = [];
|
|
60
|
+
private noteHashLeafIndexMap: Map<bigint, bigint> = new Map();
|
|
61
|
+
private nullifiedNoteHashCounters: Map<number, number> = new Map();
|
|
62
|
+
private encryptedLogs: CountedLog<EncryptedL2Log>[] = [];
|
|
63
|
+
private unencryptedLogs: CountedLog<UnencryptedL2Log>[] = [];
|
|
65
64
|
private nestedExecutions: ExecutionResult[] = [];
|
|
66
65
|
private enqueuedPublicFunctionCalls: PublicCallRequest[] = [];
|
|
67
66
|
|
|
@@ -76,6 +75,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
76
75
|
authWitnesses: AuthWitness[],
|
|
77
76
|
private readonly packedValuesCache: PackedValuesCache,
|
|
78
77
|
private readonly noteCache: ExecutionNoteCache,
|
|
78
|
+
private readonly logsCache: LogsCache,
|
|
79
79
|
db: DBOracle,
|
|
80
80
|
private node: AztecNode,
|
|
81
81
|
protected sideEffectCounter: number = 0,
|
|
@@ -112,23 +112,11 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* or to flag non-transient reads with their leafIndex.
|
|
118
|
-
* The KernelProver will use this to fully populate witnesses and provide hints to
|
|
119
|
-
* the kernel regarding which commitments each transient read request corresponds to.
|
|
120
|
-
* @param noteHashReadRequests - SideEffect containing Note hashed of the notes being read and counter.
|
|
121
|
-
* @returns An array of partially filled in read request membership witnesses.
|
|
115
|
+
* The KernelProver will use this to fully populate witnesses and provide hints to the kernel circuit
|
|
116
|
+
* regarding which note hash each settled read request corresponds to.
|
|
122
117
|
*/
|
|
123
|
-
public
|
|
124
|
-
return
|
|
125
|
-
.filter(r => !r.isEmpty())
|
|
126
|
-
.map(r => {
|
|
127
|
-
const index = this.gotNotes.get(r.value.toBigInt());
|
|
128
|
-
return index !== undefined
|
|
129
|
-
? NoteHashReadRequestMembershipWitness.empty(index)
|
|
130
|
-
: NoteHashReadRequestMembershipWitness.emptyTransient();
|
|
131
|
-
});
|
|
118
|
+
public getNoteHashLeafIndexMap() {
|
|
119
|
+
return this.noteHashLeafIndexMap;
|
|
132
120
|
}
|
|
133
121
|
|
|
134
122
|
/**
|
|
@@ -147,14 +135,28 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
147
135
|
* Return the encrypted logs emitted during this execution.
|
|
148
136
|
*/
|
|
149
137
|
public getEncryptedLogs() {
|
|
150
|
-
return
|
|
138
|
+
return this.encryptedLogs;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Return the encrypted logs emitted during this execution and nested executions.
|
|
143
|
+
*/
|
|
144
|
+
public getAllEncryptedLogs() {
|
|
145
|
+
return new EncryptedFunctionL2Logs(this.logsCache.getEncryptedLogs());
|
|
151
146
|
}
|
|
152
147
|
|
|
153
148
|
/**
|
|
154
149
|
* Return the encrypted logs emitted during this execution.
|
|
155
150
|
*/
|
|
156
151
|
public getUnencryptedLogs() {
|
|
157
|
-
return
|
|
152
|
+
return this.unencryptedLogs;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Return the unencrypted logs emitted during this execution and nested executions.
|
|
157
|
+
*/
|
|
158
|
+
public getAllUnencryptedLogs() {
|
|
159
|
+
return new UnencryptedFunctionL2Logs(this.logsCache.getUnencryptedLogs());
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
/**
|
|
@@ -265,7 +267,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
265
267
|
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)
|
|
266
268
|
// Should always be uniqueSiloedNoteHash when publicly created notes include nonces.
|
|
267
269
|
const noteHashForReadRequest = n.nonce.isZero() ? siloedNoteHash : uniqueSiloedNoteHash;
|
|
268
|
-
this.
|
|
270
|
+
this.noteHashLeafIndexMap.set(noteHashForReadRequest.toBigInt(), n.index);
|
|
269
271
|
}
|
|
270
272
|
});
|
|
271
273
|
|
|
@@ -321,7 +323,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
321
323
|
innerNoteHash,
|
|
322
324
|
);
|
|
323
325
|
if (nullifiedNoteHashCounter !== undefined) {
|
|
324
|
-
this.nullifiedNoteHashCounters.
|
|
326
|
+
this.nullifiedNoteHashCounters.set(nullifiedNoteHashCounter, counter);
|
|
325
327
|
}
|
|
326
328
|
return Promise.resolve();
|
|
327
329
|
}
|
|
@@ -340,24 +342,45 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
340
342
|
noteTypeId: Fr,
|
|
341
343
|
publicKey: Point,
|
|
342
344
|
log: Fr[],
|
|
345
|
+
counter: number,
|
|
343
346
|
) {
|
|
344
347
|
const note = new Note(log);
|
|
345
348
|
const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
|
|
346
349
|
const taggedNote = new TaggedNote(l1NotePayload);
|
|
347
350
|
const encryptedNote = taggedNote.toEncryptedBuffer(publicKey);
|
|
348
351
|
const encryptedLog = new EncryptedL2Log(encryptedNote);
|
|
349
|
-
this.encryptedLogs.push(encryptedLog);
|
|
350
|
-
|
|
352
|
+
this.encryptedLogs.push(new CountedLog(encryptedLog, counter));
|
|
353
|
+
this.logsCache.addEncryptedLog(encryptedLog);
|
|
354
|
+
return encryptedNote;
|
|
351
355
|
}
|
|
352
356
|
|
|
353
357
|
/**
|
|
354
358
|
* Emit an unencrypted log.
|
|
355
359
|
* @param log - The unencrypted log to be emitted.
|
|
356
360
|
*/
|
|
357
|
-
public override emitUnencryptedLog(log: UnencryptedL2Log) {
|
|
358
|
-
this.unencryptedLogs.push(log);
|
|
361
|
+
public override emitUnencryptedLog(log: UnencryptedL2Log, counter: number) {
|
|
362
|
+
this.unencryptedLogs.push(new CountedLog(log, counter));
|
|
363
|
+
this.logsCache.addUnencryptedLog(log);
|
|
359
364
|
const text = log.toHumanReadable();
|
|
360
365
|
this.log.verbose(`Emitted unencrypted log: "${text.length > 100 ? text.slice(0, 100) + '...' : text}"`);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Emit a contract class unencrypted log.
|
|
370
|
+
* This fn exists separately from emitUnencryptedLog because sha hashing the preimage
|
|
371
|
+
* is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it.
|
|
372
|
+
* See private_context.nr
|
|
373
|
+
* @param log - The unencrypted log to be emitted.
|
|
374
|
+
*/
|
|
375
|
+
public override emitContractClassUnencryptedLog(log: UnencryptedL2Log, counter: number) {
|
|
376
|
+
this.unencryptedLogs.push(new CountedLog(log, counter));
|
|
377
|
+
this.logsCache.addUnencryptedLog(log);
|
|
378
|
+
const text = log.toHumanReadable();
|
|
379
|
+
this.log.verbose(
|
|
380
|
+
`Emitted unencrypted log from ContractClassRegisterer: "${
|
|
381
|
+
text.length > 100 ? text.slice(0, 100) + '...' : text
|
|
382
|
+
}"`,
|
|
383
|
+
);
|
|
361
384
|
return Fr.fromBuffer(log.hash());
|
|
362
385
|
}
|
|
363
386
|
|
|
@@ -419,6 +442,7 @@ export class ClientExecutionContext extends ViewDataOracle {
|
|
|
419
442
|
this.authWitnesses,
|
|
420
443
|
this.packedValuesCache,
|
|
421
444
|
this.noteCache,
|
|
445
|
+
this.logsCache,
|
|
422
446
|
this.db,
|
|
423
447
|
this.node,
|
|
424
448
|
sideEffectCounter,
|
package/src/client/db_oracle.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
type PublicDataWitness,
|
|
7
7
|
} from '@aztec/circuit-types';
|
|
8
8
|
import { type CompleteAddress, type Header } from '@aztec/circuits.js';
|
|
9
|
-
import { type
|
|
9
|
+
import { type FunctionArtifact, type FunctionSelector } from '@aztec/foundation/abi';
|
|
10
10
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
11
11
|
import { type Fr, type Point } from '@aztec/foundation/fields';
|
|
12
12
|
import { type ContractInstance } from '@aztec/types/contracts';
|
|
@@ -102,10 +102,7 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
102
102
|
* @param selector - The corresponding function selector.
|
|
103
103
|
* @returns A Promise that resolves to a FunctionArtifact object.
|
|
104
104
|
*/
|
|
105
|
-
getFunctionArtifact(
|
|
106
|
-
contractAddress: AztecAddress,
|
|
107
|
-
selector: FunctionSelector,
|
|
108
|
-
): Promise<FunctionArtifactWithDebugMetadata>;
|
|
105
|
+
getFunctionArtifact(contractAddress: AztecAddress, selector: FunctionSelector): Promise<FunctionArtifact>;
|
|
109
106
|
|
|
110
107
|
/**
|
|
111
108
|
* Retrieves the artifact of a specified function within a given contract.
|
|
@@ -115,10 +112,7 @@ export interface DBOracle extends CommitmentsDB {
|
|
|
115
112
|
* @param functionName - The name of the function.
|
|
116
113
|
* @returns The corresponding function's artifact as an object.
|
|
117
114
|
*/
|
|
118
|
-
getFunctionArtifactByName(
|
|
119
|
-
contractAddress: AztecAddress,
|
|
120
|
-
functionName: string,
|
|
121
|
-
): Promise<FunctionArtifactWithDebugMetadata | undefined>;
|
|
115
|
+
getFunctionArtifactByName(contractAddress: AztecAddress, functionName: string): Promise<FunctionArtifact | undefined>;
|
|
122
116
|
|
|
123
117
|
/**
|
|
124
118
|
* Gets the index of a nullifier in the nullifier tree.
|