@aztec/txe 0.0.1-commit.1bea0213 → 0.0.1-commit.217f559981
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +82 -50
- package/dest/oracle/interfaces.d.ts +3 -3
- package/dest/oracle/interfaces.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.d.ts +2 -2
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_public_context.js +3 -4
- package/dest/oracle/txe_oracle_top_level_context.d.ts +5 -6
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
- package/dest/oracle/txe_oracle_top_level_context.js +92 -31
- package/dest/rpc_translator.d.ts +9 -9
- package/dest/rpc_translator.d.ts.map +1 -1
- package/dest/rpc_translator.js +42 -31
- package/dest/state_machine/archiver.d.ts +1 -1
- package/dest/state_machine/archiver.d.ts.map +1 -1
- package/dest/state_machine/archiver.js +2 -0
- package/dest/state_machine/dummy_p2p_client.d.ts +15 -11
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
- package/dest/state_machine/dummy_p2p_client.js +27 -15
- package/dest/state_machine/index.d.ts +5 -5
- package/dest/state_machine/index.d.ts.map +1 -1
- package/dest/state_machine/index.js +15 -10
- package/dest/state_machine/mock_epoch_cache.d.ts +3 -1
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
- package/dest/state_machine/mock_epoch_cache.js +4 -0
- package/dest/txe_session.d.ts +4 -6
- package/dest/txe_session.d.ts.map +1 -1
- package/dest/txe_session.js +69 -17
- package/dest/util/txe_public_contract_data_source.d.ts +2 -3
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +5 -22
- package/dest/utils/block_creation.d.ts +1 -1
- package/dest/utils/block_creation.d.ts.map +1 -1
- package/dest/utils/block_creation.js +3 -1
- package/package.json +15 -15
- package/src/index.ts +83 -49
- package/src/oracle/interfaces.ts +2 -2
- package/src/oracle/txe_oracle_public_context.ts +3 -5
- package/src/oracle/txe_oracle_top_level_context.ts +113 -85
- package/src/rpc_translator.ts +44 -26
- package/src/state_machine/archiver.ts +2 -0
- package/src/state_machine/dummy_p2p_client.ts +39 -21
- package/src/state_machine/index.ts +25 -9
- package/src/state_machine/mock_epoch_cache.ts +5 -0
- package/src/txe_session.ts +73 -77
- package/src/util/txe_public_contract_data_source.ts +10 -36
- package/src/utils/block_creation.ts +3 -1
- package/dest/util/txe_contract_store.d.ts +0 -12
- package/dest/util/txe_contract_store.d.ts.map +0 -1
- package/dest/util/txe_contract_store.js +0 -22
- package/src/util/txe_contract_store.ts +0 -36
package/src/rpc_translator.ts
CHANGED
|
@@ -328,7 +328,7 @@ export class RPCTranslator {
|
|
|
328
328
|
|
|
329
329
|
// When the argument is a slice, noir automatically adds a length field to oracle call.
|
|
330
330
|
// When the argument is an array, we add the field length manually to the signature.
|
|
331
|
-
|
|
331
|
+
async utilityLog(
|
|
332
332
|
foreignLevel: ForeignCallSingle,
|
|
333
333
|
foreignMessage: ForeignCallArray,
|
|
334
334
|
_foreignLength: ForeignCallSingle,
|
|
@@ -340,7 +340,7 @@ export class RPCTranslator {
|
|
|
340
340
|
.join('');
|
|
341
341
|
const fields = fromArray(foreignFields);
|
|
342
342
|
|
|
343
|
-
this.handlerAsMisc().
|
|
343
|
+
await this.handlerAsMisc().utilityLog(level, message, fields);
|
|
344
344
|
|
|
345
345
|
return toForeignCallResult([]);
|
|
346
346
|
}
|
|
@@ -351,7 +351,7 @@ export class RPCTranslator {
|
|
|
351
351
|
foreignStartStorageSlot: ForeignCallSingle,
|
|
352
352
|
foreignNumberOfElements: ForeignCallSingle,
|
|
353
353
|
) {
|
|
354
|
-
const blockHash = BlockHash
|
|
354
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
355
355
|
const contractAddress = addressFromSingle(foreignContractAddress);
|
|
356
356
|
const startStorageSlot = fromSingle(foreignStartStorageSlot);
|
|
357
357
|
const numberOfElements = fromSingle(foreignNumberOfElements).toNumber();
|
|
@@ -367,7 +367,7 @@ export class RPCTranslator {
|
|
|
367
367
|
}
|
|
368
368
|
|
|
369
369
|
async utilityGetPublicDataWitness(foreignBlockHash: ForeignCallSingle, foreignLeafSlot: ForeignCallSingle) {
|
|
370
|
-
const blockHash = BlockHash
|
|
370
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
371
371
|
const leafSlot = fromSingle(foreignLeafSlot);
|
|
372
372
|
|
|
373
373
|
const witness = await this.handlerAsUtility().utilityGetPublicDataWitness(blockHash, leafSlot);
|
|
@@ -545,12 +545,23 @@ export class RPCTranslator {
|
|
|
545
545
|
);
|
|
546
546
|
}
|
|
547
547
|
|
|
548
|
-
async
|
|
548
|
+
async utilityTryGetPublicKeysAndPartialAddress(foreignAddress: ForeignCallSingle) {
|
|
549
549
|
const address = addressFromSingle(foreignAddress);
|
|
550
550
|
|
|
551
|
-
const
|
|
551
|
+
const result = await this.handlerAsUtility().utilityTryGetPublicKeysAndPartialAddress(address);
|
|
552
552
|
|
|
553
|
-
return
|
|
553
|
+
// We are going to return a Noir Option struct to represent the possibility of null values. Options are a struct
|
|
554
|
+
// with two fields: `some` (a boolean) and `value` (a field array in this case).
|
|
555
|
+
if (result === undefined) {
|
|
556
|
+
// No data was found so we set `some` to 0 and pad `value` with zeros get the correct return size.
|
|
557
|
+
return toForeignCallResult([toSingle(new Fr(0)), toArray(Array(13).fill(new Fr(0)))]);
|
|
558
|
+
} else {
|
|
559
|
+
// Data was found so we set `some` to 1 and return it along with `value`.
|
|
560
|
+
return toForeignCallResult([
|
|
561
|
+
toSingle(new Fr(1)),
|
|
562
|
+
toArray([...result.publicKeys.toFields(), result.partialAddress]),
|
|
563
|
+
]);
|
|
564
|
+
}
|
|
554
565
|
}
|
|
555
566
|
|
|
556
567
|
async utilityGetKeyValidationRequest(foreignPkMHash: ForeignCallSingle) {
|
|
@@ -574,7 +585,7 @@ export class RPCTranslator {
|
|
|
574
585
|
}
|
|
575
586
|
|
|
576
587
|
async utilityGetNullifierMembershipWitness(foreignBlockHash: ForeignCallSingle, foreignNullifier: ForeignCallSingle) {
|
|
577
|
-
const blockHash = BlockHash
|
|
588
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
578
589
|
const nullifier = fromSingle(foreignNullifier);
|
|
579
590
|
|
|
580
591
|
const witness = await this.handlerAsUtility().utilityGetNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -641,26 +652,34 @@ export class RPCTranslator {
|
|
|
641
652
|
return toForeignCallResult(header.toFields().map(toSingle));
|
|
642
653
|
}
|
|
643
654
|
|
|
644
|
-
async utilityGetNoteHashMembershipWitness(
|
|
645
|
-
|
|
646
|
-
|
|
655
|
+
async utilityGetNoteHashMembershipWitness(
|
|
656
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
657
|
+
foreignNoteHash: ForeignCallSingle,
|
|
658
|
+
) {
|
|
659
|
+
const blockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
660
|
+
const noteHash = fromSingle(foreignNoteHash);
|
|
647
661
|
|
|
648
|
-
const witness = await this.handlerAsUtility().utilityGetNoteHashMembershipWitness(blockHash,
|
|
662
|
+
const witness = await this.handlerAsUtility().utilityGetNoteHashMembershipWitness(blockHash, noteHash);
|
|
649
663
|
|
|
650
664
|
if (!witness) {
|
|
651
|
-
throw new Error(`Note hash ${
|
|
665
|
+
throw new Error(`Note hash ${noteHash} not found in the note hash tree at block ${blockHash.toString()}.`);
|
|
652
666
|
}
|
|
653
667
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
654
668
|
}
|
|
655
669
|
|
|
656
|
-
async
|
|
657
|
-
|
|
658
|
-
|
|
670
|
+
async utilityGetBlockHashMembershipWitness(
|
|
671
|
+
foreignAnchorBlockHash: ForeignCallSingle,
|
|
672
|
+
foreignBlockHash: ForeignCallSingle,
|
|
673
|
+
) {
|
|
674
|
+
const anchorBlockHash = new BlockHash(fromSingle(foreignAnchorBlockHash));
|
|
675
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
659
676
|
|
|
660
|
-
const witness = await this.handlerAsUtility().
|
|
677
|
+
const witness = await this.handlerAsUtility().utilityGetBlockHashMembershipWitness(anchorBlockHash, blockHash);
|
|
661
678
|
|
|
662
679
|
if (!witness) {
|
|
663
|
-
throw new Error(
|
|
680
|
+
throw new Error(
|
|
681
|
+
`Block hash ${blockHash.toString()} not found in the archive tree at anchor block ${anchorBlockHash.toString()}.`,
|
|
682
|
+
);
|
|
664
683
|
}
|
|
665
684
|
return toForeignCallResult(witness.toNoirRepresentation());
|
|
666
685
|
}
|
|
@@ -669,7 +688,7 @@ export class RPCTranslator {
|
|
|
669
688
|
foreignBlockHash: ForeignCallSingle,
|
|
670
689
|
foreignNullifier: ForeignCallSingle,
|
|
671
690
|
) {
|
|
672
|
-
const blockHash = BlockHash
|
|
691
|
+
const blockHash = new BlockHash(fromSingle(foreignBlockHash));
|
|
673
692
|
const nullifier = fromSingle(foreignNullifier);
|
|
674
693
|
|
|
675
694
|
const witness = await this.handlerAsUtility().utilityGetLowNullifierMembershipWitness(blockHash, nullifier);
|
|
@@ -830,7 +849,7 @@ export class RPCTranslator {
|
|
|
830
849
|
|
|
831
850
|
// AVM opcodes
|
|
832
851
|
|
|
833
|
-
|
|
852
|
+
avmOpcodeEmitPublicLog(_foreignMessage: ForeignCallArray) {
|
|
834
853
|
// TODO(#8811): Implement
|
|
835
854
|
return toForeignCallResult([]);
|
|
836
855
|
}
|
|
@@ -911,11 +930,10 @@ export class RPCTranslator {
|
|
|
911
930
|
return toForeignCallResult([]);
|
|
912
931
|
}
|
|
913
932
|
|
|
914
|
-
async avmOpcodeNullifierExists(
|
|
915
|
-
const
|
|
916
|
-
const targetAddress = AztecAddress.fromField(fromSingle(foreignTargetAddress));
|
|
933
|
+
async avmOpcodeNullifierExists(foreignSiloedNullifier: ForeignCallSingle) {
|
|
934
|
+
const siloedNullifier = fromSingle(foreignSiloedNullifier);
|
|
917
935
|
|
|
918
|
-
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(
|
|
936
|
+
const exists = await this.handlerAsAvm().avmOpcodeNullifierExists(siloedNullifier);
|
|
919
937
|
|
|
920
938
|
return toForeignCallResult([toSingle(new Fr(exists))]);
|
|
921
939
|
}
|
|
@@ -1025,7 +1043,7 @@ export class RPCTranslator {
|
|
|
1025
1043
|
return toForeignCallResult([toArray(returnValues)]);
|
|
1026
1044
|
}
|
|
1027
1045
|
|
|
1028
|
-
async
|
|
1046
|
+
async txeExecuteUtilityFunction(
|
|
1029
1047
|
foreignTargetContractAddress: ForeignCallSingle,
|
|
1030
1048
|
foreignFunctionSelector: ForeignCallSingle,
|
|
1031
1049
|
foreignArgs: ForeignCallArray,
|
|
@@ -1034,7 +1052,7 @@ export class RPCTranslator {
|
|
|
1034
1052
|
const functionSelector = FunctionSelector.fromField(fromSingle(foreignFunctionSelector));
|
|
1035
1053
|
const args = fromArray(foreignArgs);
|
|
1036
1054
|
|
|
1037
|
-
const returnValues = await this.handlerAsTxe().
|
|
1055
|
+
const returnValues = await this.handlerAsTxe().txeExecuteUtilityFunction(
|
|
1038
1056
|
targetContractAddress,
|
|
1039
1057
|
functionSelector,
|
|
1040
1058
|
args,
|
|
@@ -59,6 +59,8 @@ export class TXEArchiver extends ArchiverDataSourceBase {
|
|
|
59
59
|
if (!checkpointedBlock) {
|
|
60
60
|
throw new Error(`L2Tips requested from TXE Archiver but no checkpointed block found for block number ${number}`);
|
|
61
61
|
}
|
|
62
|
+
// TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
|
|
63
|
+
// This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
|
|
62
64
|
const checkpoint = await this.store.getRangeOfCheckpoints(CheckpointNumber.fromBlockNumber(number), 1);
|
|
63
65
|
if (checkpoint.length === 0) {
|
|
64
66
|
throw new Error(`L2Tips requested from TXE Archiver but no checkpoint found for block number ${number}`);
|
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
P2PBlockReceivedCallback,
|
|
7
7
|
P2PCheckpointReceivedCallback,
|
|
8
8
|
P2PConfig,
|
|
9
|
+
P2PDuplicateAttestationCallback,
|
|
10
|
+
P2PDuplicateProposalCallback,
|
|
9
11
|
P2PSyncState,
|
|
10
12
|
PeerId,
|
|
11
13
|
ReqRespSubProtocol,
|
|
@@ -14,9 +16,9 @@ import type {
|
|
|
14
16
|
StatusMessage,
|
|
15
17
|
} from '@aztec/p2p';
|
|
16
18
|
import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
|
|
17
|
-
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
18
|
-
import type { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
|
|
19
|
-
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
19
|
+
import type { ITxProvider, PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
20
|
+
import type { BlockProposal, CheckpointAttestation, CheckpointProposal, TopicType } from '@aztec/stdlib/p2p';
|
|
21
|
+
import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
|
|
20
22
|
|
|
21
23
|
export class DummyP2P implements P2P {
|
|
22
24
|
public validate(_txs: Tx[]): Promise<void> {
|
|
@@ -39,6 +41,10 @@ export class DummyP2P implements P2P {
|
|
|
39
41
|
throw new Error('DummyP2P does not implement "getPeers"');
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
public getGossipMeshPeerCount(_topicType: TopicType): Promise<number> {
|
|
45
|
+
return Promise.resolve(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
public broadcastProposal(_proposal: BlockProposal): Promise<void> {
|
|
43
49
|
throw new Error('DummyP2P does not implement "broadcastProposal"');
|
|
44
50
|
}
|
|
@@ -71,8 +77,8 @@ export class DummyP2P implements P2P {
|
|
|
71
77
|
throw new Error('DummyP2P does not implement "sendTx"');
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
public
|
|
75
|
-
throw new Error('DummyP2P does not implement "
|
|
80
|
+
public handleFailedExecution(_txHashes: TxHash[]): Promise<void> {
|
|
81
|
+
throw new Error('DummyP2P does not implement "handleFailedExecution"');
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
public getTxByHashFromPool(_txHash: TxHash): Promise<Tx | undefined> {
|
|
@@ -97,6 +103,10 @@ export class DummyP2P implements P2P {
|
|
|
97
103
|
throw new Error('DummyP2P does not implement "iteratePendingTxs"');
|
|
98
104
|
}
|
|
99
105
|
|
|
106
|
+
public iterateEligiblePendingTxs(): AsyncIterableIterator<Tx> {
|
|
107
|
+
throw new Error('DummyP2P does not implement "iterateEligiblePendingTxs"');
|
|
108
|
+
}
|
|
109
|
+
|
|
100
110
|
public getPendingTxCount(): Promise<number> {
|
|
101
111
|
throw new Error('DummyP2P does not implement "getPendingTxCount"');
|
|
102
112
|
}
|
|
@@ -125,6 +135,10 @@ export class DummyP2P implements P2P {
|
|
|
125
135
|
throw new Error('DummyP2P does not implement "isP2PClient"');
|
|
126
136
|
}
|
|
127
137
|
|
|
138
|
+
public getTxProvider(): ITxProvider {
|
|
139
|
+
throw new Error('DummyP2P does not implement "getTxProvider"');
|
|
140
|
+
}
|
|
141
|
+
|
|
128
142
|
public getTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
|
|
129
143
|
throw new Error('DummyP2P does not implement "getTxsByHash"');
|
|
130
144
|
}
|
|
@@ -133,8 +147,8 @@ export class DummyP2P implements P2P {
|
|
|
133
147
|
throw new Error('DummyP2P does not implement "getCheckpointAttestationsForSlot"');
|
|
134
148
|
}
|
|
135
149
|
|
|
136
|
-
public
|
|
137
|
-
throw new Error('DummyP2P does not implement "
|
|
150
|
+
public addOwnCheckpointAttestations(_attestations: CheckpointAttestation[]): Promise<void> {
|
|
151
|
+
throw new Error('DummyP2P does not implement "addOwnCheckpointAttestations"');
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
public getL2BlockHash(_number: number): Promise<string | undefined> {
|
|
@@ -157,14 +171,6 @@ export class DummyP2P implements P2P {
|
|
|
157
171
|
throw new Error('DummyP2P does not implement "sync"');
|
|
158
172
|
}
|
|
159
173
|
|
|
160
|
-
public requestTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
|
|
161
|
-
throw new Error('DummyP2P does not implement "requestTxsByHash"');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public getTxs(_filter: 'all' | 'pending' | 'mined'): Promise<Tx[]> {
|
|
165
|
-
throw new Error('DummyP2P does not implement "getTxs"');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
174
|
public getTxsByHashFromPool(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
169
175
|
throw new Error('DummyP2P does not implement "getTxsByHashFromPool"');
|
|
170
176
|
}
|
|
@@ -173,10 +179,6 @@ export class DummyP2P implements P2P {
|
|
|
173
179
|
throw new Error('DummyP2P does not implement "hasTxsInPool"');
|
|
174
180
|
}
|
|
175
181
|
|
|
176
|
-
public addTxsToPool(_txs: Tx[]): Promise<number> {
|
|
177
|
-
throw new Error('DummyP2P does not implement "addTxs"');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
182
|
public getSyncedLatestBlockNum(): Promise<number> {
|
|
181
183
|
throw new Error('DummyP2P does not implement "getSyncedLatestBlockNum"');
|
|
182
184
|
}
|
|
@@ -189,8 +191,12 @@ export class DummyP2P implements P2P {
|
|
|
189
191
|
throw new Error('DummyP2P does not implement "getSyncedLatestSlot"');
|
|
190
192
|
}
|
|
191
193
|
|
|
192
|
-
|
|
193
|
-
throw new Error('DummyP2P does not implement "
|
|
194
|
+
protectTxs(_txHashes: TxHash[], _blockHeader: BlockHeader): Promise<TxHash[]> {
|
|
195
|
+
throw new Error('DummyP2P does not implement "protectTxs".');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
prepareForSlot(_slotNumber: SlotNumber): Promise<void> {
|
|
199
|
+
return Promise.resolve();
|
|
194
200
|
}
|
|
195
201
|
|
|
196
202
|
addReqRespSubProtocol(
|
|
@@ -206,4 +212,16 @@ export class DummyP2P implements P2P {
|
|
|
206
212
|
|
|
207
213
|
//This is no-op
|
|
208
214
|
public registerThisValidatorAddresses(_address: EthAddress[]): void {}
|
|
215
|
+
|
|
216
|
+
public registerDuplicateProposalCallback(_callback: P2PDuplicateProposalCallback): void {
|
|
217
|
+
throw new Error('DummyP2P does not implement "registerDuplicateProposalCallback"');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
public registerDuplicateAttestationCallback(_callback: P2PDuplicateAttestationCallback): void {
|
|
221
|
+
throw new Error('DummyP2P does not implement "registerDuplicateAttestationCallback"');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
public hasBlockProposalsForSlot(_slot: SlotNumber): Promise<boolean> {
|
|
225
|
+
throw new Error('DummyP2P does not implement "hasBlockProposalsForSlot"');
|
|
226
|
+
}
|
|
209
227
|
}
|
|
@@ -3,8 +3,7 @@ import { TestCircuitVerifier } from '@aztec/bb-prover/test';
|
|
|
3
3
|
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
6
|
-
import type
|
|
7
|
-
import { AnchorBlockStore } from '@aztec/pxe/server';
|
|
6
|
+
import { type AnchorBlockStore, type ContractStore, ContractSyncService, type NoteStore } from '@aztec/pxe/server';
|
|
8
7
|
import { L2Block } from '@aztec/stdlib/block';
|
|
9
8
|
import { Checkpoint, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
10
9
|
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
@@ -26,13 +25,16 @@ export class TXEStateMachine {
|
|
|
26
25
|
public synchronizer: TXESynchronizer,
|
|
27
26
|
public archiver: TXEArchiver,
|
|
28
27
|
public anchorBlockStore: AnchorBlockStore,
|
|
28
|
+
public contractSyncService: ContractSyncService,
|
|
29
29
|
) {}
|
|
30
30
|
|
|
31
|
-
public static async create(
|
|
32
|
-
|
|
31
|
+
public static async create(
|
|
32
|
+
archiver: TXEArchiver,
|
|
33
|
+
anchorBlockStore: AnchorBlockStore,
|
|
34
|
+
contractStore: ContractStore,
|
|
35
|
+
noteStore: NoteStore,
|
|
36
|
+
) {
|
|
33
37
|
const synchronizer = await TXESynchronizer.create();
|
|
34
|
-
const anchorBlockStore = new AnchorBlockStore(db);
|
|
35
|
-
|
|
36
38
|
const aztecNodeConfig = {} as AztecNodeConfig;
|
|
37
39
|
|
|
38
40
|
const log = createLogger('txe_node');
|
|
@@ -48,6 +50,7 @@ export class TXEStateMachine {
|
|
|
48
50
|
undefined,
|
|
49
51
|
undefined,
|
|
50
52
|
undefined,
|
|
53
|
+
undefined,
|
|
51
54
|
VERSION,
|
|
52
55
|
CHAIN_ID,
|
|
53
56
|
new TXEGlobalVariablesBuilder(),
|
|
@@ -58,11 +61,21 @@ export class TXEStateMachine {
|
|
|
58
61
|
log,
|
|
59
62
|
);
|
|
60
63
|
|
|
61
|
-
|
|
64
|
+
const contractSyncService = new ContractSyncService(
|
|
65
|
+
node,
|
|
66
|
+
contractStore,
|
|
67
|
+
noteStore,
|
|
68
|
+
createLogger('txe:contract_sync'),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return new this(node, synchronizer, archiver, anchorBlockStore, contractSyncService);
|
|
62
72
|
}
|
|
63
73
|
|
|
64
74
|
public async handleL2Block(block: L2Block) {
|
|
65
|
-
// Create a checkpoint from the block manually
|
|
75
|
+
// Create a checkpoint from the block manually.
|
|
76
|
+
// TXE uses 1-block-per-checkpoint for testing simplicity, so we can use block number as checkpoint number.
|
|
77
|
+
// This uses the deprecated fromBlockNumber method intentionally for the TXE testing environment.
|
|
78
|
+
const checkpointNumber = CheckpointNumber.fromBlockNumber(block.number);
|
|
66
79
|
const checkpoint = new Checkpoint(
|
|
67
80
|
block.archive,
|
|
68
81
|
CheckpointHeader.from({
|
|
@@ -79,7 +92,7 @@ export class TXEStateMachine {
|
|
|
79
92
|
totalManaUsed: block.header.totalManaUsed,
|
|
80
93
|
}),
|
|
81
94
|
[block],
|
|
82
|
-
|
|
95
|
+
checkpointNumber,
|
|
83
96
|
);
|
|
84
97
|
|
|
85
98
|
const publishedCheckpoint = new PublishedCheckpoint(
|
|
@@ -91,6 +104,9 @@ export class TXEStateMachine {
|
|
|
91
104
|
),
|
|
92
105
|
[],
|
|
93
106
|
);
|
|
107
|
+
// Wipe contract sync cache when anchor block changes (mirrors BlockSynchronizer behavior)
|
|
108
|
+
this.contractSyncService.wipe();
|
|
109
|
+
|
|
94
110
|
await Promise.all([
|
|
95
111
|
this.synchronizer.handleL2Block(block),
|
|
96
112
|
this.archiver.addCheckpoints([publishedCheckpoint], undefined),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '@aztec/epoch-cache';
|
|
2
2
|
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
+
import { EmptyL1RollupConstants, type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Mock implementation of the EpochCacheInterface used to satisfy dependencies of AztecNodeService.
|
|
@@ -64,4 +65,8 @@ export class MockEpochCache implements EpochCacheInterface {
|
|
|
64
65
|
filterInCommittee(_slot: SlotTag, _validators: EthAddress[]): Promise<EthAddress[]> {
|
|
65
66
|
return Promise.resolve([]);
|
|
66
67
|
}
|
|
68
|
+
|
|
69
|
+
getL1Constants(): L1RollupConstants {
|
|
70
|
+
return EmptyL1RollupConstants;
|
|
71
|
+
}
|
|
67
72
|
}
|
package/src/txe_session.ts
CHANGED
|
@@ -3,10 +3,12 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { KeyStore } from '@aztec/key-store';
|
|
5
5
|
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
6
|
-
import type {
|
|
6
|
+
import type { AccessScopes } from '@aztec/pxe/client/lazy';
|
|
7
7
|
import {
|
|
8
8
|
AddressStore,
|
|
9
|
+
AnchorBlockStore,
|
|
9
10
|
CapsuleStore,
|
|
11
|
+
ContractStore,
|
|
10
12
|
JobCoordinator,
|
|
11
13
|
NoteService,
|
|
12
14
|
NoteStore,
|
|
@@ -49,10 +51,10 @@ import type { IAvmExecutionOracle, ITxeExecutionOracle } from './oracle/interfac
|
|
|
49
51
|
import { TXEOraclePublicContext } from './oracle/txe_oracle_public_context.js';
|
|
50
52
|
import { TXEOracleTopLevelContext } from './oracle/txe_oracle_top_level_context.js';
|
|
51
53
|
import { RPCTranslator } from './rpc_translator.js';
|
|
54
|
+
import { TXEArchiver } from './state_machine/archiver.js';
|
|
52
55
|
import { TXEStateMachine } from './state_machine/index.js';
|
|
53
56
|
import type { ForeignCallArgs, ForeignCallResult } from './util/encoding.js';
|
|
54
57
|
import { TXEAccountStore } from './util/txe_account_store.js';
|
|
55
|
-
import { TXEContractStore } from './util/txe_contract_store.js';
|
|
56
58
|
import { getSingleTxBlockRequestHash, insertTxEffectIntoWorldTrees, makeTXEBlock } from './utils/block_creation.js';
|
|
57
59
|
import { makeTxEffect } from './utils/tx_effect_creation.js';
|
|
58
60
|
|
|
@@ -129,7 +131,7 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
129
131
|
| IPrivateExecutionOracle
|
|
130
132
|
| IAvmExecutionOracle
|
|
131
133
|
| ITxeExecutionOracle,
|
|
132
|
-
private contractStore:
|
|
134
|
+
private contractStore: ContractStore,
|
|
133
135
|
private noteStore: NoteStore,
|
|
134
136
|
private keyStore: KeyStore,
|
|
135
137
|
private addressStore: AddressStore,
|
|
@@ -146,12 +148,11 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
146
148
|
private nextBlockTimestamp: bigint,
|
|
147
149
|
) {}
|
|
148
150
|
|
|
149
|
-
static async init(
|
|
151
|
+
static async init(contractStore: ContractStore) {
|
|
150
152
|
const store = await openTmpStore('txe-session');
|
|
151
153
|
|
|
152
154
|
const addressStore = new AddressStore(store);
|
|
153
155
|
const privateEventStore = new PrivateEventStore(store);
|
|
154
|
-
const contractStore = new TXEContractStore(store);
|
|
155
156
|
const noteStore = new NoteStore(store);
|
|
156
157
|
const senderTaggingStore = new SenderTaggingStore(store);
|
|
157
158
|
const recipientTaggingStore = new RecipientTaggingStore(store);
|
|
@@ -170,13 +171,9 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
170
171
|
noteStore,
|
|
171
172
|
]);
|
|
172
173
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
await contractStore.addContractInstance(instance);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const stateMachine = await TXEStateMachine.create(store);
|
|
174
|
+
const archiver = new TXEArchiver(store);
|
|
175
|
+
const anchorBlockStore = new AnchorBlockStore(store);
|
|
176
|
+
const stateMachine = await TXEStateMachine.create(archiver, anchorBlockStore, contractStore, noteStore);
|
|
180
177
|
|
|
181
178
|
const nextBlockTimestamp = BigInt(Math.floor(new Date().getTime() / 1000));
|
|
182
179
|
const version = new Fr(await stateMachine.node.getVersion());
|
|
@@ -312,17 +309,15 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
312
309
|
): Promise<PrivateContextInputs> {
|
|
313
310
|
this.exitTopLevelState();
|
|
314
311
|
|
|
315
|
-
await new NoteService(
|
|
316
|
-
this.noteStore,
|
|
317
|
-
this.stateMachine.node,
|
|
318
|
-
this.stateMachine.anchorBlockStore,
|
|
319
|
-
this.currentJobId,
|
|
320
|
-
).syncNoteNullifiers(contractAddress);
|
|
321
|
-
|
|
322
312
|
// Private execution has two associated block numbers: the anchor block (i.e. the historical block that is used to
|
|
323
313
|
// build the proof), and the *next* block, i.e. the one we'll create once the execution ends, and which will contain
|
|
324
314
|
// a single transaction with the effects of what was done in the test.
|
|
325
315
|
const anchorBlock = await this.stateMachine.node.getBlockHeader(anchorBlockNumber ?? 'latest');
|
|
316
|
+
|
|
317
|
+
await new NoteService(this.noteStore, this.stateMachine.node, anchorBlock!, this.currentJobId).syncNoteNullifiers(
|
|
318
|
+
contractAddress,
|
|
319
|
+
'ALL_SCOPES',
|
|
320
|
+
);
|
|
326
321
|
const latestBlock = await this.stateMachine.node.getBlockHeader('latest');
|
|
327
322
|
|
|
328
323
|
const nextBlockGlobalVariables = makeGlobalVariables(undefined, {
|
|
@@ -338,30 +333,31 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
338
333
|
const taggingIndexCache = new ExecutionTaggingIndexCache();
|
|
339
334
|
|
|
340
335
|
const utilityExecutor = this.utilityExecutorForContractSync(anchorBlock);
|
|
341
|
-
this.oracleHandler = new PrivateExecutionOracle(
|
|
342
|
-
Fr.ZERO,
|
|
343
|
-
new TxContext(this.chainId, this.version, GasSettings.empty()),
|
|
344
|
-
new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
|
|
345
|
-
anchorBlock!,
|
|
336
|
+
this.oracleHandler = new PrivateExecutionOracle({
|
|
337
|
+
argsHash: Fr.ZERO,
|
|
338
|
+
txContext: new TxContext(this.chainId, this.version, GasSettings.empty()),
|
|
339
|
+
callContext: new CallContext(AztecAddress.ZERO, contractAddress, FunctionSelector.empty(), false),
|
|
340
|
+
anchorBlockHeader: anchorBlock!,
|
|
346
341
|
utilityExecutor,
|
|
347
|
-
[],
|
|
348
|
-
[],
|
|
349
|
-
new HashedValuesCache(),
|
|
342
|
+
authWitnesses: [],
|
|
343
|
+
capsules: [],
|
|
344
|
+
executionCache: new HashedValuesCache(),
|
|
350
345
|
noteCache,
|
|
351
346
|
taggingIndexCache,
|
|
352
|
-
this.contractStore,
|
|
353
|
-
this.noteStore,
|
|
354
|
-
this.keyStore,
|
|
355
|
-
this.addressStore,
|
|
356
|
-
this.stateMachine.node,
|
|
357
|
-
this.
|
|
358
|
-
this.
|
|
359
|
-
this.
|
|
360
|
-
this.
|
|
361
|
-
this.
|
|
362
|
-
this.
|
|
363
|
-
this.currentJobId,
|
|
364
|
-
|
|
347
|
+
contractStore: this.contractStore,
|
|
348
|
+
noteStore: this.noteStore,
|
|
349
|
+
keyStore: this.keyStore,
|
|
350
|
+
addressStore: this.addressStore,
|
|
351
|
+
aztecNode: this.stateMachine.node,
|
|
352
|
+
senderTaggingStore: this.senderTaggingStore,
|
|
353
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
354
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
355
|
+
capsuleStore: this.capsuleStore,
|
|
356
|
+
privateEventStore: this.privateEventStore,
|
|
357
|
+
contractSyncService: this.stateMachine.contractSyncService,
|
|
358
|
+
jobId: this.currentJobId,
|
|
359
|
+
scopes: 'ALL_SCOPES',
|
|
360
|
+
});
|
|
365
361
|
|
|
366
362
|
// We store the note and tagging index caches fed into the PrivateExecutionOracle (along with some other auxiliary
|
|
367
363
|
// data) in order to refer to it later, mimicking the way this object is used by the ContractFunctionSimulator. The
|
|
@@ -401,6 +397,8 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
401
397
|
async enterUtilityState(contractAddress: AztecAddress = DEFAULT_ADDRESS) {
|
|
402
398
|
this.exitTopLevelState();
|
|
403
399
|
|
|
400
|
+
const anchorBlockHeader = await this.stateMachine.anchorBlockStore.getBlockHeader();
|
|
401
|
+
|
|
404
402
|
// There is no automatic message discovery and contract-driven syncing process in inlined private or utility
|
|
405
403
|
// contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
|
|
406
404
|
// we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
|
|
@@ -409,29 +407,27 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
409
407
|
await new NoteService(
|
|
410
408
|
this.noteStore,
|
|
411
409
|
this.stateMachine.node,
|
|
412
|
-
|
|
410
|
+
anchorBlockHeader,
|
|
413
411
|
this.currentJobId,
|
|
414
|
-
).syncNoteNullifiers(contractAddress);
|
|
412
|
+
).syncNoteNullifiers(contractAddress, 'ALL_SCOPES');
|
|
415
413
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
this.oracleHandler = new UtilityExecutionOracle(
|
|
414
|
+
this.oracleHandler = new UtilityExecutionOracle({
|
|
419
415
|
contractAddress,
|
|
420
|
-
[],
|
|
421
|
-
[],
|
|
416
|
+
authWitnesses: [],
|
|
417
|
+
capsules: [],
|
|
422
418
|
anchorBlockHeader,
|
|
423
|
-
this.contractStore,
|
|
424
|
-
this.noteStore,
|
|
425
|
-
this.keyStore,
|
|
426
|
-
this.addressStore,
|
|
427
|
-
this.stateMachine.node,
|
|
428
|
-
this.
|
|
429
|
-
this.
|
|
430
|
-
this.
|
|
431
|
-
this.
|
|
432
|
-
this.
|
|
433
|
-
|
|
434
|
-
);
|
|
419
|
+
contractStore: this.contractStore,
|
|
420
|
+
noteStore: this.noteStore,
|
|
421
|
+
keyStore: this.keyStore,
|
|
422
|
+
addressStore: this.addressStore,
|
|
423
|
+
aztecNode: this.stateMachine.node,
|
|
424
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
425
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
426
|
+
capsuleStore: this.capsuleStore,
|
|
427
|
+
privateEventStore: this.privateEventStore,
|
|
428
|
+
jobId: this.currentJobId,
|
|
429
|
+
scopes: 'ALL_SCOPES',
|
|
430
|
+
});
|
|
435
431
|
|
|
436
432
|
this.state = { name: 'UTILITY' };
|
|
437
433
|
this.logger.debug(`Entered state ${this.state.name}`);
|
|
@@ -499,30 +495,30 @@ export class TXESession implements TXESessionStateHandler {
|
|
|
499
495
|
}
|
|
500
496
|
|
|
501
497
|
private utilityExecutorForContractSync(anchorBlock: any) {
|
|
502
|
-
return async (call: FunctionCall) => {
|
|
498
|
+
return async (call: FunctionCall, scopes: AccessScopes) => {
|
|
503
499
|
const entryPointArtifact = await this.contractStore.getFunctionArtifactWithDebugMetadata(call.to, call.selector);
|
|
504
500
|
if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
|
|
505
501
|
throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
|
|
506
502
|
}
|
|
507
503
|
|
|
508
504
|
try {
|
|
509
|
-
const oracle = new UtilityExecutionOracle(
|
|
510
|
-
call.to,
|
|
511
|
-
[],
|
|
512
|
-
[],
|
|
513
|
-
anchorBlock!,
|
|
514
|
-
this.contractStore,
|
|
515
|
-
this.noteStore,
|
|
516
|
-
this.keyStore,
|
|
517
|
-
this.addressStore,
|
|
518
|
-
this.stateMachine.node,
|
|
519
|
-
this.
|
|
520
|
-
this.
|
|
521
|
-
this.
|
|
522
|
-
this.
|
|
523
|
-
this.
|
|
524
|
-
|
|
525
|
-
);
|
|
505
|
+
const oracle = new UtilityExecutionOracle({
|
|
506
|
+
contractAddress: call.to,
|
|
507
|
+
authWitnesses: [],
|
|
508
|
+
capsules: [],
|
|
509
|
+
anchorBlockHeader: anchorBlock!,
|
|
510
|
+
contractStore: this.contractStore,
|
|
511
|
+
noteStore: this.noteStore,
|
|
512
|
+
keyStore: this.keyStore,
|
|
513
|
+
addressStore: this.addressStore,
|
|
514
|
+
aztecNode: this.stateMachine.node,
|
|
515
|
+
recipientTaggingStore: this.recipientTaggingStore,
|
|
516
|
+
senderAddressBookStore: this.senderAddressBookStore,
|
|
517
|
+
capsuleStore: this.capsuleStore,
|
|
518
|
+
privateEventStore: this.privateEventStore,
|
|
519
|
+
jobId: this.currentJobId,
|
|
520
|
+
scopes,
|
|
521
|
+
});
|
|
526
522
|
await new WASMSimulator()
|
|
527
523
|
.executeUserCircuit(toACVMWitness(0, call.args), entryPointArtifact, new Oracle(oracle).toACIRCallback())
|
|
528
524
|
.catch((err: Error) => {
|