@aztec/p2p 0.0.1-commit.b2a5d0dd1 → 0.0.1-commit.b3d3157a
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/bootstrap/bootstrap.d.ts +1 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +9 -1
- package/dest/client/factory.d.ts +3 -3
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +12 -9
- package/dest/client/interface.d.ts +6 -4
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +11 -8
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +53 -17
- package/dest/config.d.ts +43 -17
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +48 -8
- package/dest/errors/reqresp.error.d.ts +1 -20
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +0 -21
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +93 -55
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +258 -195
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +175 -59
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +6 -4
- package/dest/mem_pools/instrumentation.d.ts +1 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +17 -1
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -5
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +1 -7
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +73 -83
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +5 -2
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +18 -2
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +3 -4
- package/dest/msg_validators/clock_tolerance.d.ts +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +13 -11
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +5 -2
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +5 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +8 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +28 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +3 -3
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +1 -0
- package/dest/msg_validators/tx_validator/factory.d.ts +5 -4
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +11 -7
- package/dest/msg_validators/tx_validator/index.d.ts +3 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +2 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
- package/dest/services/discv5/discV5_service.d.ts +2 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +35 -8
- package/dest/services/dummy_service.d.ts +10 -17
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +9 -18
- package/dest/services/libp2p/libp2p_service.d.ts +19 -21
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +147 -148
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +1 -0
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +1 -8
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +35 -44
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +8 -5
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
- package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
- package/dest/services/reqresp/interface.d.ts +3 -10
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +0 -9
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +42 -24
- package/dest/services/reqresp/reqresp.d.ts +5 -29
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +16 -206
- package/dest/services/service.d.ts +7 -13
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +2 -23
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +2 -55
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
- package/dest/services/tx_collection/index.d.ts +2 -3
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +0 -1
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +0 -2
- package/dest/services/tx_collection/tx_collection.d.ts +35 -51
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +275 -119
- package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +2 -2
- package/dest/services/tx_file_store/tx_file_store.d.ts +1 -3
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +4 -14
- package/dest/services/tx_provider.d.ts +3 -1
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +3 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +13 -7
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +12 -37
- package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +11 -15
- package/dest/test-helpers/test_tx_provider.d.ts +3 -1
- package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
- package/dest/test-helpers/test_tx_provider.js +3 -0
- package/dest/test-helpers/testbench-utils.d.ts +12 -14
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +19 -14
- package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +13 -24
- package/dest/testbench/worker_client_manager.d.ts +3 -6
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +2 -8
- package/dest/util.d.ts +11 -6
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +35 -14
- package/dest/versioning.d.ts +3 -6
- package/dest/versioning.d.ts.map +1 -1
- package/dest/versioning.js +3 -24
- package/package.json +15 -14
- package/src/bootstrap/bootstrap.ts +9 -1
- package/src/client/factory.ts +20 -5
- package/src/client/interface.ts +6 -10
- package/src/client/p2p_client.ts +61 -36
- package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
- package/src/config.ts +94 -6
- package/src/errors/reqresp.error.ts +0 -25
- package/src/mem_pools/attestation_pool/attestation_pool.ts +309 -238
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +198 -62
- package/src/mem_pools/attestation_pool/mocks.ts +13 -8
- package/src/mem_pools/instrumentation.ts +5 -1
- package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +73 -90
- package/src/msg_validators/attestation_validator/attestation_validator.ts +21 -1
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +11 -7
- package/src/msg_validators/clock_tolerance.ts +13 -12
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +9 -2
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +14 -2
- package/src/msg_validators/proposal_validator/proposal_validator.ts +39 -2
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +3 -3
- package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
- package/src/msg_validators/tx_validator/data_validator.ts +2 -0
- package/src/msg_validators/tx_validator/factory.ts +15 -6
- package/src/msg_validators/tx_validator/index.ts +2 -0
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
- package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
- package/src/services/discv5/discV5_service.ts +38 -5
- package/src/services/dummy_service.ts +12 -43
- package/src/services/libp2p/libp2p_service.ts +169 -167
- package/src/services/peer-manager/peer_manager.ts +1 -0
- package/src/services/reqresp/README.md +0 -14
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +39 -52
- package/src/services/reqresp/batch-tx-requester/interface.ts +11 -4
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
- package/src/services/reqresp/interface.ts +2 -38
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
- package/src/services/reqresp/reqresp.ts +11 -251
- package/src/services/service.ts +9 -30
- package/src/services/tx_collection/config.ts +3 -80
- package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
- package/src/services/tx_collection/index.ts +1 -6
- package/src/services/tx_collection/instrumentation.ts +1 -7
- package/src/services/tx_collection/tx_collection.ts +330 -173
- package/src/services/tx_collection/tx_collection_sink.ts +2 -2
- package/src/services/tx_file_store/tx_file_store.ts +5 -17
- package/src/services/tx_provider.ts +5 -0
- package/src/test-helpers/make-test-p2p-clients.ts +1 -0
- package/src/test-helpers/mock-pubsub.ts +17 -60
- package/src/test-helpers/reqresp-nodes.ts +8 -20
- package/src/test-helpers/test_tx_provider.ts +5 -0
- package/src/test-helpers/testbench-utils.ts +23 -27
- package/src/testbench/p2p_client_testbench_worker.ts +16 -42
- package/src/testbench/worker_client_manager.ts +4 -19
- package/src/util.ts +32 -17
- package/src/versioning.ts +3 -33
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -318
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
- package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -51
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/fast_tx_collection.js +0 -311
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -48
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
- package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
- package/dest/services/tx_collection/slow_tx_collection.js +0 -211
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -357
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
- package/src/services/tx_collection/fast_tx_collection.ts +0 -361
- package/src/services/tx_collection/proposal_tx_collector.ts +0 -108
- package/src/services/tx_collection/slow_tx_collection.ts +0 -266
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { FifoSet } from '@aztec/foundation/fifo-set';
|
|
2
3
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
4
|
import type { DateProvider } from '@aztec/foundation/timer';
|
|
4
5
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
@@ -40,6 +41,13 @@ import {
|
|
|
40
41
|
import { type TxMetaData, type TxState, buildTxMetaData, checkNullifierConflict } from './tx_metadata.js';
|
|
41
42
|
import { TxPoolIndices } from './tx_pool_indices.js';
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Maximum number of full transactions to load into memory at once when finalizing a block.
|
|
46
|
+
* Bounds peak memory while archiving and hard-deleting mined txs (~23k txs/epoch at 10 TPS would
|
|
47
|
+
* otherwise OOM the node).
|
|
48
|
+
*/
|
|
49
|
+
const FINALIZE_BLOCK_CHUNK_SIZE = 100;
|
|
50
|
+
|
|
43
51
|
/**
|
|
44
52
|
* Callbacks for the implementation to notify the outer class about events and metrics.
|
|
45
53
|
*/
|
|
@@ -75,7 +83,7 @@ export class TxPoolV2Impl {
|
|
|
75
83
|
#evictionManager: EvictionManager;
|
|
76
84
|
#dateProvider: DateProvider;
|
|
77
85
|
#instrumentation: TxPoolV2Instrumentation;
|
|
78
|
-
#evictedTxHashes:
|
|
86
|
+
#evictedTxHashes: FifoSet<string>;
|
|
79
87
|
#log: Logger;
|
|
80
88
|
#callbacks: TxPoolV2Callbacks;
|
|
81
89
|
|
|
@@ -98,6 +106,7 @@ export class TxPoolV2Impl {
|
|
|
98
106
|
this.#checkAllowedSetupCalls = deps.checkAllowedSetupCalls;
|
|
99
107
|
|
|
100
108
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
109
|
+
this.#evictedTxHashes = FifoSet.withLimit<string>(this.#config.evictedTxCacheSize);
|
|
101
110
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
102
111
|
this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
|
|
103
112
|
this.#dateProvider = dateProvider;
|
|
@@ -140,39 +149,67 @@ export class TxPoolV2Impl {
|
|
|
140
149
|
// Step 0: Hydrate deleted pool state
|
|
141
150
|
await this.#deletedPool.hydrateFromDatabase();
|
|
142
151
|
|
|
143
|
-
// Step 1:
|
|
144
|
-
const
|
|
152
|
+
// Step 1: Stream txs from DB, building metadata and mined status one at a time.
|
|
153
|
+
const minedMetas: TxMetaData[] = [];
|
|
154
|
+
const pendingMetas: TxMetaData[] = [];
|
|
155
|
+
const deserializationErrors: string[] = [];
|
|
156
|
+
|
|
157
|
+
for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
|
|
158
|
+
// Skip soft-deleted transactions - they stay in DB but not in indices
|
|
159
|
+
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
let meta: TxMetaData;
|
|
164
|
+
let txEffect: Awaited<ReturnType<L2BlockSource['getTxEffect']>>;
|
|
165
|
+
try {
|
|
166
|
+
const tx = Tx.fromBuffer(buffer);
|
|
167
|
+
// Resolve allowed-setup-calls and the tx effect concurrently
|
|
168
|
+
// getTxEffect failures are non-fatal (we just treat the tx as not-yet-mined), so
|
|
169
|
+
// its rejection is swallowed before the Promise.all so it can't fail-fast the batch.
|
|
170
|
+
const txEffectPromise = this.#l2BlockSource.getTxEffect(tx.getTxHash()).catch(err => {
|
|
171
|
+
this.#log.warn(`Failed to check mined status for tx ${txHashStr}`, { err });
|
|
172
|
+
return undefined;
|
|
173
|
+
});
|
|
174
|
+
const [allowedSetupCalls, fetchedTxEffect] = await Promise.all([
|
|
175
|
+
this.#checkAllowedSetupCalls(tx),
|
|
176
|
+
txEffectPromise,
|
|
177
|
+
]);
|
|
178
|
+
meta = await buildTxMetaData(tx, allowedSetupCalls);
|
|
179
|
+
txEffect = fetchedTxEffect;
|
|
180
|
+
} catch (err) {
|
|
181
|
+
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
182
|
+
deserializationErrors.push(txHashStr);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
145
185
|
|
|
146
|
-
|
|
147
|
-
|
|
186
|
+
if (txEffect) {
|
|
187
|
+
meta.minedL2BlockId = {
|
|
188
|
+
number: txEffect.l2BlockNumber,
|
|
189
|
+
hash: txEffect.l2BlockHash.toString(),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
148
192
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const nonMined: { tx: Tx; meta: TxMetaData }[] = [];
|
|
152
|
-
for (const entry of loaded) {
|
|
153
|
-
if (entry.meta.minedL2BlockId !== undefined) {
|
|
154
|
-
mined.push(entry.meta);
|
|
193
|
+
if (meta.minedL2BlockId !== undefined) {
|
|
194
|
+
minedMetas.push(meta);
|
|
155
195
|
} else {
|
|
156
|
-
|
|
196
|
+
pendingMetas.push(meta);
|
|
157
197
|
}
|
|
158
198
|
}
|
|
159
199
|
|
|
160
|
-
// Step
|
|
161
|
-
const { valid, invalid } = await this.#revalidateMetadata(
|
|
162
|
-
nonMined.map(e => e.meta),
|
|
163
|
-
'on startup',
|
|
164
|
-
);
|
|
200
|
+
// Step 2: Validate non-mined transactions
|
|
201
|
+
const { valid, invalid } = await this.#revalidateMetadata(pendingMetas, 'on startup');
|
|
165
202
|
|
|
166
|
-
// Step
|
|
167
|
-
for (const meta of
|
|
203
|
+
// Step 3: Populate mined indices (these don't need conflict resolution)
|
|
204
|
+
for (const meta of minedMetas) {
|
|
168
205
|
this.#indices.addMined(meta);
|
|
169
206
|
}
|
|
170
207
|
|
|
171
|
-
// Step
|
|
208
|
+
// Step 4: Rebuild pending pool by running pre-add rules for each tx
|
|
172
209
|
// This resolves nullifier conflicts, fee payer balance issues, and pool size limits
|
|
173
210
|
const { rejected } = await this.#rebuildPendingPool(valid);
|
|
174
211
|
|
|
175
|
-
// Step
|
|
212
|
+
// Step 5: Delete invalid and rejected txs from DB only (indices were never populated for these)
|
|
176
213
|
const toDelete = [...deserializationErrors, ...invalid, ...rejected];
|
|
177
214
|
if (toDelete.length === 0) {
|
|
178
215
|
return;
|
|
@@ -640,28 +677,29 @@ export class TxPoolV2Impl {
|
|
|
640
677
|
// Step 1: Find mined txs at or before finalized block
|
|
641
678
|
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
|
|
642
679
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
680
|
+
// Step 2: Archive in chunks if archiving is enabled. Hydrating an entire epoch's worth of
|
|
681
|
+
// mined txs at once would OOM under load. When archiving is disabled there is no need to hydrate the txs at all.
|
|
682
|
+
if (this.#archive.isEnabled()) {
|
|
683
|
+
for (let i = 0; i < minedTxsToFinalize.length; i += FINALIZE_BLOCK_CHUNK_SIZE) {
|
|
684
|
+
const chunk = minedTxsToFinalize.slice(i, i + FINALIZE_BLOCK_CHUNK_SIZE);
|
|
685
|
+
const txsToArchive: Tx[] = [];
|
|
686
|
+
for (const txHashStr of chunk) {
|
|
648
687
|
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
649
688
|
if (buffer) {
|
|
650
689
|
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
651
690
|
}
|
|
652
691
|
}
|
|
692
|
+
if (txsToArchive.length > 0) {
|
|
693
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
694
|
+
}
|
|
653
695
|
}
|
|
696
|
+
}
|
|
654
697
|
|
|
655
|
-
|
|
698
|
+
// Step 3: Delete mined txs from the active pool and finalize soft-deleted txs in one
|
|
699
|
+
// transaction. Only tx hashes are touched here, so memory is bounded and atomicity is preserved.
|
|
700
|
+
await this.#store.transactionAsync(async () => {
|
|
656
701
|
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
657
|
-
|
|
658
|
-
// Step 4: Finalize soft-deleted txs
|
|
659
702
|
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
660
|
-
|
|
661
|
-
// Step 5: Archive mined txs
|
|
662
|
-
if (txsToArchive.length > 0) {
|
|
663
|
-
await this.#archive.archiveTxs(txsToArchive);
|
|
664
|
-
}
|
|
665
703
|
});
|
|
666
704
|
|
|
667
705
|
if (minedTxsToFinalize.length > 0) {
|
|
@@ -867,21 +905,11 @@ export class TxPoolV2Impl {
|
|
|
867
905
|
this.#instrumentation.recordEvictions(txHashes.length, reason);
|
|
868
906
|
for (const txHashStr of txHashes) {
|
|
869
907
|
this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
|
|
870
|
-
this.#
|
|
908
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
871
909
|
}
|
|
872
910
|
await this.#deleteTxsBatch(txHashes);
|
|
873
911
|
}
|
|
874
912
|
|
|
875
|
-
/** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */
|
|
876
|
-
#addToEvictedCache(txHashStr: string): void {
|
|
877
|
-
if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
|
|
878
|
-
// FIFO eviction: remove the first (oldest) entry
|
|
879
|
-
const oldest = this.#evictedTxHashes.values().next().value!;
|
|
880
|
-
this.#evictedTxHashes.delete(oldest);
|
|
881
|
-
}
|
|
882
|
-
this.#evictedTxHashes.add(txHashStr);
|
|
883
|
-
}
|
|
884
|
-
|
|
885
913
|
// ============================================================================
|
|
886
914
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
887
915
|
// ============================================================================
|
|
@@ -976,51 +1004,6 @@ export class TxPoolV2Impl {
|
|
|
976
1004
|
};
|
|
977
1005
|
}
|
|
978
1006
|
|
|
979
|
-
/** Loads all transactions from the database, returning loaded txs and deserialization errors */
|
|
980
|
-
async #loadAllTxsFromDb(): Promise<{
|
|
981
|
-
loaded: { tx: Tx; meta: TxMetaData }[];
|
|
982
|
-
errors: string[];
|
|
983
|
-
}> {
|
|
984
|
-
const loaded: { tx: Tx; meta: TxMetaData }[] = [];
|
|
985
|
-
const errors: string[] = [];
|
|
986
|
-
|
|
987
|
-
for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
|
|
988
|
-
// Skip soft-deleted transactions - they stay in DB but not in indices
|
|
989
|
-
if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
990
|
-
continue;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
try {
|
|
994
|
-
const tx = Tx.fromBuffer(buffer);
|
|
995
|
-
const allowedSetupCalls = await this.#checkAllowedSetupCalls(tx);
|
|
996
|
-
const meta = await buildTxMetaData(tx, allowedSetupCalls);
|
|
997
|
-
loaded.push({ tx, meta });
|
|
998
|
-
} catch (err) {
|
|
999
|
-
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
1000
|
-
errors.push(txHashStr);
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
return { loaded, errors };
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
/** Queries block source and marks mined status on transaction metadata */
|
|
1008
|
-
async #markMinedStatusBatch(metas: TxMetaData[]): Promise<void> {
|
|
1009
|
-
for (const meta of metas) {
|
|
1010
|
-
try {
|
|
1011
|
-
const txEffect = await this.#l2BlockSource.getTxEffect(TxHash.fromString(meta.txHash));
|
|
1012
|
-
if (txEffect) {
|
|
1013
|
-
meta.minedL2BlockId = {
|
|
1014
|
-
number: txEffect.l2BlockNumber,
|
|
1015
|
-
hash: txEffect.l2BlockHash.toString(),
|
|
1016
|
-
};
|
|
1017
|
-
}
|
|
1018
|
-
} catch (err) {
|
|
1019
|
-
this.#log.warn(`Failed to check mined status for tx ${meta.txHash}`, { err });
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
1007
|
/**
|
|
1025
1008
|
* Rebuilds the pending pool by processing each tx through pre-add rules.
|
|
1026
1009
|
* Starts with an empty pending pool and adds txs one by one, resolving conflicts.
|
|
@@ -3,9 +3,11 @@ import { NoCommitteeError } from '@aztec/ethereum/contracts';
|
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import {
|
|
5
5
|
type CheckpointAttestation,
|
|
6
|
+
type CoordinationSignatureContext,
|
|
6
7
|
type P2PValidator,
|
|
7
8
|
PeerErrorSeverity,
|
|
8
9
|
type ValidationResult,
|
|
10
|
+
hasValidSignatureContext,
|
|
9
11
|
} from '@aztec/stdlib/p2p';
|
|
10
12
|
|
|
11
13
|
import { PipeliningWindow, isWithinClockTolerance } from '../clock_tolerance.js';
|
|
@@ -14,15 +16,22 @@ export class CheckpointAttestationValidator implements P2PValidator<CheckpointAt
|
|
|
14
16
|
protected epochCache: EpochCacheInterface;
|
|
15
17
|
protected logger: Logger;
|
|
16
18
|
private readonly pipeliningWindow: PipeliningWindow;
|
|
19
|
+
protected readonly signatureContext: CoordinationSignatureContext;
|
|
17
20
|
|
|
18
21
|
constructor(
|
|
19
22
|
epochCache: EpochCacheInterface,
|
|
20
23
|
opts: {
|
|
21
24
|
l1PublishingTime?: number;
|
|
25
|
+
p2pPropagationTime?: number;
|
|
26
|
+
signatureContext: CoordinationSignatureContext;
|
|
22
27
|
},
|
|
23
28
|
) {
|
|
24
29
|
this.epochCache = epochCache;
|
|
25
|
-
this.pipeliningWindow = new PipeliningWindow(epochCache, {
|
|
30
|
+
this.pipeliningWindow = new PipeliningWindow(epochCache, {
|
|
31
|
+
l1PublishingTime: opts.l1PublishingTime,
|
|
32
|
+
p2pPropagationTime: opts.p2pPropagationTime,
|
|
33
|
+
});
|
|
34
|
+
this.signatureContext = opts.signatureContext;
|
|
26
35
|
this.logger = createLogger('p2p:checkpoint-attestation-validator');
|
|
27
36
|
}
|
|
28
37
|
|
|
@@ -30,6 +39,17 @@ export class CheckpointAttestationValidator implements P2PValidator<CheckpointAt
|
|
|
30
39
|
const slotNumber = message.payload.header.slotNumber;
|
|
31
40
|
|
|
32
41
|
try {
|
|
42
|
+
// Cross-chain replay check: reject attestations that carry a foreign signing domain.
|
|
43
|
+
if (!hasValidSignatureContext(message.payload, this.signatureContext)) {
|
|
44
|
+
this.logger.warn(`Rejecting checkpoint attestation with foreign signature context for slot ${slotNumber}`, {
|
|
45
|
+
chainId: message.payload.signatureContext.chainId,
|
|
46
|
+
rollupAddress: message.payload.signatureContext.rollupAddress.toString(),
|
|
47
|
+
expectedChainId: this.signatureContext.chainId,
|
|
48
|
+
expectedRollupAddress: this.signatureContext.rollupAddress.toString(),
|
|
49
|
+
});
|
|
50
|
+
return { result: 'reject', severity: PeerErrorSeverity.LowToleranceError };
|
|
51
|
+
}
|
|
52
|
+
|
|
33
53
|
// Use target slots since proposals target pipeline slots (slot + 1 when pipelining).
|
|
34
54
|
const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
|
|
35
55
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type CheckpointAttestation,
|
|
4
|
+
type CoordinationSignatureContext,
|
|
5
|
+
PeerErrorSeverity,
|
|
6
|
+
type ValidationResult,
|
|
7
|
+
} from '@aztec/stdlib/p2p';
|
|
3
8
|
import { Attributes, Metrics, type TelemetryClient, createUpDownCounterWithDefault } from '@aztec/telemetry-client';
|
|
4
9
|
|
|
5
10
|
import type { AttestationPoolApi } from '../../mem_pools/attestation_pool/attestation_pool.js';
|
|
@@ -22,7 +27,9 @@ export class FishermanAttestationValidator extends CheckpointAttestationValidato
|
|
|
22
27
|
telemetryClient: TelemetryClient,
|
|
23
28
|
opts: {
|
|
24
29
|
l1PublishingTime?: number;
|
|
25
|
-
|
|
30
|
+
p2pPropagationTime?: number;
|
|
31
|
+
signatureContext: CoordinationSignatureContext;
|
|
32
|
+
},
|
|
26
33
|
) {
|
|
27
34
|
super(epochCache, opts);
|
|
28
35
|
this.logger = this.logger.createChild('[FISHERMAN]');
|
|
@@ -57,8 +64,7 @@ export class FishermanAttestationValidator extends CheckpointAttestationValidato
|
|
|
57
64
|
return { result: 'accept' };
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
const
|
|
61
|
-
const proposal = await this.attestationPool.getCheckpointProposal(proposalId);
|
|
67
|
+
const proposal = await this.attestationPool.getCheckpointProposal(message.payload.header.slotNumber);
|
|
62
68
|
|
|
63
69
|
if (proposal) {
|
|
64
70
|
// Compare the attestation payload with the proposal payload
|
|
@@ -87,9 +93,7 @@ export class FishermanAttestationValidator extends CheckpointAttestationValidato
|
|
|
87
93
|
}
|
|
88
94
|
} else {
|
|
89
95
|
// We might receive attestations before proposals in some cases
|
|
90
|
-
this.logger.debug(
|
|
91
|
-
`Received attestation for slot ${slotNumberBigInt} but proposal not found yet. ` + `Proposal ID: ${proposalId}`,
|
|
92
|
-
);
|
|
96
|
+
this.logger.debug(`Received attestation for slot ${slotNumberBigInt} but proposal not found yet.`);
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
return { result: 'accept' };
|
|
@@ -53,27 +53,28 @@ export function isWithinClockTolerance(
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* Checks if a message
|
|
56
|
+
* Checks if a straggler message for the previous target slot should be accepted.
|
|
57
57
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
58
|
+
* Proposals and attestations carry the target slot N. Most of the time the receiver is either
|
|
59
|
+
* still in the build slot N-1 (accepted via the main `slotNumber === targetSlot` match) or in the
|
|
60
|
+
* target slot N (accepted again via `targetSlot`). Stragglers that arrive after the receiver has
|
|
61
|
+
* rolled past the target slot fall to this check: accept `messageSlot === slotNow` while we're
|
|
62
|
+
* still within the first `windowSeconds + clock-disparity` of the slot.
|
|
63
|
+
*
|
|
64
|
+
* Under the early-pipelining schedule `windowSeconds` is small (0 for proposals,
|
|
65
|
+
* `2*p2pPropagationTime` for attestations) since the proposer collects everything
|
|
66
|
+
* before the slot boundary.
|
|
62
67
|
*
|
|
63
68
|
* @param messageSlot - The slot number from the received message
|
|
64
|
-
* @param epochCache - EpochCache to get timing
|
|
65
|
-
* @param windowSeconds -
|
|
66
|
-
* @returns true if
|
|
69
|
+
* @param epochCache - EpochCache to get timing state
|
|
70
|
+
* @param windowSeconds - How far into the current slot we still accept previous-target messages
|
|
71
|
+
* @returns true if the message is for the current wallclock slot and we're within the grace period
|
|
67
72
|
*/
|
|
68
73
|
function isWithinPipeliningWindow(
|
|
69
74
|
messageSlot: SlotNumber,
|
|
70
75
|
epochCache: EpochCacheInterface,
|
|
71
76
|
windowSeconds: number,
|
|
72
77
|
): boolean {
|
|
73
|
-
if (!epochCache.isProposerPipeliningEnabled()) {
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
78
|
const currentSlot = epochCache.getSlotNow();
|
|
78
79
|
if (messageSlot !== currentSlot) {
|
|
79
80
|
return false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import type { BlockProposal, P2PValidator, ValidationResult } from '@aztec/stdlib/p2p';
|
|
2
|
+
import type { BlockProposal, CoordinationSignatureContext, P2PValidator, ValidationResult } from '@aztec/stdlib/p2p';
|
|
3
3
|
|
|
4
4
|
import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
5
5
|
|
|
@@ -8,7 +8,14 @@ export class BlockProposalValidator implements P2PValidator<BlockProposal> {
|
|
|
8
8
|
|
|
9
9
|
constructor(
|
|
10
10
|
epochCache: EpochCacheInterface,
|
|
11
|
-
opts: {
|
|
11
|
+
opts: {
|
|
12
|
+
txsPermitted: boolean;
|
|
13
|
+
maxTxsPerBlock?: number;
|
|
14
|
+
maxBlocksPerCheckpoint?: number;
|
|
15
|
+
p2pPropagationTime?: number;
|
|
16
|
+
skipSlotValidation?: boolean;
|
|
17
|
+
signatureContext: CoordinationSignatureContext;
|
|
18
|
+
},
|
|
12
19
|
) {
|
|
13
20
|
this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:block_proposal_validator');
|
|
14
21
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
CheckpointProposal,
|
|
4
|
+
CoordinationSignatureContext,
|
|
5
|
+
P2PValidator,
|
|
6
|
+
ValidationResult,
|
|
7
|
+
} from '@aztec/stdlib/p2p';
|
|
3
8
|
|
|
4
9
|
import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
5
10
|
|
|
@@ -8,7 +13,14 @@ export class CheckpointProposalValidator implements P2PValidator<CheckpointPropo
|
|
|
8
13
|
|
|
9
14
|
constructor(
|
|
10
15
|
epochCache: EpochCacheInterface,
|
|
11
|
-
opts: {
|
|
16
|
+
opts: {
|
|
17
|
+
txsPermitted: boolean;
|
|
18
|
+
maxTxsPerBlock?: number;
|
|
19
|
+
maxBlocksPerCheckpoint?: number;
|
|
20
|
+
p2pPropagationTime?: number;
|
|
21
|
+
skipSlotValidation?: boolean;
|
|
22
|
+
signatureContext: CoordinationSignatureContext;
|
|
23
|
+
},
|
|
12
24
|
) {
|
|
13
25
|
this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:checkpoint_proposal_validator');
|
|
14
26
|
}
|
|
@@ -4,8 +4,10 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
|
4
4
|
import {
|
|
5
5
|
type BlockProposal,
|
|
6
6
|
type CheckpointProposalCore,
|
|
7
|
+
type CoordinationSignatureContext,
|
|
7
8
|
PeerErrorSeverity,
|
|
8
9
|
type ValidationResult,
|
|
10
|
+
hasValidSignatureContext,
|
|
9
11
|
} from '@aztec/stdlib/p2p';
|
|
10
12
|
|
|
11
13
|
import { PipeliningWindow, isWithinClockTolerance } from '../clock_tolerance.js';
|
|
@@ -16,28 +18,52 @@ export class ProposalValidator {
|
|
|
16
18
|
private logger: Logger;
|
|
17
19
|
private txsPermitted: boolean;
|
|
18
20
|
private maxTxsPerBlock?: number;
|
|
21
|
+
private maxBlocksPerCheckpoint?: number;
|
|
19
22
|
private pipeliningWindow: PipeliningWindow;
|
|
23
|
+
private skipSlotValidation: boolean;
|
|
24
|
+
private signatureContext: CoordinationSignatureContext;
|
|
20
25
|
|
|
21
26
|
constructor(
|
|
22
27
|
epochCache: EpochCacheInterface,
|
|
23
|
-
opts: {
|
|
28
|
+
opts: {
|
|
29
|
+
txsPermitted: boolean;
|
|
30
|
+
maxTxsPerBlock?: number;
|
|
31
|
+
maxBlocksPerCheckpoint?: number;
|
|
32
|
+
p2pPropagationTime?: number;
|
|
33
|
+
skipSlotValidation?: boolean;
|
|
34
|
+
signatureContext: CoordinationSignatureContext;
|
|
35
|
+
},
|
|
24
36
|
loggerName: string,
|
|
25
37
|
) {
|
|
26
38
|
this.epochCache = epochCache;
|
|
27
39
|
this.txsPermitted = opts.txsPermitted;
|
|
28
40
|
this.maxTxsPerBlock = opts.maxTxsPerBlock;
|
|
41
|
+
this.maxBlocksPerCheckpoint = opts.maxBlocksPerCheckpoint;
|
|
29
42
|
this.pipeliningWindow = new PipeliningWindow(epochCache, { p2pPropagationTime: opts.p2pPropagationTime });
|
|
43
|
+
this.skipSlotValidation = opts.skipSlotValidation ?? false;
|
|
44
|
+
this.signatureContext = opts.signatureContext;
|
|
30
45
|
this.logger = createLogger(loggerName);
|
|
31
46
|
}
|
|
32
47
|
|
|
33
48
|
/** Validates header-level fields: slot, signature, and proposer. */
|
|
34
49
|
public async validate(proposal: BlockProposal | CheckpointProposalCore): Promise<ValidationResult> {
|
|
35
50
|
try {
|
|
51
|
+
// Cross-chain replay check: reject proposals that carry a foreign signing domain.
|
|
52
|
+
if (!hasValidSignatureContext(proposal, this.signatureContext)) {
|
|
53
|
+
this.logger.warn(`Penalizing peer for proposal with foreign signature context`, {
|
|
54
|
+
chainId: proposal.signatureContext.chainId,
|
|
55
|
+
rollupAddress: proposal.signatureContext.rollupAddress.toString(),
|
|
56
|
+
expectedChainId: this.signatureContext.chainId,
|
|
57
|
+
expectedRollupAddress: this.signatureContext.rollupAddress.toString(),
|
|
58
|
+
});
|
|
59
|
+
return { result: 'reject', severity: PeerErrorSeverity.LowToleranceError };
|
|
60
|
+
}
|
|
61
|
+
|
|
36
62
|
// Slot check: use target slots since proposals target pipeline slots (slot + 1 when pipelining).
|
|
37
63
|
const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
|
|
38
64
|
|
|
39
65
|
const slotNumber = proposal.slotNumber;
|
|
40
|
-
if (slotNumber !== targetSlot && slotNumber !== nextSlot) {
|
|
66
|
+
if (!this.skipSlotValidation && slotNumber !== targetSlot && slotNumber !== nextSlot) {
|
|
41
67
|
// When pipelining, accept proposals for the current slot (built in the previous slot)
|
|
42
68
|
// if they're still within the shared proposal acceptance window.
|
|
43
69
|
if (this.pipeliningWindow.acceptsProposal(slotNumber)) {
|
|
@@ -68,6 +94,17 @@ export class ProposalValidator {
|
|
|
68
94
|
return { result: 'reject', severity: PeerErrorSeverity.MidToleranceError };
|
|
69
95
|
}
|
|
70
96
|
|
|
97
|
+
if (
|
|
98
|
+
this.maxBlocksPerCheckpoint !== undefined &&
|
|
99
|
+
'indexWithinCheckpoint' in proposal &&
|
|
100
|
+
proposal.indexWithinCheckpoint >= this.maxBlocksPerCheckpoint
|
|
101
|
+
) {
|
|
102
|
+
this.logger.warn(
|
|
103
|
+
`Penalizing peer for proposal with indexWithinCheckpoint ${proposal.indexWithinCheckpoint} >= max ${this.maxBlocksPerCheckpoint}`,
|
|
104
|
+
);
|
|
105
|
+
return { result: 'reject', severity: PeerErrorSeverity.MidToleranceError };
|
|
106
|
+
}
|
|
107
|
+
|
|
71
108
|
return { result: 'accept' };
|
|
72
109
|
} catch (e) {
|
|
73
110
|
if (e instanceof NoCommitteeError) {
|
|
@@ -11,22 +11,13 @@ export class AggregateTxValidator<T> implements TxValidator<T> {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
14
|
-
const
|
|
14
|
+
const reasons: string[] = [];
|
|
15
15
|
for (const validator of this.validators) {
|
|
16
16
|
const result = await validator.validateTx(tx);
|
|
17
17
|
if (result.result === 'invalid') {
|
|
18
|
-
|
|
19
|
-
aggregate.reason!.push(...result.reason);
|
|
20
|
-
} else if (result.result === 'skipped') {
|
|
21
|
-
if (aggregate.result === 'valid') {
|
|
22
|
-
aggregate.result = 'skipped';
|
|
23
|
-
}
|
|
24
|
-
aggregate.reason!.push(...result.reason);
|
|
18
|
+
reasons.push(...result.reason);
|
|
25
19
|
}
|
|
26
20
|
}
|
|
27
|
-
|
|
28
|
-
delete aggregate.reason;
|
|
29
|
-
}
|
|
30
|
-
return aggregate as TxValidationResult;
|
|
21
|
+
return reasons.length > 0 ? { result: 'invalid', reason: reasons } : { result: 'valid' };
|
|
31
22
|
}
|
|
32
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
2
|
-
import { AuthRegistryArtifact } from '@aztec/protocol-contracts/auth-registry';
|
|
3
2
|
import { FeeJuiceArtifact } from '@aztec/protocol-contracts/fee-juice';
|
|
3
|
+
import { AuthRegistryArtifact, STANDARD_AUTH_REGISTRY_ADDRESS } from '@aztec/standard-contracts/auth-registry';
|
|
4
4
|
import type { AllowedElement } from '@aztec/stdlib/interfaces/server';
|
|
5
5
|
|
|
6
6
|
import { buildAllowedElement } from './allowed_setup_helpers.js';
|
|
@@ -12,12 +12,12 @@ export async function getDefaultAllowedSetupFunctions(): Promise<AllowedElement[
|
|
|
12
12
|
if (defaultAllowedSetupFunctions === undefined) {
|
|
13
13
|
defaultAllowedSetupFunctions = await Promise.all([
|
|
14
14
|
// AuthRegistry: needed for authwit support via private path (set_authorized_private enqueues _set_authorized)
|
|
15
|
-
buildAllowedElement(AuthRegistryArtifact, { address:
|
|
15
|
+
buildAllowedElement(AuthRegistryArtifact, { address: STANDARD_AUTH_REGISTRY_ADDRESS }, '_set_authorized', {
|
|
16
16
|
onlySelf: true,
|
|
17
17
|
rejectNullMsgSender: true,
|
|
18
18
|
}),
|
|
19
19
|
// AuthRegistry: needed for authwit support via public path (PublicFeePaymentMethod calls set_authorized directly)
|
|
20
|
-
buildAllowedElement(AuthRegistryArtifact, { address:
|
|
20
|
+
buildAllowedElement(AuthRegistryArtifact, { address: STANDARD_AUTH_REGISTRY_ADDRESS }, 'set_authorized', {
|
|
21
21
|
rejectNullMsgSender: true,
|
|
22
22
|
}),
|
|
23
23
|
// FeeJuice: needed for claiming on the same tx as a spend (claim_and_end_setup enqueues this)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Tx, TxValidationResult, TxValidator } from '@aztec/stdlib/tx';
|
|
2
|
+
|
|
3
|
+
import type { ITxValidationCache } from './tx_validation_cache.js';
|
|
4
|
+
|
|
5
|
+
/** Wraps a {@link TxValidator} to cache its results in a shared {@link ITxValidationCache}. */
|
|
6
|
+
export class CachedTxValidator<T extends Tx> implements TxValidator<T> {
|
|
7
|
+
constructor(
|
|
8
|
+
private readonly inner: TxValidator<T>,
|
|
9
|
+
private readonly validatorSymbol: symbol,
|
|
10
|
+
private readonly cache: ITxValidationCache,
|
|
11
|
+
) {}
|
|
12
|
+
|
|
13
|
+
public static new<T extends Tx>(
|
|
14
|
+
inner: TxValidator<T> & { identifier: symbol },
|
|
15
|
+
cache?: ITxValidationCache,
|
|
16
|
+
): TxValidator<T> {
|
|
17
|
+
return CachedTxValidator.newWithIdentifier(inner, inner.identifier, cache);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public static newWithIdentifier<T extends Tx>(
|
|
21
|
+
inner: TxValidator<T>,
|
|
22
|
+
identifier: symbol,
|
|
23
|
+
cache?: ITxValidationCache,
|
|
24
|
+
): TxValidator<T> {
|
|
25
|
+
return cache ? new CachedTxValidator(inner, identifier, cache) : inner;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public validateTx(tx: T): Promise<TxValidationResult> {
|
|
29
|
+
return this.cache.getOrValidate(this.validatorSymbol, tx, () => this.inner.validateTx(tx));
|
|
30
|
+
}
|
|
31
|
+
}
|