@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.
- package/dest/bin/index.js +3 -5
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +106 -106
- package/dest/node/txe_node.d.ts +19 -6
- package/dest/node/txe_node.d.ts.map +1 -1
- package/dest/node/txe_node.js +303 -334
- package/dest/oracle/txe_oracle.d.ts +25 -16
- package/dest/oracle/txe_oracle.d.ts.map +1 -1
- package/dest/oracle/txe_oracle.js +249 -143
- package/dest/txe_service/txe_service.d.ts +3 -3
- package/dest/txe_service/txe_service.d.ts.map +1 -1
- package/dest/txe_service/txe_service.js +205 -105
- package/dest/util/encoding.d.ts +39 -25
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +45 -11
- package/dest/util/expected_failure_error.js +1 -2
- package/dest/util/txe_database.d.ts +3 -2
- package/dest/util/txe_database.d.ts.map +1 -1
- package/dest/util/txe_database.js +6 -10
- package/dest/util/txe_public_contract_data_source.d.ts +5 -3
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +25 -13
- package/dest/util/txe_world_state_db.d.ts +6 -8
- package/dest/util/txe_world_state_db.d.ts.map +1 -1
- package/dest/util/txe_world_state_db.js +10 -23
- package/package.json +14 -15
- package/src/index.ts +2 -2
- package/src/node/txe_node.ts +64 -42
- package/src/oracle/txe_oracle.ts +101 -86
- package/src/txe_service/txe_service.ts +25 -28
- package/src/util/encoding.ts +32 -5
- package/src/util/txe_database.ts +3 -2
- package/src/util/txe_public_contract_data_source.ts +8 -9
- package/src/util/txe_world_state_db.ts +9 -26
package/src/node/txe_node.ts
CHANGED
|
@@ -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
|
-
|
|
42
|
-
|
|
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 {
|
|
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(
|
|
586
|
-
|
|
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
|
|
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
|
}
|
package/src/oracle/txe_oracle.ts
CHANGED
|
@@ -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
|
-
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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:
|
|
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!.
|
|
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
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
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
|
-
|
|
912
|
-
|
|
910
|
+
const { usedTxRequestHashForNonces } = this.noteCache.finish();
|
|
911
|
+
const firstNullifier = usedTxRequestHashForNonces
|
|
912
|
+
? this.getTxRequestHash()
|
|
913
|
+
: this.noteCache.getAllNullifiers()[0];
|
|
913
914
|
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
|
|
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 {
|
|
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 {
|
|
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(
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
589
|
+
const plaintextBuffer = await this.typedOracle.aes128Decrypt(ciphertextBuffer, ivBuffer, symKeyBuffer);
|
|
591
590
|
|
|
592
|
-
|
|
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.
|
|
623
|
+
toSingle(instance.currentContractClassId),
|
|
627
624
|
// AVM requires an extra boolean indicating the instance was found
|
|
628
625
|
toSingle(new Fr(1)),
|
|
629
626
|
]);
|
package/src/util/encoding.ts
CHANGED
|
@@ -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
|
}
|
package/src/util/txe_database.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
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/
|
|
12
|
-
import { type ContractArtifact } from '@aztec/foundation/abi';
|
|
13
|
-
import { PrivateFunctionsTree } from '@aztec/pxe';
|
|
12
|
+
} from '@aztec/stdlib/contract';
|
|
14
13
|
|
|
15
|
-
import {
|
|
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.
|
|
73
|
+
return this.txeOracle.getContractDataOracle().getContractArtifact(instance.currentContractClassId);
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
async getContractFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
|