@aztec/txe 0.0.0-test.0 → 0.0.1-commit.03f7ef2
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.d.ts +1 -1
- package/dest/bin/index.js +3 -2
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +81 -51
- package/dest/oracle/interfaces.d.ts +57 -0
- package/dest/oracle/interfaces.d.ts.map +1 -0
- package/dest/oracle/interfaces.js +3 -0
- package/dest/oracle/txe_oracle_public_context.d.ts +34 -0
- package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_public_context.js +122 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts +63 -0
- package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -0
- package/dest/oracle/txe_oracle_top_level_context.js +453 -0
- package/dest/rpc_translator.d.ts +246 -0
- package/dest/rpc_translator.d.ts.map +1 -0
- package/dest/rpc_translator.js +666 -0
- package/dest/state_machine/archiver.d.ts +78 -0
- package/dest/state_machine/archiver.d.ts.map +1 -0
- package/dest/state_machine/archiver.js +206 -0
- package/dest/state_machine/dummy_p2p_client.d.ts +54 -0
- package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -0
- package/dest/state_machine/dummy_p2p_client.js +138 -0
- package/dest/state_machine/global_variable_builder.d.ts +11 -0
- package/dest/state_machine/global_variable_builder.d.ts.map +1 -0
- package/dest/state_machine/global_variable_builder.js +22 -0
- package/dest/state_machine/index.d.ts +16 -0
- package/dest/state_machine/index.d.ts.map +1 -0
- package/dest/state_machine/index.js +45 -0
- package/dest/state_machine/mock_epoch_cache.d.ts +26 -0
- package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -0
- package/dest/state_machine/mock_epoch_cache.js +51 -0
- package/dest/state_machine/synchronizer.d.ts +33 -0
- package/dest/state_machine/synchronizer.d.ts.map +1 -0
- package/dest/state_machine/synchronizer.js +59 -0
- package/dest/txe_session.d.ts +72 -0
- package/dest/txe_session.d.ts.map +1 -0
- package/dest/txe_session.js +264 -0
- package/dest/util/encoding.d.ts +647 -30
- package/dest/util/encoding.d.ts.map +1 -1
- package/dest/util/encoding.js +66 -11
- package/dest/util/expected_failure_error.d.ts +1 -1
- package/dest/util/expected_failure_error.d.ts.map +1 -1
- package/dest/util/txe_account_data_provider.d.ts +1 -1
- package/dest/util/txe_account_data_provider.d.ts.map +1 -1
- package/dest/util/txe_contract_data_provider.d.ts +12 -0
- package/dest/util/txe_contract_data_provider.d.ts.map +1 -0
- package/dest/util/txe_contract_data_provider.js +22 -0
- package/dest/util/txe_public_contract_data_source.d.ts +12 -11
- package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
- package/dest/util/txe_public_contract_data_source.js +37 -58
- package/dest/utils/block_creation.d.ts +28 -0
- package/dest/utils/block_creation.d.ts.map +1 -0
- package/dest/utils/block_creation.js +45 -0
- package/dest/utils/tx_effect_creation.d.ts +6 -0
- package/dest/utils/tx_effect_creation.d.ts.map +1 -0
- package/dest/utils/tx_effect_creation.js +16 -0
- package/package.json +30 -24
- package/src/bin/index.ts +3 -2
- package/src/index.ts +105 -74
- package/src/oracle/interfaces.ts +86 -0
- package/src/oracle/txe_oracle_public_context.ts +160 -0
- package/src/oracle/txe_oracle_top_level_context.ts +696 -0
- package/src/rpc_translator.ts +1083 -0
- package/src/state_machine/archiver.ts +263 -0
- package/src/state_machine/dummy_p2p_client.ts +204 -0
- package/src/state_machine/global_variable_builder.ts +38 -0
- package/src/state_machine/index.ts +78 -0
- package/src/state_machine/mock_epoch_cache.ts +68 -0
- package/src/state_machine/synchronizer.ts +88 -0
- package/src/txe_session.ts +466 -0
- package/src/util/encoding.ts +85 -11
- package/src/util/txe_contract_data_provider.ts +36 -0
- package/src/util/txe_public_contract_data_source.ts +43 -58
- package/src/utils/block_creation.ts +94 -0
- package/src/utils/tx_effect_creation.ts +38 -0
- package/dest/node/txe_node.d.ts +0 -358
- package/dest/node/txe_node.d.ts.map +0 -1
- package/dest/node/txe_node.js +0 -504
- package/dest/oracle/txe_oracle.d.ts +0 -152
- package/dest/oracle/txe_oracle.d.ts.map +0 -1
- package/dest/oracle/txe_oracle.js +0 -833
- package/dest/txe_service/txe_service.d.ts +0 -212
- package/dest/txe_service/txe_service.d.ts.map +0 -1
- package/dest/txe_service/txe_service.js +0 -572
- package/dest/util/txe_world_state_db.d.ts +0 -14
- package/dest/util/txe_world_state_db.d.ts.map +0 -1
- package/dest/util/txe_world_state_db.js +0 -27
- package/src/node/txe_node.ts +0 -725
- package/src/oracle/txe_oracle.ts +0 -1241
- package/src/txe_service/txe_service.ts +0 -749
- package/src/util/txe_world_state_db.ts +0 -38
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { ArchiverStoreHelper, KVArchiverDataStore } from '@aztec/archiver';
|
|
2
|
+
import { GENESIS_ARCHIVE_ROOT } from '@aztec/constants';
|
|
3
|
+
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
4
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
|
+
import { isDefined } from '@aztec/foundation/types';
|
|
7
|
+
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
8
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
9
|
+
import {
|
|
10
|
+
CommitteeAttestation,
|
|
11
|
+
L2Block,
|
|
12
|
+
type L2BlockId,
|
|
13
|
+
type L2BlockNew,
|
|
14
|
+
type L2BlockSource,
|
|
15
|
+
type L2Tips,
|
|
16
|
+
PublishedL2Block,
|
|
17
|
+
type ValidateBlockResult,
|
|
18
|
+
} from '@aztec/stdlib/block';
|
|
19
|
+
import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
20
|
+
import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
21
|
+
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
22
|
+
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
23
|
+
import type { UInt64 } from '@aztec/stdlib/types';
|
|
24
|
+
|
|
25
|
+
// We are extending the ArchiverDataStoreHelper here because it provides most of the endpoints needed by the
|
|
26
|
+
// node for reading from and writing to state, without needing any of the extra overhead that the Archiver itself
|
|
27
|
+
// requires (i.e. an L1 client)
|
|
28
|
+
export class TXEArchiver extends ArchiverStoreHelper implements L2BlockSource {
|
|
29
|
+
constructor(db: AztecAsyncKVStore) {
|
|
30
|
+
super(new KVArchiverDataStore(db, 9999));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
|
|
34
|
+
if (number === 0) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const publishedBlocks = await this.getPublishedBlocks(number, 1);
|
|
38
|
+
if (publishedBlocks.length === 0) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
return publishedBlocks[0].block;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public async getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
|
|
45
|
+
const publishedBlocks = await this.getPublishedBlocks(from, limit, proven);
|
|
46
|
+
return publishedBlocks.map(x => x.block);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public override async addCheckpoints(
|
|
50
|
+
checkpoints: PublishedCheckpoint[],
|
|
51
|
+
_result?: ValidateBlockResult,
|
|
52
|
+
): Promise<boolean> {
|
|
53
|
+
const allBlocks = checkpoints.flatMap(ch => ch.checkpoint.blocks);
|
|
54
|
+
const opResults = await Promise.all([this.store.addLogs(allBlocks), this.store.addCheckpoints(checkpoints)]);
|
|
55
|
+
|
|
56
|
+
return opResults.every(Boolean);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gets the number of the latest L2 block processed by the block source implementation.
|
|
61
|
+
* @returns The number of the latest L2 block processed by the block source implementation.
|
|
62
|
+
*/
|
|
63
|
+
public getBlockNumber(): Promise<BlockNumber> {
|
|
64
|
+
return this.store.getLatestBlockNumber();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Gets the number of the latest L2 block proven seen by the block source implementation.
|
|
69
|
+
* @returns The number of the latest L2 block proven seen by the block source implementation.
|
|
70
|
+
*/
|
|
71
|
+
public override getProvenBlockNumber(): Promise<BlockNumber> {
|
|
72
|
+
return this.store.getProvenBlockNumber();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Gets a published l2 block. If a negative number is passed, the block returned is the most recent.
|
|
77
|
+
* @param number - The block number to return (inclusive).
|
|
78
|
+
* @returns The requested L2 block.
|
|
79
|
+
*/
|
|
80
|
+
public async getPublishedBlock(number: number): Promise<PublishedL2Block | undefined> {
|
|
81
|
+
// If the number provided is -ve, then return the latest block.
|
|
82
|
+
if (number < 0) {
|
|
83
|
+
number = await this.store.getLatestBlockNumber();
|
|
84
|
+
}
|
|
85
|
+
if (number == 0) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
const publishedBlocks = await this.retrievePublishedBlocks(BlockNumber(number), 1);
|
|
89
|
+
return publishedBlocks.length === 0 ? undefined : publishedBlocks[0];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
|
|
93
|
+
return this.retrievePublishedBlocks(from, limit, proven);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private async retrievePublishedBlocks(
|
|
97
|
+
from: BlockNumber,
|
|
98
|
+
limit: number,
|
|
99
|
+
proven?: boolean,
|
|
100
|
+
): Promise<PublishedL2Block[]> {
|
|
101
|
+
const checkpoints = await this.store.getRangeOfCheckpoints(CheckpointNumber(from), limit);
|
|
102
|
+
const provenCheckpointNumber = await this.store.getProvenCheckpointNumber();
|
|
103
|
+
const blocks = (
|
|
104
|
+
await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
|
|
105
|
+
).filter(isDefined);
|
|
106
|
+
|
|
107
|
+
const olbBlocks: PublishedL2Block[] = [];
|
|
108
|
+
for (let i = 0; i < checkpoints.length; i++) {
|
|
109
|
+
const blockForCheckpoint = blocks[i][0];
|
|
110
|
+
const checkpoint = checkpoints[i];
|
|
111
|
+
if (proven === true && checkpoint.checkpointNumber > provenCheckpointNumber) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const oldCheckpoint = new Checkpoint(
|
|
115
|
+
blockForCheckpoint.archive,
|
|
116
|
+
checkpoint.header,
|
|
117
|
+
[blockForCheckpoint],
|
|
118
|
+
checkpoint.checkpointNumber,
|
|
119
|
+
);
|
|
120
|
+
const oldBlock = L2Block.fromCheckpoint(oldCheckpoint);
|
|
121
|
+
const publishedBlock = new PublishedL2Block(
|
|
122
|
+
oldBlock,
|
|
123
|
+
checkpoint.l1,
|
|
124
|
+
checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
|
|
125
|
+
);
|
|
126
|
+
olbBlocks.push(publishedBlock);
|
|
127
|
+
}
|
|
128
|
+
return olbBlocks;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Gets an l2 block. If a negative number is passed, the block returned is the most recent.
|
|
133
|
+
* @param number - The block number to return (inclusive).
|
|
134
|
+
* @returns The requested L2 block.
|
|
135
|
+
*/
|
|
136
|
+
public getL2Block(number: BlockNumber | 'latest'): Promise<L2Block | undefined> {
|
|
137
|
+
return this.getPublishedBlock(number != 'latest' ? number : -1).then(b => b?.block);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Gets an L2 block (new format).
|
|
142
|
+
* @param number - The block number to return.
|
|
143
|
+
* @returns The requested L2 block.
|
|
144
|
+
*/
|
|
145
|
+
public getL2BlockNew(number: BlockNumber): Promise<L2BlockNew | undefined> {
|
|
146
|
+
if (number === 0) {
|
|
147
|
+
return Promise.resolve(undefined);
|
|
148
|
+
}
|
|
149
|
+
return this.store.getBlock(number);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Gets an l2 block header.
|
|
154
|
+
* @param number - The block number to return or 'latest' for the most recent one.
|
|
155
|
+
* @returns The requested L2 block header.
|
|
156
|
+
*/
|
|
157
|
+
public async getBlockHeader(number: number | 'latest'): Promise<BlockHeader | undefined> {
|
|
158
|
+
if (number === 'latest') {
|
|
159
|
+
number = await this.store.getLatestBlockNumber();
|
|
160
|
+
}
|
|
161
|
+
if (number === 0) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
const headers = await this.store.getBlockHeaders(BlockNumber(number), 1);
|
|
165
|
+
return headers.length === 0 ? undefined : headers[0];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public getBlockRange(from: number, limit: number, _proven?: boolean): Promise<L2Block[]> {
|
|
169
|
+
return this.getPublishedBlocks(BlockNumber(from), limit).then(blocks => blocks.map(b => b.block));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public getPublishedCheckpoints(_from: CheckpointNumber, _limit: number): Promise<PublishedCheckpoint[]> {
|
|
173
|
+
throw new Error('TXE Archiver does not implement "getPublishedCheckpoints"');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public getCheckpointByArchive(_archive: Fr): Promise<Checkpoint | undefined> {
|
|
177
|
+
throw new Error('TXE Archiver does not implement "getCheckpointByArchive"');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public getL2SlotNumber(): Promise<SlotNumber | undefined> {
|
|
181
|
+
throw new Error('TXE Archiver does not implement "getL2SlotNumber"');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public getL2EpochNumber(): Promise<EpochNumber> {
|
|
185
|
+
throw new Error('TXE Archiver does not implement "getL2EpochNumber"');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public getCheckpointsForEpoch(_epochNumber: EpochNumber): Promise<Checkpoint[]> {
|
|
189
|
+
throw new Error('TXE Archiver does not implement "getCheckpointsForEpoch"');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public getBlocksForEpoch(_epochNumber: EpochNumber): Promise<L2Block[]> {
|
|
193
|
+
throw new Error('TXE Archiver does not implement "getBlocksForEpoch"');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
public getBlockHeadersForEpoch(_epochNumber: EpochNumber): Promise<BlockHeader[]> {
|
|
197
|
+
throw new Error('TXE Archiver does not implement "getBlockHeadersForEpoch"');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public isEpochComplete(_epochNumber: EpochNumber): Promise<boolean> {
|
|
201
|
+
throw new Error('TXE Archiver does not implement "isEpochComplete"');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public async getL2Tips(): Promise<L2Tips> {
|
|
205
|
+
// In TXE there is no possibility of reorgs and no blocks are ever getting proven so we just set 'latest', 'proven'
|
|
206
|
+
// and 'finalized' to the latest block.
|
|
207
|
+
const blockHeader = await this.getBlockHeader('latest');
|
|
208
|
+
if (!blockHeader) {
|
|
209
|
+
throw new Error('L2Tips requested from TXE Archiver but no block header found');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const number = blockHeader.globalVariables.blockNumber;
|
|
213
|
+
const hash = (await blockHeader.hash()).toString();
|
|
214
|
+
return {
|
|
215
|
+
latest: { number, hash } as L2BlockId,
|
|
216
|
+
proven: { number, hash } as L2BlockId,
|
|
217
|
+
finalized: { number, hash } as L2BlockId,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public getL1Constants(): Promise<L1RollupConstants> {
|
|
222
|
+
throw new Error('TXE Archiver does not implement "getL2Constants"');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
public getGenesisValues(): Promise<{ genesisArchiveRoot: Fr }> {
|
|
226
|
+
return Promise.resolve({ genesisArchiveRoot: new Fr(GENESIS_ARCHIVE_ROOT) });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public syncImmediate(): Promise<void> {
|
|
230
|
+
throw new Error('TXE Archiver does not implement "syncImmediate"');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public getContract(_address: AztecAddress, _timestamp?: UInt64): Promise<ContractInstanceWithAddress | undefined> {
|
|
234
|
+
throw new Error('TXE Archiver does not implement "getContract"');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
public getRollupAddress(): Promise<EthAddress> {
|
|
238
|
+
throw new Error('TXE Archiver does not implement "getRollupAddress"');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
public getRegistryAddress(): Promise<EthAddress> {
|
|
242
|
+
throw new Error('TXE Archiver does not implement "getRegistryAddress"');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public getL1Timestamp(): Promise<bigint> {
|
|
246
|
+
throw new Error('TXE Archiver does not implement "getL1Timestamp"');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
public isPendingChainInvalid(): Promise<boolean> {
|
|
250
|
+
return Promise.resolve(false);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public override getPendingChainValidationStatus(): Promise<ValidateBlockResult> {
|
|
254
|
+
return Promise.resolve({ valid: true });
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
getPublishedBlockByHash(_blockHash: Fr): Promise<PublishedL2Block | undefined> {
|
|
258
|
+
throw new Error('Method not implemented.');
|
|
259
|
+
}
|
|
260
|
+
getPublishedBlockByArchive(_archive: Fr): Promise<PublishedL2Block | undefined> {
|
|
261
|
+
throw new Error('Method not implemented.');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import type {
|
|
3
|
+
AuthRequest,
|
|
4
|
+
ENR,
|
|
5
|
+
P2P,
|
|
6
|
+
P2PBlockReceivedCallback,
|
|
7
|
+
P2PConfig,
|
|
8
|
+
P2PSyncState,
|
|
9
|
+
PeerId,
|
|
10
|
+
ReqRespSubProtocol,
|
|
11
|
+
ReqRespSubProtocolHandler,
|
|
12
|
+
ReqRespSubProtocolValidators,
|
|
13
|
+
StatusMessage,
|
|
14
|
+
} from '@aztec/p2p';
|
|
15
|
+
import type { EthAddress, L2BlockStreamEvent, L2Tips } from '@aztec/stdlib/block';
|
|
16
|
+
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
17
|
+
import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
18
|
+
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
19
|
+
|
|
20
|
+
export class DummyP2P implements P2P {
|
|
21
|
+
public broadcastAttestations(_attestations: BlockAttestation[]): Promise<void> {
|
|
22
|
+
return Promise.resolve();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public validate(_txs: Tx[]): Promise<void> {
|
|
26
|
+
return Promise.resolve();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public clear(): Promise<void> {
|
|
30
|
+
throw new Error('DummyP2P does not implement "clear".');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public getPendingTxs(): Promise<Tx[]> {
|
|
34
|
+
throw new Error('DummyP2P does not implement "getPendingTxs"');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public getEncodedEnr(): Promise<string | undefined> {
|
|
38
|
+
throw new Error('DummyP2P does not implement "getEncodedEnr"');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public getPeers(_includePending?: boolean): Promise<PeerInfo[]> {
|
|
42
|
+
throw new Error('DummyP2P does not implement "getPeers"');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public broadcastProposal(_proposal: BlockProposal): Promise<void> {
|
|
46
|
+
throw new Error('DummyP2P does not implement "broadcastProposal"');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public registerBlockProposalHandler(_handler: P2PBlockReceivedCallback): void {
|
|
50
|
+
throw new Error('DummyP2P does not implement "registerBlockProposalHandler"');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public requestTxs(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
54
|
+
throw new Error('DummyP2P does not implement "requestTxs"');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public requestTxByHash(_txHash: TxHash): Promise<Tx | undefined> {
|
|
58
|
+
throw new Error('DummyP2P does not implement "requestTxByHash"');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public sendTx(_tx: Tx): Promise<void> {
|
|
62
|
+
throw new Error('DummyP2P does not implement "sendTx"');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public deleteTxs(_txHashes: TxHash[]): Promise<void> {
|
|
66
|
+
throw new Error('DummyP2P does not implement "deleteTxs"');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public getTxByHashFromPool(_txHash: TxHash): Promise<Tx | undefined> {
|
|
70
|
+
throw new Error('DummyP2P does not implement "getTxByHashFromPool"');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public getTxByHash(_txHash: TxHash): Promise<Tx | undefined> {
|
|
74
|
+
throw new Error('DummyP2P does not implement "getTxByHash"');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public getArchivedTxByHash(_txHash: TxHash): Promise<Tx | undefined> {
|
|
78
|
+
throw new Error('DummyP2P does not implement "getArchivedTxByHash"');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public getTxStatus(_txHash: TxHash): Promise<'pending' | 'mined' | undefined> {
|
|
82
|
+
// In TXE there is no concept of transactions but we need to implement this because of tagging. We return 'mined'
|
|
83
|
+
// tx status for any tx hash.
|
|
84
|
+
return Promise.resolve('mined');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public iteratePendingTxs(): AsyncIterableIterator<Tx> {
|
|
88
|
+
throw new Error('DummyP2P does not implement "iteratePendingTxs"');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public getPendingTxCount(): Promise<number> {
|
|
92
|
+
throw new Error('DummyP2P does not implement "getPendingTxCount"');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public start(): Promise<void> {
|
|
96
|
+
throw new Error('DummyP2P does not implement "start"');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public stop(): Promise<void> {
|
|
100
|
+
throw new Error('DummyP2P does not implement "stop"');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public isReady(): boolean {
|
|
104
|
+
throw new Error('DummyP2P does not implement "isReady"');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public getStatus(): Promise<P2PSyncState> {
|
|
108
|
+
throw new Error('DummyP2P does not implement "getStatus"');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public getEnr(): ENR | undefined {
|
|
112
|
+
throw new Error('DummyP2P does not implement "getEnr"');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public isP2PClient(): true {
|
|
116
|
+
throw new Error('DummyP2P does not implement "isP2PClient"');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public getTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
|
|
120
|
+
throw new Error('DummyP2P does not implement "getTxsByHash"');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public getAttestationsForSlot(_slot: SlotNumber, _proposalId?: string): Promise<BlockAttestation[]> {
|
|
124
|
+
throw new Error('DummyP2P does not implement "getAttestationForSlot"');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public deleteAttestation(_attestation: BlockAttestation): Promise<void> {
|
|
128
|
+
return Promise.resolve();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public addAttestations(_attestations: BlockAttestation[]): Promise<void> {
|
|
132
|
+
throw new Error('DummyP2P does not implement "addAttestations"');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public getL2BlockHash(_number: number): Promise<string | undefined> {
|
|
136
|
+
throw new Error('DummyP2P does not implement "getL2BlockHash"');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
public updateP2PConfig(_config: Partial<P2PConfig>): Promise<void> {
|
|
140
|
+
throw new Error('DummyP2P does not implement "updateP2PConfig"');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public getL2Tips(): Promise<L2Tips> {
|
|
144
|
+
throw new Error('DummyP2P does not implement "getL2Tips"');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public handleBlockStreamEvent(_event: L2BlockStreamEvent): Promise<void> {
|
|
148
|
+
throw new Error('DummyP2P does not implement "handleBlockStreamEvent"');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public sync() {
|
|
152
|
+
throw new Error('DummyP2P does not implement "sync"');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public requestTxsByHash(_txHashes: TxHash[]): Promise<Tx[]> {
|
|
156
|
+
throw new Error('DummyP2P does not implement "requestTxsByHash"');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public getTxs(_filter: 'all' | 'pending' | 'mined'): Promise<Tx[]> {
|
|
160
|
+
throw new Error('DummyP2P does not implement "getTxs"');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public getTxsByHashFromPool(_txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
164
|
+
throw new Error('DummyP2P does not implement "getTxsByHashFromPool"');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public hasTxsInPool(_txHashes: TxHash[]): Promise<boolean[]> {
|
|
168
|
+
throw new Error('DummyP2P does not implement "hasTxsInPool"');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public addTxsToPool(_txs: Tx[]): Promise<number> {
|
|
172
|
+
throw new Error('DummyP2P does not implement "addTxs"');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
public getSyncedLatestBlockNum(): Promise<number> {
|
|
176
|
+
throw new Error('DummyP2P does not implement "getSyncedLatestBlockNum"');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public getSyncedProvenBlockNum(): Promise<number> {
|
|
180
|
+
throw new Error('DummyP2P does not implement "getSyncedProvenBlockNum"');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public getSyncedLatestSlot(): Promise<bigint> {
|
|
184
|
+
throw new Error('DummyP2P does not implement "getSyncedLatestSlot"');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
markTxsAsNonEvictable(_: TxHash[]): Promise<void> {
|
|
188
|
+
throw new Error('DummyP2P does not implement "markTxsAsNonEvictable".');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
addReqRespSubProtocol(
|
|
192
|
+
_subProtocol: ReqRespSubProtocol,
|
|
193
|
+
_handler: ReqRespSubProtocolHandler,
|
|
194
|
+
_validator?: ReqRespSubProtocolValidators[ReqRespSubProtocol],
|
|
195
|
+
): Promise<void> {
|
|
196
|
+
throw new Error('DummyP2P does not implement "addReqRespSubProtocol".');
|
|
197
|
+
}
|
|
198
|
+
handleAuthRequestFromPeer(_authRequest: AuthRequest, _peerId: PeerId): Promise<StatusMessage> {
|
|
199
|
+
throw new Error('DummyP2P does not implement "handleAuthRequestFromPeer".');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//This is no-op
|
|
203
|
+
public registerThisValidatorAddresses(_address: EthAddress[]): void {}
|
|
204
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
|
+
import { GasFees } from '@aztec/stdlib/gas';
|
|
5
|
+
import { makeGlobalVariables } from '@aztec/stdlib/testing';
|
|
6
|
+
import { type CheckpointGlobalVariables, type GlobalVariableBuilder, GlobalVariables } from '@aztec/stdlib/tx';
|
|
7
|
+
|
|
8
|
+
export class TXEGlobalVariablesBuilder implements GlobalVariableBuilder {
|
|
9
|
+
public getCurrentBaseFees(): Promise<GasFees> {
|
|
10
|
+
return Promise.resolve(new GasFees(0, 0));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public buildGlobalVariables(
|
|
14
|
+
_blockNumber: BlockNumber,
|
|
15
|
+
_coinbase: EthAddress,
|
|
16
|
+
_feeRecipient: AztecAddress,
|
|
17
|
+
_slotNumber?: SlotNumber,
|
|
18
|
+
): Promise<GlobalVariables> {
|
|
19
|
+
return Promise.resolve(makeGlobalVariables());
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public buildCheckpointGlobalVariables(
|
|
23
|
+
_coinbase: EthAddress,
|
|
24
|
+
_feeRecipient: AztecAddress,
|
|
25
|
+
_slotNumber: SlotNumber,
|
|
26
|
+
): Promise<CheckpointGlobalVariables> {
|
|
27
|
+
const vars = makeGlobalVariables();
|
|
28
|
+
return Promise.resolve({
|
|
29
|
+
chainId: vars.chainId,
|
|
30
|
+
version: vars.version,
|
|
31
|
+
slotNumber: vars.slotNumber,
|
|
32
|
+
timestamp: vars.timestamp,
|
|
33
|
+
coinbase: vars.coinbase,
|
|
34
|
+
feeRecipient: vars.feeRecipient,
|
|
35
|
+
gasFees: vars.gasFees,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
|
|
2
|
+
import { TestCircuitVerifier } from '@aztec/bb-prover/test';
|
|
3
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
5
|
+
import { AnchorBlockDataProvider } from '@aztec/pxe/server';
|
|
6
|
+
import { L2Block } from '@aztec/stdlib/block';
|
|
7
|
+
import { L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
8
|
+
import type { AztecNode } from '@aztec/stdlib/interfaces/client';
|
|
9
|
+
import { getPackageVersion } from '@aztec/stdlib/update-checker';
|
|
10
|
+
|
|
11
|
+
import { TXEArchiver } from './archiver.js';
|
|
12
|
+
import { DummyP2P } from './dummy_p2p_client.js';
|
|
13
|
+
import { TXEGlobalVariablesBuilder } from './global_variable_builder.js';
|
|
14
|
+
import { MockEpochCache } from './mock_epoch_cache.js';
|
|
15
|
+
import { TXESynchronizer } from './synchronizer.js';
|
|
16
|
+
|
|
17
|
+
const VERSION = 1;
|
|
18
|
+
const CHAIN_ID = 1;
|
|
19
|
+
|
|
20
|
+
export class TXEStateMachine {
|
|
21
|
+
constructor(
|
|
22
|
+
public node: AztecNode,
|
|
23
|
+
public synchronizer: TXESynchronizer,
|
|
24
|
+
public archiver: TXEArchiver,
|
|
25
|
+
public anchorBlockDataProvider: AnchorBlockDataProvider,
|
|
26
|
+
) {}
|
|
27
|
+
|
|
28
|
+
public static async create(db: AztecAsyncKVStore) {
|
|
29
|
+
const archiver = new TXEArchiver(db);
|
|
30
|
+
const synchronizer = await TXESynchronizer.create();
|
|
31
|
+
const anchorBlockDataProvider = new AnchorBlockDataProvider(db);
|
|
32
|
+
|
|
33
|
+
const aztecNodeConfig = {} as AztecNodeConfig;
|
|
34
|
+
|
|
35
|
+
const log = createLogger('txe_node');
|
|
36
|
+
const node = new AztecNodeService(
|
|
37
|
+
aztecNodeConfig,
|
|
38
|
+
new DummyP2P(),
|
|
39
|
+
archiver,
|
|
40
|
+
archiver,
|
|
41
|
+
archiver,
|
|
42
|
+
archiver,
|
|
43
|
+
synchronizer,
|
|
44
|
+
undefined,
|
|
45
|
+
undefined,
|
|
46
|
+
undefined,
|
|
47
|
+
undefined,
|
|
48
|
+
VERSION,
|
|
49
|
+
CHAIN_ID,
|
|
50
|
+
new TXEGlobalVariablesBuilder(),
|
|
51
|
+
new MockEpochCache(),
|
|
52
|
+
getPackageVersion() ?? '',
|
|
53
|
+
new TestCircuitVerifier(),
|
|
54
|
+
undefined,
|
|
55
|
+
log,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return new this(node, synchronizer, archiver, anchorBlockDataProvider);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async handleL2Block(block: L2Block) {
|
|
62
|
+
const checkpoint = block.toCheckpoint();
|
|
63
|
+
const publishedCheckpoint = new PublishedCheckpoint(
|
|
64
|
+
checkpoint,
|
|
65
|
+
new L1PublishedData(
|
|
66
|
+
BigInt(block.header.globalVariables.blockNumber),
|
|
67
|
+
block.header.globalVariables.timestamp,
|
|
68
|
+
block.header.globalVariables.blockNumber.toString(),
|
|
69
|
+
),
|
|
70
|
+
[],
|
|
71
|
+
);
|
|
72
|
+
await Promise.all([
|
|
73
|
+
this.synchronizer.handleL2Block(block.toL2Block()),
|
|
74
|
+
this.archiver.addCheckpoints([publishedCheckpoint], undefined),
|
|
75
|
+
this.anchorBlockDataProvider.setHeader(block.getBlockHeader()),
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '@aztec/epoch-cache';
|
|
2
|
+
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mock implementation of the EpochCacheInterface used to satisfy dependencies of AztecNodeService.
|
|
7
|
+
* Since in TXE we don't validate transactions, mock suffices here.
|
|
8
|
+
*/
|
|
9
|
+
export class MockEpochCache implements EpochCacheInterface {
|
|
10
|
+
getCommittee(): Promise<EpochCommitteeInfo> {
|
|
11
|
+
return Promise.resolve({
|
|
12
|
+
committee: undefined,
|
|
13
|
+
seed: 0n,
|
|
14
|
+
epoch: EpochNumber.ZERO,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getEpochAndSlotNow(): EpochAndSlot {
|
|
19
|
+
return {
|
|
20
|
+
epoch: EpochNumber.ZERO,
|
|
21
|
+
slot: SlotNumber(0),
|
|
22
|
+
ts: 0n,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint } {
|
|
27
|
+
return {
|
|
28
|
+
epoch: EpochNumber.ZERO,
|
|
29
|
+
slot: SlotNumber(0),
|
|
30
|
+
ts: 0n,
|
|
31
|
+
now: 0n,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getProposerIndexEncoding(_epoch: EpochNumber, _slot: SlotNumber, _seed: bigint): `0x${string}` {
|
|
36
|
+
return '0x00';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
computeProposerIndex(_slot: SlotNumber, _epoch: EpochNumber, _seed: bigint, _size: bigint): bigint {
|
|
40
|
+
return 0n;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getProposerAttesterAddressInCurrentOrNextSlot(): Promise<{
|
|
44
|
+
currentProposer: EthAddress | undefined;
|
|
45
|
+
nextProposer: EthAddress | undefined;
|
|
46
|
+
currentSlot: SlotNumber;
|
|
47
|
+
nextSlot: SlotNumber;
|
|
48
|
+
}> {
|
|
49
|
+
return Promise.resolve({
|
|
50
|
+
currentProposer: undefined,
|
|
51
|
+
nextProposer: undefined,
|
|
52
|
+
currentSlot: SlotNumber(0),
|
|
53
|
+
nextSlot: SlotNumber(0),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
isInCommittee(_slot: SlotTag, _validator: EthAddress): Promise<boolean> {
|
|
58
|
+
return Promise.resolve(false);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
getRegisteredValidators(): Promise<EthAddress[]> {
|
|
62
|
+
return Promise.resolve([]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
filterInCommittee(_slot: SlotTag, _validators: EthAddress[]): Promise<EthAddress[]> {
|
|
66
|
+
return Promise.resolve([]);
|
|
67
|
+
}
|
|
68
|
+
}
|