@aztec/txe 0.76.4 → 0.77.0-testnet-ignition.21

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.
Files changed (35) hide show
  1. package/dest/bin/index.js +3 -5
  2. package/dest/index.d.ts +1 -1
  3. package/dest/index.d.ts.map +1 -1
  4. package/dest/index.js +106 -106
  5. package/dest/node/txe_node.d.ts +19 -6
  6. package/dest/node/txe_node.d.ts.map +1 -1
  7. package/dest/node/txe_node.js +303 -334
  8. package/dest/oracle/txe_oracle.d.ts +25 -16
  9. package/dest/oracle/txe_oracle.d.ts.map +1 -1
  10. package/dest/oracle/txe_oracle.js +249 -143
  11. package/dest/txe_service/txe_service.d.ts +3 -3
  12. package/dest/txe_service/txe_service.d.ts.map +1 -1
  13. package/dest/txe_service/txe_service.js +205 -105
  14. package/dest/util/encoding.d.ts +39 -25
  15. package/dest/util/encoding.d.ts.map +1 -1
  16. package/dest/util/encoding.js +45 -11
  17. package/dest/util/expected_failure_error.js +1 -2
  18. package/dest/util/txe_database.d.ts +3 -2
  19. package/dest/util/txe_database.d.ts.map +1 -1
  20. package/dest/util/txe_database.js +6 -10
  21. package/dest/util/txe_public_contract_data_source.d.ts +5 -3
  22. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  23. package/dest/util/txe_public_contract_data_source.js +25 -13
  24. package/dest/util/txe_world_state_db.d.ts +6 -8
  25. package/dest/util/txe_world_state_db.d.ts.map +1 -1
  26. package/dest/util/txe_world_state_db.js +10 -23
  27. package/package.json +14 -15
  28. package/src/index.ts +2 -2
  29. package/src/node/txe_node.ts +64 -42
  30. package/src/oracle/txe_oracle.ts +101 -86
  31. package/src/txe_service/txe_service.ts +25 -28
  32. package/src/util/encoding.ts +32 -5
  33. package/src/util/txe_database.ts +3 -2
  34. package/src/util/txe_public_contract_data_source.ts +8 -9
  35. package/src/util/txe_world_state_db.ts +9 -26
@@ -1,51 +1,51 @@
1
- import { createLogger } from '@aztec/aztec.js';
2
- import {
3
- type AztecNode,
4
- type GetContractClassLogsResponse,
5
- type GetPublicLogsResponse,
6
- type InBlock,
7
- type L2Block,
8
- L2BlockHash,
9
- type L2BlockNumber,
10
- type L2Tips,
11
- type LogFilter,
12
- type MerkleTreeId,
13
- type MerkleTreeReadOperations,
14
- type MerkleTreeWriteOperations,
15
- type NullifierMembershipWitness,
16
- type ProverConfig,
17
- type PublicDataWitness,
18
- type PublicSimulationOutput,
19
- type SequencerConfig,
20
- type SiblingPath,
21
- type Tx,
22
- type TxEffect,
23
- TxHash,
24
- TxReceipt,
25
- TxScopedL2Log,
26
- type TxValidationResult,
27
- } from '@aztec/circuit-types';
28
1
  import {
29
2
  type ARCHIVE_HEIGHT,
30
- type AztecAddress,
31
- type BlockHeader,
32
- type ContractClassPublic,
33
- type ContractInstanceWithAddress,
34
- type GasFees,
35
3
  type L1_TO_L2_MSG_TREE_HEIGHT,
36
4
  type NOTE_HASH_TREE_HEIGHT,
37
5
  type NULLIFIER_TREE_HEIGHT,
38
- type NodeInfo,
39
6
  type PUBLIC_DATA_TREE_HEIGHT,
40
7
  PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
41
- type PrivateLog,
42
- type ProtocolContractAddresses,
43
- type PublicLog,
44
- } from '@aztec/circuits.js';
45
- import { type L1ContractAddresses } from '@aztec/ethereum';
8
+ } from '@aztec/constants';
9
+ import type { L1ContractAddresses } from '@aztec/ethereum';
46
10
  import { poseidon2Hash } from '@aztec/foundation/crypto';
47
11
  import { Fr } from '@aztec/foundation/fields';
48
- import { type NativeWorldStateService } from '@aztec/world-state';
12
+ import { createLogger } from '@aztec/foundation/log';
13
+ import type { SiblingPath } from '@aztec/foundation/trees';
14
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
15
+ import { type InBlock, L2Block, L2BlockHash, type L2BlockNumber, type L2Tips } from '@aztec/stdlib/block';
16
+ import type {
17
+ ContractClassPublic,
18
+ ContractInstanceWithAddress,
19
+ NodeInfo,
20
+ ProtocolContractAddresses,
21
+ } from '@aztec/stdlib/contract';
22
+ import type { GasFees } from '@aztec/stdlib/gas';
23
+ import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
24
+ import type { AztecNode, GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
25
+ import type {
26
+ MerkleTreeReadOperations,
27
+ MerkleTreeWriteOperations,
28
+ ProverConfig,
29
+ SequencerConfig,
30
+ WorldStateSyncStatus,
31
+ } from '@aztec/stdlib/interfaces/server';
32
+ import { type LogFilter, type PrivateLog, type PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs';
33
+ import {
34
+ MerkleTreeId,
35
+ type NullifierMembershipWitness,
36
+ type PublicDataTreeLeafPreimage,
37
+ PublicDataWitness,
38
+ } from '@aztec/stdlib/trees';
39
+ import {
40
+ BlockHeader,
41
+ type PublicSimulationOutput,
42
+ type Tx,
43
+ type TxEffect,
44
+ TxHash,
45
+ TxReceipt,
46
+ type TxValidationResult,
47
+ } from '@aztec/stdlib/tx';
48
+ import type { NativeWorldStateService } from '@aztec/world-state';
49
49
 
50
50
  export class TXENode implements AztecNode {
51
51
  #logsByTags = new Map<string, TxScopedL2Log[]>();
@@ -582,8 +582,23 @@ export class TXENode implements AztecNode {
582
582
  * @param blockNumber - The block number at which to get the data or 'latest'.
583
583
  * @returns Storage value at the given contract slot.
584
584
  */
585
- getPublicStorageAt(_contract: AztecAddress, _slot: Fr, _blockNumber: L2BlockNumber): Promise<Fr> {
586
- throw new Error('TXE Node method getPublicStorageAt not implemented');
585
+ async getPublicStorageAt(contract: AztecAddress, slot: Fr, blockNumber: L2BlockNumber): Promise<Fr> {
586
+ const db: MerkleTreeReadOperations =
587
+ blockNumber === (await this.getBlockNumber()) || blockNumber === 'latest' || blockNumber === undefined
588
+ ? this.baseFork
589
+ : this.nativeWorldStateService.getSnapshot(blockNumber);
590
+
591
+ const leafSlot = await computePublicDataTreeLeafSlot(contract, slot);
592
+
593
+ const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
594
+ if (!lowLeafResult || !lowLeafResult.alreadyPresent) {
595
+ return Fr.ZERO;
596
+ }
597
+ const preimage = (await db.getLeafPreimage(
598
+ MerkleTreeId.PUBLIC_DATA_TREE,
599
+ lowLeafResult.index,
600
+ )) as PublicDataTreeLeafPreimage;
601
+ return preimage.value;
587
602
  }
588
603
 
589
604
  /**
@@ -610,7 +625,7 @@ export class TXENode implements AztecNode {
610
625
  * @param tx - The transaction to validate for correctness.
611
626
  * @param isSimulation - True if the transaction is a simulated one without generated proofs. (Optional)
612
627
  */
613
- isValidTx(_tx: Tx, _isSimulation?: boolean): Promise<TxValidationResult> {
628
+ isValidTx(_tx: Tx): Promise<TxValidationResult> {
614
629
  throw new Error('TXE Node method isValidTx not implemented');
615
630
  }
616
631
 
@@ -700,4 +715,11 @@ export class TXENode implements AztecNode {
700
715
  getNodeInfo(): Promise<NodeInfo> {
701
716
  throw new Error('TXE Node method getNodeInfo not implemented');
702
717
  }
718
+
719
+ /**
720
+ * Returns the sync status of the node's world state
721
+ */
722
+ getWorldStateSyncStatus(): Promise<WorldStateSyncStatus> {
723
+ throw new Error('TXE Node method getWorldStateSyncStatus not implemented');
724
+ }
703
725
  }
@@ -1,82 +1,25 @@
1
+ import { Body, L2Block, Note } from '@aztec/aztec.js';
1
2
  import {
2
- AuthWitness,
3
- Body,
4
- L2Block,
5
- MerkleTreeId,
6
- type MerkleTreeReadOperations,
7
- type MerkleTreeWriteOperations,
8
- Note,
9
- type NoteStatus,
10
- NullifierMembershipWitness,
11
- PublicDataWitness,
12
- PublicExecutionRequest,
13
- SimulationError,
14
- TxEffect,
15
- TxHash,
16
- type UnencryptedL2Log,
17
- } from '@aztec/circuit-types';
18
- import { type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats';
19
- import {
20
- AppendOnlyTreeSnapshot,
21
- BlockHeader,
22
- CallContext,
23
- type ContractInstance,
24
- type ContractInstanceWithAddress,
25
- Gas,
26
- GasFees,
27
- GlobalVariables,
28
- IndexedTaggingSecret,
29
- type KeyValidationRequest,
30
3
  type L1_TO_L2_MSG_TREE_HEIGHT,
31
4
  MAX_NOTE_HASHES_PER_TX,
32
5
  MAX_NULLIFIERS_PER_TX,
33
6
  NULLIFIER_SUBTREE_HEIGHT,
34
7
  type NULLIFIER_TREE_HEIGHT,
35
8
  NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
36
- type NullifierLeafPreimage,
37
9
  PRIVATE_CONTEXT_INPUTS_LENGTH,
38
10
  type PUBLIC_DATA_TREE_HEIGHT,
39
11
  PUBLIC_DISPATCH_SELECTOR,
40
- PrivateContextInputs,
41
- type PrivateLog,
42
- PublicDataTreeLeaf,
43
- type PublicDataTreeLeafPreimage,
44
- PublicDataWrite,
45
- type PublicLog,
46
- computeTaggingSecretPoint,
47
- deriveKeys,
48
- } from '@aztec/circuits.js';
49
- import { Schnorr } from '@aztec/circuits.js/barretenberg';
50
- import {
51
- computeNoteHashNonce,
52
- computePublicDataTreeLeafSlot,
53
- computeUniqueNoteHash,
54
- siloNoteHash,
55
- siloNullifier,
56
- } from '@aztec/circuits.js/hash';
57
- import {
58
- makeAppendOnlyTreeSnapshot,
59
- makeContentCommitment,
60
- makeGlobalVariables,
61
- makeHeader,
62
- } from '@aztec/circuits.js/testing';
63
- import {
64
- type ContractArtifact,
65
- type FunctionAbi,
66
- FunctionSelector,
67
- type NoteSelector,
68
- countArgumentsSize,
69
- } from '@aztec/foundation/abi';
70
- import { AztecAddress } from '@aztec/foundation/aztec-address';
12
+ } from '@aztec/constants';
71
13
  import { padArrayEnd } from '@aztec/foundation/collection';
72
- import { poseidon2Hash } from '@aztec/foundation/crypto';
14
+ import { Schnorr, poseidon2Hash } from '@aztec/foundation/crypto';
73
15
  import { Fr } from '@aztec/foundation/fields';
74
16
  import { type LogFn, type Logger, applyStringFormatting, createDebugOnlyLogger } from '@aztec/foundation/log';
75
17
  import { Timer } from '@aztec/foundation/timer';
76
- import { type KeyStore } from '@aztec/key-store';
18
+ import type { KeyStore } from '@aztec/key-store';
77
19
  import { ContractDataOracle, SimulatorOracle, enrichPublicSimulationError } from '@aztec/pxe';
78
20
  import {
79
21
  ExecutionNoteCache,
22
+ type HashedValuesCache,
80
23
  type MessageLoadOracleInputs,
81
24
  type NoteData,
82
25
  Oracle,
@@ -92,16 +35,58 @@ import {
92
35
  import { createTxForPublicCalls } from '@aztec/simulator/public/fixtures';
93
36
  import {
94
37
  ExecutionError,
95
- type HashedValuesCache,
96
38
  type PublicTxResult,
97
39
  PublicTxSimulator,
98
40
  createSimulationError,
99
41
  resolveAssertionMessageFromError,
100
42
  } from '@aztec/simulator/server';
101
- import { type NativeWorldStateService } from '@aztec/world-state';
43
+ import {
44
+ type ContractArtifact,
45
+ type FunctionAbi,
46
+ FunctionSelector,
47
+ type NoteSelector,
48
+ countArgumentsSize,
49
+ } from '@aztec/stdlib/abi';
50
+ import { AuthWitness } from '@aztec/stdlib/auth-witness';
51
+ import { PublicDataWrite } from '@aztec/stdlib/avm';
52
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
53
+ import type { ContractInstance, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
54
+ import { SimulationError } from '@aztec/stdlib/errors';
55
+ import { Gas, GasFees } from '@aztec/stdlib/gas';
56
+ import {
57
+ computeNoteHashNonce,
58
+ computePublicDataTreeLeafSlot,
59
+ computeUniqueNoteHash,
60
+ siloNoteHash,
61
+ siloNullifier,
62
+ } from '@aztec/stdlib/hash';
63
+ import type { MerkleTreeReadOperations, MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
64
+ import { type KeyValidationRequest, PrivateContextInputs } from '@aztec/stdlib/kernel';
65
+ import { computeTaggingSecretPoint, deriveKeys } from '@aztec/stdlib/keys';
66
+ import { ContractClassLog, LogWithTxData } from '@aztec/stdlib/logs';
67
+ import { IndexedTaggingSecret, type PrivateLog, type PublicLog } from '@aztec/stdlib/logs';
68
+ import type { NoteStatus } from '@aztec/stdlib/note';
69
+ import type { CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
70
+ import {
71
+ makeAppendOnlyTreeSnapshot,
72
+ makeContentCommitment,
73
+ makeGlobalVariables,
74
+ makeHeader,
75
+ } from '@aztec/stdlib/testing';
76
+ import {
77
+ AppendOnlyTreeSnapshot,
78
+ MerkleTreeId,
79
+ type NullifierLeafPreimage,
80
+ NullifierMembershipWitness,
81
+ PublicDataTreeLeaf,
82
+ type PublicDataTreeLeafPreimage,
83
+ PublicDataWitness,
84
+ } from '@aztec/stdlib/trees';
85
+ import { BlockHeader, CallContext, GlobalVariables, PublicExecutionRequest, TxEffect, TxHash } from '@aztec/stdlib/tx';
86
+ import { ForkCheckpoint, type NativeWorldStateService } from '@aztec/world-state/native';
102
87
 
103
88
  import { TXENode } from '../node/txe_node.js';
104
- import { type TXEDatabase } from '../util/txe_database.js';
89
+ import type { TXEDatabase } from '../util/txe_database.js';
105
90
  import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
106
91
  import { TXEWorldStateDB } from '../util/txe_world_state_db.js';
107
92
 
@@ -164,6 +149,7 @@ export class TXE implements TypedOracle {
164
149
  this.viewDataOracle = new ViewDataOracle(
165
150
  this.contractAddress,
166
151
  [] /* authWitnesses */,
152
+ [] /* capsules */,
167
153
  this.simulatorOracle, // note: SimulatorOracle implements DBOracle
168
154
  this.node,
169
155
  /* log, */
@@ -719,6 +705,8 @@ export class TXE implements TypedOracle {
719
705
  for (const txEffect of paddedTxEffects) {
720
706
  // We do not need to add public data writes because we apply them as we go. We use the sequentialInsert because
721
707
  // the batchInsert was not working when updating a previously updated slot.
708
+ // FIXME: public data writes, note hashes, nullifiers, messages should all be handled in the same way.
709
+ // They are all relevant to subsequent enqueued calls and txs.
722
710
 
723
711
  const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
724
712
 
@@ -752,6 +740,11 @@ export class TXE implements TypedOracle {
752
740
 
753
741
  await fork.updateArchive(l2Block.header);
754
742
 
743
+ // We've built a block with all of our state changes in a "fork".
744
+ // Now emulate a "sync" to this block, by letting cpp reapply the block's
745
+ // changes to the underlying unforked world state and comparing the results
746
+ // against the block's state reference (which is this state reference here in the fork).
747
+ // This essentially commits the state updates to the unforked state and sanity checks the roots.
755
748
  await this.nativeWorldStateService.handleL2BlockAndMessages(l2Block, l1ToL2Messages);
756
749
 
757
750
  this.publicDataWrites = [];
@@ -767,7 +760,7 @@ export class TXE implements TypedOracle {
767
760
  return new Fr(this.blockNumber + 6969);
768
761
  }
769
762
 
770
- emitContractClassLog(_log: UnencryptedL2Log, _counter: number): Fr {
763
+ emitContractClassLog(_log: ContractClassLog, _counter: number): Fr {
771
764
  throw new Error('Method not implemented.');
772
765
  }
773
766
 
@@ -873,7 +866,7 @@ export class TXE implements TypedOracle {
873
866
  if (!instance) {
874
867
  return undefined;
875
868
  }
876
- const artifact = await this.contractDataOracle.getContractArtifact(instance!.contractClassId);
869
+ const artifact = await this.contractDataOracle.getContractArtifact(instance!.currentContractClassId);
877
870
  if (!artifact) {
878
871
  return undefined;
879
872
  }
@@ -902,28 +895,45 @@ export class TXE implements TypedOracle {
902
895
  globalVariables.blockNumber = new Fr(this.blockNumber);
903
896
  globalVariables.gasFees = new GasFees(1, 1);
904
897
 
905
- const simulator = new PublicTxSimulator(
906
- db,
907
- new TXEWorldStateDB(db, new TXEPublicContractDataSource(this), this),
908
- globalVariables,
909
- );
898
+ let result: PublicTxResult;
899
+ // Checkpoint here so that we can revert merkle ops after simulation.
900
+ // See note at revert below.
901
+ const checkpoint = await ForkCheckpoint.new(db);
902
+ try {
903
+ const simulator = new PublicTxSimulator(
904
+ db,
905
+ new TXEWorldStateDB(db, new TXEPublicContractDataSource(this), this),
906
+ globalVariables,
907
+ /*doMerkleOperations=*/ true,
908
+ );
910
909
 
911
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
912
- const firstNullifier = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
910
+ const { usedTxRequestHashForNonces } = this.noteCache.finish();
911
+ const firstNullifier = usedTxRequestHashForNonces
912
+ ? this.getTxRequestHash()
913
+ : this.noteCache.getAllNullifiers()[0];
913
914
 
914
- // When setting up a teardown call, we tell it that
915
- // private execution used Gas(1, 1) so it can compute a tx fee.
916
- const gasUsedByPrivate = isTeardown ? new Gas(1, 1) : Gas.empty();
917
- const tx = await createTxForPublicCalls(
918
- firstNullifier,
919
- /*setupExecutionRequests=*/ [],
920
- /*appExecutionRequests=*/ isTeardown ? [] : [executionRequest],
921
- /*teardownExecutionRequests=*/ isTeardown ? executionRequest : undefined,
922
- /*feePayer=*/ AztecAddress.zero(),
923
- gasUsedByPrivate,
924
- );
915
+ // When setting up a teardown call, we tell it that
916
+ // private execution used Gas(1, 1) so it can compute a tx fee.
917
+ const gasUsedByPrivate = isTeardown ? new Gas(1, 1) : Gas.empty();
918
+ const tx = await createTxForPublicCalls(
919
+ firstNullifier,
920
+ /*setupExecutionRequests=*/ [],
921
+ /*appExecutionRequests=*/ isTeardown ? [] : [executionRequest],
922
+ /*teardownExecutionRequests=*/ isTeardown ? executionRequest : undefined,
923
+ /*feePayer=*/ AztecAddress.zero(),
924
+ gasUsedByPrivate,
925
+ );
926
+
927
+ result = await simulator.simulate(tx);
928
+ } finally {
929
+ // NOTE: Don't accept any merkle updates from the AVM since this was just 1 enqueued call
930
+ // and the TXE will re-apply all txEffects after entire execution (all enqueued calls)
931
+ // complete.
932
+ await checkpoint.revert();
933
+ // If an error is thrown during the above simulation, this revert is the last
934
+ // thing executed and we skip the postprocessing below.
935
+ }
925
936
 
926
- const result = await simulator.simulate(tx);
927
937
  const noteHashes = result.avmProvingRequest.inputs.publicInputs.accumulatedData.noteHashes.filter(
928
938
  s => !s.isEmpty(),
929
939
  );
@@ -931,6 +941,7 @@ export class TXE implements TypedOracle {
931
941
  const publicDataWrites = result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicDataWrites.filter(
932
942
  s => !s.isEmpty(),
933
943
  );
944
+ // For now, public data writes are the only merkle operations that are readable by later enqueued calls in the TXE.
934
945
  await this.addPublicDataWrites(publicDataWrites);
935
946
 
936
947
  this.addUniqueNoteHashesFromPublic(noteHashes);
@@ -1081,6 +1092,10 @@ export class TXE implements TypedOracle {
1081
1092
  throw new Error('deliverNote');
1082
1093
  }
1083
1094
 
1095
+ async getLogByTag(tag: Fr): Promise<LogWithTxData | null> {
1096
+ return await this.simulatorOracle.getLogByTag(tag);
1097
+ }
1098
+
1084
1099
  // AVM oracles
1085
1100
 
1086
1101
  async avmOpcodeCall(targetContractAddress: AztecAddress, args: Fr[], isStaticCall: boolean): Promise<PublicTxResult> {
@@ -1,23 +1,19 @@
1
- import { MerkleTreeId, SimulationError } from '@aztec/circuit-types';
2
- import {
3
- type ContractInstanceWithAddress,
4
- DEPLOYER_CONTRACT_ADDRESS,
5
- Fr,
6
- FunctionSelector,
7
- PublicDataWrite,
8
- computePartialAddress,
9
- } from '@aztec/circuits.js';
10
- import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec/circuits.js/hash';
11
- import { type ContractArtifact, NoteSelector } from '@aztec/foundation/abi';
12
- import { AztecAddress } from '@aztec/foundation/aztec-address';
13
- import { type Logger } from '@aztec/foundation/log';
1
+ import { type ContractInstanceWithAddress, Fr } from '@aztec/aztec.js';
2
+ import { DEPLOYER_CONTRACT_ADDRESS } from '@aztec/constants';
3
+ import type { Logger } from '@aztec/foundation/log';
14
4
  import { KeyStore } from '@aztec/key-store';
15
- import { openTmpStore } from '@aztec/kv-store/lmdb';
5
+ import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
16
6
  import { protocolContractNames } from '@aztec/protocol-contracts';
17
- import { getCanonicalProtocolContract } from '@aztec/protocol-contracts/bundle';
7
+ import { BundledProtocolContractsProvider } from '@aztec/protocol-contracts/providers/bundle';
18
8
  import { enrichPublicSimulationError } from '@aztec/pxe';
19
- import { type TypedOracle } from '@aztec/simulator/client';
20
- import { HashedValuesCache } from '@aztec/simulator/server';
9
+ import { HashedValuesCache, type TypedOracle } from '@aztec/simulator/client';
10
+ import { type ContractArtifact, FunctionSelector, NoteSelector } from '@aztec/stdlib/abi';
11
+ import { PublicDataWrite } from '@aztec/stdlib/avm';
12
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
13
+ import { computePartialAddress } from '@aztec/stdlib/contract';
14
+ import { SimulationError } from '@aztec/stdlib/errors';
15
+ import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec/stdlib/hash';
16
+ import { MerkleTreeId } from '@aztec/stdlib/trees';
21
17
  import { NativeWorldStateService } from '@aztec/world-state';
22
18
 
23
19
  import { TXE } from '../oracle/txe_oracle.js';
@@ -25,6 +21,8 @@ import {
25
21
  type ForeignCallArray,
26
22
  type ForeignCallSingle,
27
23
  addressFromSingle,
24
+ arrayToBoundedVec,
25
+ bufferToU8Array,
28
26
  fromArray,
29
27
  fromSingle,
30
28
  fromUintArray,
@@ -39,7 +37,7 @@ export class TXEService {
39
37
  constructor(private logger: Logger, private typedOracle: TypedOracle) {}
40
38
 
41
39
  static async init(logger: Logger) {
42
- const store = openTmpStore(true);
40
+ const store = await openTmpStore('test');
43
41
  const executionCache = new HashedValuesCache();
44
42
  const nativeWorldStateService = await NativeWorldStateService.tmp();
45
43
  const baseFork = await nativeWorldStateService.fork();
@@ -47,8 +45,9 @@ export class TXEService {
47
45
  const keyStore = new KeyStore(store);
48
46
  const txeDatabase = new TXEDatabase(store);
49
47
  // Register protocol contracts.
48
+ const provider = new BundledProtocolContractsProvider();
50
49
  for (const name of protocolContractNames) {
51
- const { contractClass, instance, artifact } = await getCanonicalProtocolContract(name);
50
+ const { contractClass, instance, artifact } = await provider.getProtocolContractArtifact(name);
52
51
  await txeDatabase.addContractArtifact(contractClass.id, artifact);
53
52
  await txeDatabase.addContractInstance(instance);
54
53
  }
@@ -99,7 +98,7 @@ export class TXEService {
99
98
  await this.addAccount(artifact, instance, secret);
100
99
  } else {
101
100
  await (this.typedOracle as TXE).addContractInstance(instance);
102
- await (this.typedOracle as TXE).addContractArtifact(instance.contractClassId, artifact);
101
+ await (this.typedOracle as TXE).addContractArtifact(instance.currentContractClassId, artifact);
103
102
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
104
103
  }
105
104
 
@@ -107,7 +106,7 @@ export class TXEService {
107
106
  toArray([
108
107
  instance.salt,
109
108
  instance.deployer.toField(),
110
- instance.contractClassId,
109
+ instance.currentContractClassId,
111
110
  instance.initializationHash,
112
111
  ...instance.publicKeys.toFields(),
113
112
  ]),
@@ -153,7 +152,7 @@ export class TXEService {
153
152
  async addAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: ForeignCallSingle) {
154
153
  this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
155
154
  await (this.typedOracle as TXE).addContractInstance(instance);
156
- await (this.typedOracle as TXE).addContractArtifact(instance.contractClassId, artifact);
155
+ await (this.typedOracle as TXE).addContractArtifact(instance.currentContractClassId, artifact);
157
156
 
158
157
  const keyStore = (this.typedOracle as TXE).getKeyStore();
159
158
  const completeAddress = await keyStore.addAccount(fromSingle(secret), await computePartialAddress(instance));
@@ -392,7 +391,7 @@ export class TXEService {
392
391
  toArray([
393
392
  instance.salt,
394
393
  instance.deployer.toField(),
395
- instance.contractClassId,
394
+ instance.currentContractClassId,
396
395
  instance.initializationHash,
397
396
  ...instance.publicKeys.toFields(),
398
397
  ]),
@@ -587,11 +586,9 @@ export class TXEService {
587
586
  const ivBuffer = fromUintArray(iv, 8);
588
587
  const symKeyBuffer = fromUintArray(symKey, 8);
589
588
 
590
- const paddedPlaintext = await this.typedOracle.aes128Decrypt(ciphertextBuffer, ivBuffer, symKeyBuffer);
589
+ const plaintextBuffer = await this.typedOracle.aes128Decrypt(ciphertextBuffer, ivBuffer, symKeyBuffer);
591
590
 
592
- // We convert each byte of the buffer to its own Field, so that the Noir
593
- // function correctly receives [u8; N].
594
- return toForeignCallResult([toArray(Array.from(paddedPlaintext).map(byte => new Fr(byte)))]);
591
+ return toForeignCallResult(arrayToBoundedVec(bufferToU8Array(plaintextBuffer), ciphertextBuffer.length));
595
592
  }
596
593
 
597
594
  // AVM opcodes
@@ -623,7 +620,7 @@ export class TXEService {
623
620
  async avmOpcodeGetContractInstanceClassId(address: ForeignCallSingle) {
624
621
  const instance = await this.typedOracle.getContractInstance(addressFromSingle(address));
625
622
  return toForeignCallResult([
626
- toSingle(instance.contractClassId),
623
+ toSingle(instance.currentContractClassId),
627
624
  // AVM requires an extra boolean indicating the instance was found
628
625
  toSingle(new Fr(1)),
629
626
  ]);
@@ -1,7 +1,8 @@
1
- import { AztecAddress, type ContractInstanceWithAddress, ContractInstanceWithAddressSchema } from '@aztec/circuits.js';
2
- import { type ContractArtifact, ContractArtifactSchema } from '@aztec/foundation/abi';
3
1
  import { Fr } from '@aztec/foundation/fields';
4
2
  import { hexToBuffer } from '@aztec/foundation/string';
3
+ import { type ContractArtifact, ContractArtifactSchema } from '@aztec/stdlib/abi';
4
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
5
+ import { type ContractInstanceWithAddress, ContractInstanceWithAddressSchema } from '@aztec/stdlib/contract';
5
6
 
6
7
  import { z } from 'zod';
7
8
 
@@ -32,7 +33,7 @@ export function fromArray(obj: ForeignCallArray) {
32
33
  * @param uintBitSize If it's an array of Noir u8's, put `8`, etc.
33
34
  * @returns
34
35
  */
35
- export function fromUintArray(obj: ForeignCallArray, uintBitSize: number) {
36
+ export function fromUintArray(obj: ForeignCallArray, uintBitSize: number): Buffer {
36
37
  if (uintBitSize % 8 !== 0) {
37
38
  throw new Error(`u${uintBitSize} is not a supported type in Noir`);
38
39
  }
@@ -40,14 +41,40 @@ export function fromUintArray(obj: ForeignCallArray, uintBitSize: number) {
40
41
  return Buffer.concat(obj.map(str => hexToBuffer(str).slice(-uintByteSize)));
41
42
  }
42
43
 
43
- export function toSingle(obj: Fr | AztecAddress) {
44
+ export function toSingle(obj: Fr | AztecAddress): ForeignCallSingle {
44
45
  return obj.toString().slice(2);
45
46
  }
46
47
 
47
- export function toArray(objs: Fr[]) {
48
+ export function toArray(objs: Fr[]): ForeignCallArray {
48
49
  return objs.map(obj => obj.toString());
49
50
  }
50
51
 
52
+ export function bufferToU8Array(buffer: Buffer): ForeignCallArray {
53
+ return toArray(Array.from(buffer).map(byte => new Fr(byte)));
54
+ }
55
+
56
+ /**
57
+ * Converts a ForeignCallArray into a tuple which represents a nr BoundedVec.
58
+ * If the input array is shorter than the maxLen, it pads the result with zeros,
59
+ * so that nr can correctly coerce this result into a BoundedVec.
60
+ * @param array
61
+ * @param maxLen - the max length of the BoundedVec.
62
+ * @returns a tuple representing a BoundedVec.
63
+ */
64
+ export function arrayToBoundedVec(array: ForeignCallArray, maxLen: number): [ForeignCallArray, ForeignCallSingle] {
65
+ if (array.length > maxLen) {
66
+ throw new Error(`Array of length ${array.length} larger than maxLen ${maxLen}`);
67
+ }
68
+ const lengthDiff = maxLen - array.length;
69
+ // We pad the array to the maxLen of the BoundedVec.
70
+ const zeroPaddingArray = toArray(Array(lengthDiff).fill(new Fr(0)));
71
+
72
+ // These variable names match with the BoundedVec members in nr:
73
+ const storage = array.concat(zeroPaddingArray);
74
+ const len = toSingle(new Fr(array.length));
75
+ return [storage, len];
76
+ }
77
+
51
78
  export function toForeignCallResult(obj: (ForeignCallSingle | ForeignCallArray)[]) {
52
79
  return { values: obj };
53
80
  }
@@ -1,6 +1,7 @@
1
- import { type AztecAddress, CompleteAddress } from '@aztec/circuits.js';
2
- import { type AztecAsyncKVStore, type AztecAsyncMap } from '@aztec/kv-store';
1
+ import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
3
2
  import { KVPxeDatabase } from '@aztec/pxe';
3
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+ import { CompleteAddress } from '@aztec/stdlib/contract';
4
5
 
5
6
  export class TXEDatabase extends KVPxeDatabase {
6
7
  #accounts: AztecAsyncMap<string, Buffer>;
@@ -1,18 +1,17 @@
1
+ import { PUBLIC_DISPATCH_SELECTOR } from '@aztec/constants';
2
+ import { Fr } from '@aztec/foundation/fields';
3
+ import { PrivateFunctionsTree } from '@aztec/pxe';
4
+ import { type ContractArtifact, FunctionSelector } from '@aztec/stdlib/abi';
5
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
1
6
  import {
2
- type AztecAddress,
3
7
  type ContractClassPublic,
4
8
  type ContractDataSource,
5
9
  type ContractInstanceWithAddress,
6
- Fr,
7
- FunctionSelector,
8
- PUBLIC_DISPATCH_SELECTOR,
9
10
  type PublicFunction,
10
11
  computePublicBytecodeCommitment,
11
- } from '@aztec/circuits.js';
12
- import { type ContractArtifact } from '@aztec/foundation/abi';
13
- import { PrivateFunctionsTree } from '@aztec/pxe';
12
+ } from '@aztec/stdlib/contract';
14
13
 
15
- import { type TXE } from '../oracle/txe_oracle.js';
14
+ import type { TXE } from '../oracle/txe_oracle.js';
16
15
 
17
16
  export class TXEPublicContractDataSource implements ContractDataSource {
18
17
  constructor(private txeOracle: TXE) {}
@@ -71,7 +70,7 @@ export class TXEPublicContractDataSource implements ContractDataSource {
71
70
 
72
71
  async getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined> {
73
72
  const instance = await this.txeOracle.getContractDataOracle().getContractInstance(address);
74
- return this.txeOracle.getContractDataOracle().getContractArtifact(instance.contractClassId);
73
+ return this.txeOracle.getContractDataOracle().getContractArtifact(instance.currentContractClassId);
75
74
  }
76
75
 
77
76
  async getContractFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {