@aztec/p2p 0.0.1-commit.7cf39cb55 → 0.0.1-commit.808bf7f90
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/client/factory.d.ts +3 -2
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +5 -3
- package/dest/client/interface.d.ts +7 -9
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +4 -7
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +38 -14
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +5 -5
- package/dest/config.d.ts +4 -6
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +0 -5
- package/dest/errors/tx-pool.error.d.ts +8 -0
- package/dest/errors/tx-pool.error.d.ts.map +1 -0
- package/dest/errors/tx-pool.error.js +9 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +2 -2
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +3 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +9 -0
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +10 -4
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +48 -5
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +5 -5
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +12 -6
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +14 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +12 -2
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +3 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +7 -5
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +29 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +5 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +12 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +5 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +6 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +10 -4
- 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 +240 -124
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +3 -3
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- package/dest/services/dummy_service.d.ts +3 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +3 -0
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +2 -1
- package/dest/services/gossipsub/topic_score_params.d.ts +18 -6
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +32 -10
- package/dest/services/libp2p/libp2p_service.d.ts +2 -1
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +7 -3
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -3
- 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 +5 -9
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -6
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +10 -13
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +25 -46
- package/dest/services/service.d.ts +4 -2
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +39 -33
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +4 -2
- package/dest/services/tx_collection/file_store_tx_source.d.ts +15 -6
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +47 -16
- 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 +2 -1
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
- package/dest/services/tx_collection/slow_tx_collection.d.ts +2 -2
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +10 -8
- package/dest/services/tx_collection/tx_collection.d.ts +5 -4
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.d.ts +6 -5
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +13 -22
- package/dest/services/tx_collection/tx_source.d.ts +8 -3
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +19 -2
- package/dest/services/tx_file_store/tx_file_store.js +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +3 -2
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +6 -0
- package/dest/test-helpers/testbench-utils.d.ts +5 -2
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +1 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +8 -8
- package/dest/util.d.ts +2 -2
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +6 -2
- package/src/client/interface.ts +14 -9
- package/src/client/p2p_client.ts +44 -17
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +18 -8
- package/src/config.ts +2 -10
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/mem_pools/attestation_pool/mocks.ts +2 -1
- package/src/mem_pools/tx_pool/README.md +1 -1
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/README.md +1 -1
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +11 -0
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +15 -4
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +49 -4
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +4 -4
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +12 -9
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +24 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +11 -2
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +40 -9
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +14 -3
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +11 -6
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +262 -117
- package/src/msg_validators/tx_validator/gas_validator.ts +11 -3
- package/src/msg_validators/tx_validator/timestamp_validator.ts +7 -7
- package/src/services/dummy_service.ts +5 -1
- package/src/services/encoding.ts +2 -1
- package/src/services/gossipsub/README.md +29 -14
- package/src/services/gossipsub/topic_score_params.ts +49 -13
- package/src/services/libp2p/libp2p_service.ts +7 -2
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +6 -6
- package/src/services/reqresp/batch-tx-requester/interface.ts +1 -5
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +23 -71
- package/src/services/service.ts +10 -1
- package/src/services/tx_collection/fast_tx_collection.ts +51 -30
- package/src/services/tx_collection/file_store_tx_collection.ts +7 -3
- package/src/services/tx_collection/file_store_tx_source.ts +61 -17
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
- package/src/services/tx_collection/slow_tx_collection.ts +8 -9
- package/src/services/tx_collection/tx_collection.ts +4 -3
- package/src/services/tx_collection/tx_collection_sink.ts +15 -29
- package/src/services/tx_collection/tx_source.ts +22 -3
- package/src/services/tx_file_store/tx_file_store.ts +1 -1
- package/src/test-helpers/mock-pubsub.ts +10 -0
- package/src/test-helpers/testbench-utils.ts +2 -2
- package/src/testbench/p2p_client_testbench_worker.ts +20 -13
- package/src/util.ts +7 -1
|
@@ -9,6 +9,7 @@ import type { L2Block, L2BlockId, L2BlockSource } from '@aztec/stdlib/block';
|
|
|
9
9
|
import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
10
10
|
import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
|
|
11
11
|
import { BlockHeader, Tx, TxHash, type TxValidator } from '@aztec/stdlib/tx';
|
|
12
|
+
import type { TelemetryClient } from '@aztec/telemetry-client';
|
|
12
13
|
|
|
13
14
|
import { TxArchive } from './archive/index.js';
|
|
14
15
|
import { DeletedPool } from './deleted_pool.js';
|
|
@@ -22,8 +23,12 @@ import {
|
|
|
22
23
|
LowPriorityPreAddRule,
|
|
23
24
|
NullifierConflictRule,
|
|
24
25
|
type PoolOperations,
|
|
26
|
+
type PreAddContext,
|
|
25
27
|
type PreAddPoolAccess,
|
|
28
|
+
TxPoolRejectionCode,
|
|
29
|
+
type TxPoolRejectionError,
|
|
26
30
|
} from './eviction/index.js';
|
|
31
|
+
import { TxPoolV2Instrumentation } from './instrumentation.js';
|
|
27
32
|
import {
|
|
28
33
|
type AddTxsResult,
|
|
29
34
|
DEFAULT_TX_POOL_V2_CONFIG,
|
|
@@ -66,6 +71,8 @@ export class TxPoolV2Impl {
|
|
|
66
71
|
#deletedPool: DeletedPool;
|
|
67
72
|
#evictionManager: EvictionManager;
|
|
68
73
|
#dateProvider: DateProvider;
|
|
74
|
+
#instrumentation: TxPoolV2Instrumentation;
|
|
75
|
+
#evictedTxHashes: Set<string> = new Set();
|
|
69
76
|
#log: Logger;
|
|
70
77
|
#callbacks: TxPoolV2Callbacks;
|
|
71
78
|
|
|
@@ -74,6 +81,7 @@ export class TxPoolV2Impl {
|
|
|
74
81
|
archiveStore: AztecAsyncKVStore,
|
|
75
82
|
deps: TxPoolV2Dependencies,
|
|
76
83
|
callbacks: TxPoolV2Callbacks,
|
|
84
|
+
telemetry: TelemetryClient,
|
|
77
85
|
config: Partial<TxPoolV2Config> = {},
|
|
78
86
|
dateProvider: DateProvider,
|
|
79
87
|
log: Logger,
|
|
@@ -89,6 +97,7 @@ export class TxPoolV2Impl {
|
|
|
89
97
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
90
98
|
this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
|
|
91
99
|
this.#dateProvider = dateProvider;
|
|
100
|
+
this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
|
|
92
101
|
this.#log = log;
|
|
93
102
|
this.#callbacks = callbacks;
|
|
94
103
|
|
|
@@ -171,13 +180,16 @@ export class TxPoolV2Impl {
|
|
|
171
180
|
this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
|
|
172
181
|
}
|
|
173
182
|
|
|
174
|
-
async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
|
|
183
|
+
async addPendingTxs(txs: Tx[], opts: { source?: string; feeComparisonOnly?: boolean }): Promise<AddTxsResult> {
|
|
175
184
|
const accepted: TxHash[] = [];
|
|
176
185
|
const ignored: TxHash[] = [];
|
|
177
186
|
const rejected: TxHash[] = [];
|
|
187
|
+
const errors = new Map<string, TxPoolRejectionError>();
|
|
178
188
|
const acceptedPending = new Set<string>();
|
|
179
189
|
|
|
180
190
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
191
|
+
const preAddContext: PreAddContext | undefined =
|
|
192
|
+
opts.feeComparisonOnly !== undefined ? { feeComparisonOnly: opts.feeComparisonOnly } : undefined;
|
|
181
193
|
|
|
182
194
|
await this.#store.transactionAsync(async () => {
|
|
183
195
|
for (const tx of txs) {
|
|
@@ -204,7 +216,15 @@ export class TxPoolV2Impl {
|
|
|
204
216
|
accepted.push(txHash);
|
|
205
217
|
} else {
|
|
206
218
|
// Regular pending tx - validate and run pre-add rules
|
|
207
|
-
const result = await this.#tryAddRegularPendingTx(
|
|
219
|
+
const result = await this.#tryAddRegularPendingTx(
|
|
220
|
+
tx,
|
|
221
|
+
opts,
|
|
222
|
+
poolAccess,
|
|
223
|
+
acceptedPending,
|
|
224
|
+
ignored,
|
|
225
|
+
errors,
|
|
226
|
+
preAddContext,
|
|
227
|
+
);
|
|
208
228
|
if (result.status === 'accepted') {
|
|
209
229
|
acceptedPending.add(txHashStr);
|
|
210
230
|
} else if (result.status === 'rejected') {
|
|
@@ -214,6 +234,13 @@ export class TxPoolV2Impl {
|
|
|
214
234
|
}
|
|
215
235
|
}
|
|
216
236
|
}
|
|
237
|
+
|
|
238
|
+
// Run post-add eviction rules for pending txs (inside transaction for atomicity)
|
|
239
|
+
if (acceptedPending.size > 0) {
|
|
240
|
+
const feePayers = Array.from(acceptedPending).map(txHash => this.#indices.getMetadata(txHash)!.feePayer);
|
|
241
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
242
|
+
await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
|
|
243
|
+
}
|
|
217
244
|
});
|
|
218
245
|
|
|
219
246
|
// Build final accepted list for pending txs (excludes intra-batch evictions)
|
|
@@ -221,14 +248,15 @@ export class TxPoolV2Impl {
|
|
|
221
248
|
accepted.push(TxHash.fromString(txHashStr));
|
|
222
249
|
}
|
|
223
250
|
|
|
224
|
-
//
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
251
|
+
// Record metrics
|
|
252
|
+
if (ignored.length > 0) {
|
|
253
|
+
this.#instrumentation.recordIgnored(ignored.length);
|
|
254
|
+
}
|
|
255
|
+
if (rejected.length > 0) {
|
|
256
|
+
this.#instrumentation.recordRejected(rejected.length);
|
|
229
257
|
}
|
|
230
258
|
|
|
231
|
-
return { accepted, ignored, rejected };
|
|
259
|
+
return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
|
|
232
260
|
}
|
|
233
261
|
|
|
234
262
|
/** Validates and adds a regular pending tx. Returns status. */
|
|
@@ -238,6 +266,8 @@ export class TxPoolV2Impl {
|
|
|
238
266
|
poolAccess: PreAddPoolAccess,
|
|
239
267
|
acceptedPending: Set<string>,
|
|
240
268
|
ignored: TxHash[],
|
|
269
|
+
errors: Map<string, TxPoolRejectionError>,
|
|
270
|
+
preAddContext?: PreAddContext,
|
|
241
271
|
): Promise<{ status: 'accepted' | 'ignored' | 'rejected' }> {
|
|
242
272
|
const txHash = tx.getTxHash();
|
|
243
273
|
const txHashStr = txHash.toString();
|
|
@@ -249,27 +279,49 @@ export class TxPoolV2Impl {
|
|
|
249
279
|
}
|
|
250
280
|
|
|
251
281
|
// Run pre-add rules
|
|
252
|
-
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
282
|
+
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess, preAddContext);
|
|
253
283
|
|
|
254
284
|
if (preAddResult.shouldIgnore) {
|
|
255
|
-
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason}`);
|
|
285
|
+
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
|
|
286
|
+
if (preAddResult.reason && preAddResult.reason.code !== TxPoolRejectionCode.INTERNAL_ERROR) {
|
|
287
|
+
errors.set(txHashStr, preAddResult.reason);
|
|
288
|
+
}
|
|
256
289
|
return { status: 'ignored' };
|
|
257
290
|
}
|
|
258
291
|
|
|
259
|
-
// Evict conflicts
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
292
|
+
// Evict conflicts, grouped by rule name for metrics
|
|
293
|
+
if (preAddResult.evictions && preAddResult.evictions.length > 0) {
|
|
294
|
+
const byReason = new Map<string, string[]>();
|
|
295
|
+
for (const { txHash: evictHash, reason } of preAddResult.evictions) {
|
|
296
|
+
const group = byReason.get(reason);
|
|
297
|
+
if (group) {
|
|
298
|
+
group.push(evictHash);
|
|
299
|
+
} else {
|
|
300
|
+
byReason.set(reason, [evictHash]);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
for (const [reason, hashes] of byReason) {
|
|
304
|
+
await this.#evictTxs(hashes, reason);
|
|
305
|
+
}
|
|
306
|
+
for (const evictHashStr of preAddResult.txHashesToEvict) {
|
|
307
|
+
this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
|
|
308
|
+
evictedTxHash: evictHashStr,
|
|
309
|
+
replacementTxHash: txHashStr,
|
|
310
|
+
});
|
|
311
|
+
if (acceptedPending.has(evictHashStr)) {
|
|
312
|
+
// Evicted tx was from this batch - mark as ignored in result
|
|
313
|
+
acceptedPending.delete(evictHashStr);
|
|
314
|
+
ignored.push(TxHash.fromString(evictHashStr));
|
|
315
|
+
}
|
|
270
316
|
}
|
|
271
317
|
}
|
|
272
318
|
|
|
319
|
+
// Randomly drop the transaction for testing purposes (report as accepted so it propagates)
|
|
320
|
+
if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
|
|
321
|
+
this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
|
|
322
|
+
return { status: 'accepted' };
|
|
323
|
+
}
|
|
324
|
+
|
|
273
325
|
// Add the transaction
|
|
274
326
|
await this.#addTx(tx, 'pending', opts);
|
|
275
327
|
return { status: 'accepted' };
|
|
@@ -327,23 +379,58 @@ export class TxPoolV2Impl {
|
|
|
327
379
|
});
|
|
328
380
|
}
|
|
329
381
|
|
|
330
|
-
protectTxs(txHashes: TxHash[], block: BlockHeader): TxHash[] {
|
|
382
|
+
async protectTxs(txHashes: TxHash[], block: BlockHeader): Promise<TxHash[]> {
|
|
331
383
|
const slotNumber = block.globalVariables.slotNumber;
|
|
332
384
|
const missing: TxHash[] = [];
|
|
385
|
+
let softDeletedHits = 0;
|
|
386
|
+
let missingPreviouslyEvicted = 0;
|
|
333
387
|
|
|
334
|
-
|
|
335
|
-
const
|
|
388
|
+
await this.#store.transactionAsync(async () => {
|
|
389
|
+
for (const txHash of txHashes) {
|
|
390
|
+
const txHashStr = txHash.toString();
|
|
336
391
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
392
|
+
if (this.#indices.has(txHashStr)) {
|
|
393
|
+
// Update protection for existing tx
|
|
394
|
+
this.#indices.updateProtection(txHashStr, slotNumber);
|
|
395
|
+
} else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
|
|
396
|
+
// Resurrect soft-deleted tx as protected
|
|
397
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
398
|
+
if (buffer) {
|
|
399
|
+
const tx = Tx.fromBuffer(buffer);
|
|
400
|
+
await this.#addTx(tx, { protected: slotNumber });
|
|
401
|
+
softDeletedHits++;
|
|
402
|
+
} else {
|
|
403
|
+
// Data missing despite soft-delete flag — treat as truly missing
|
|
404
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
405
|
+
missing.push(txHash);
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
// Truly missing — pre-record protection for tx we don't have yet
|
|
409
|
+
this.#indices.setProtection(txHashStr, slotNumber);
|
|
410
|
+
missing.push(txHash);
|
|
411
|
+
if (this.#evictedTxHashes.has(txHashStr)) {
|
|
412
|
+
missingPreviouslyEvicted++;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
344
415
|
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// Record metrics
|
|
419
|
+
if (softDeletedHits > 0) {
|
|
420
|
+
this.#instrumentation.recordSoftDeletedHits(softDeletedHits);
|
|
421
|
+
}
|
|
422
|
+
if (missing.length > 0) {
|
|
423
|
+
this.#log.debug(`protectTxs missing tx hashes: ${missing.map(h => h.toString()).join(', ')}`);
|
|
424
|
+
this.#instrumentation.recordMissingOnProtect(missing.length);
|
|
425
|
+
}
|
|
426
|
+
if (missingPreviouslyEvicted > 0) {
|
|
427
|
+
this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
|
|
345
428
|
}
|
|
346
429
|
|
|
430
|
+
this.#log.info(
|
|
431
|
+
`Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`,
|
|
432
|
+
);
|
|
433
|
+
|
|
347
434
|
return missing;
|
|
348
435
|
}
|
|
349
436
|
|
|
@@ -387,57 +474,63 @@ export class TxPoolV2Impl {
|
|
|
387
474
|
}
|
|
388
475
|
}
|
|
389
476
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
477
|
+
await this.#store.transactionAsync(async () => {
|
|
478
|
+
// Step 4: Mark txs as mined (only those we have in the pool)
|
|
479
|
+
for (const meta of found) {
|
|
480
|
+
this.#indices.markAsMined(meta, blockId);
|
|
481
|
+
await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
|
|
482
|
+
}
|
|
395
483
|
|
|
396
|
-
|
|
397
|
-
|
|
484
|
+
// Step 5: Run post-event eviction rules (inside transaction for atomicity)
|
|
485
|
+
await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
|
|
486
|
+
});
|
|
398
487
|
|
|
399
488
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
400
489
|
}
|
|
401
490
|
|
|
402
491
|
async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
|
|
403
|
-
|
|
404
|
-
|
|
492
|
+
await this.#store.transactionAsync(async () => {
|
|
493
|
+
// Step 0: Clean up slot-deleted txs from previous slots
|
|
494
|
+
await this.#deletedPool.cleanupSlotDeleted(slotNumber);
|
|
405
495
|
|
|
406
|
-
|
|
407
|
-
|
|
496
|
+
// Step 1: Find expired protected txs
|
|
497
|
+
const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
|
|
408
498
|
|
|
409
|
-
|
|
410
|
-
|
|
499
|
+
// Step 2: Clear protection for all expired entries (including those without metadata)
|
|
500
|
+
this.#indices.clearProtection(expiredProtected);
|
|
411
501
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
502
|
+
// Step 3: Filter to only txs that have metadata and are not mined
|
|
503
|
+
const txsToRestore = this.#indices.filterRestorable(expiredProtected);
|
|
504
|
+
if (txsToRestore.length === 0) {
|
|
505
|
+
this.#log.debug(`Preparing for slot ${slotNumber}, no txs to unprotect`);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
417
508
|
|
|
418
|
-
|
|
509
|
+
this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
|
|
419
510
|
|
|
420
|
-
|
|
421
|
-
|
|
511
|
+
// Step 4: Validate for pending pool
|
|
512
|
+
const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
|
|
422
513
|
|
|
423
|
-
|
|
424
|
-
|
|
514
|
+
// Step 5: Resolve nullifier conflicts and add winners to pending indices
|
|
515
|
+
const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
425
516
|
|
|
426
|
-
|
|
427
|
-
|
|
517
|
+
// Step 6: Delete invalid txs and evict conflict losers
|
|
518
|
+
await this.#deleteTxsBatch(invalid);
|
|
519
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
428
520
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
521
|
+
// Step 7: Run eviction rules (enforce pool size limit)
|
|
522
|
+
if (added.length > 0) {
|
|
523
|
+
const feePayers = added.map(meta => meta.feePayer);
|
|
524
|
+
const uniqueFeePayers = new Set<string>(feePayers);
|
|
525
|
+
await this.#evictionManager.evictAfterNewTxs(
|
|
526
|
+
added.map(m => m.txHash),
|
|
527
|
+
[...uniqueFeePayers],
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
438
531
|
}
|
|
439
532
|
|
|
440
|
-
async handlePrunedBlocks(latestBlock: L2BlockId): Promise<void> {
|
|
533
|
+
async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
|
|
441
534
|
// Step 1: Find transactions mined after the prune point
|
|
442
535
|
const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
|
|
443
536
|
if (txsToUnmine.length === 0) {
|
|
@@ -447,46 +540,60 @@ export class TxPoolV2Impl {
|
|
|
447
540
|
|
|
448
541
|
this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
|
|
449
542
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
543
|
+
await this.#store.transactionAsync(async () => {
|
|
544
|
+
// Step 2: Mark ALL un-mined txs with their original mined block number
|
|
545
|
+
// This ensures they get soft-deleted if removed later, and only hard-deleted
|
|
546
|
+
// when their original mined block is finalized
|
|
547
|
+
await this.#deletedPool.markFromPrunedBlock(
|
|
548
|
+
txsToUnmine.map(m => ({
|
|
549
|
+
txHash: m.txHash,
|
|
550
|
+
minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
|
|
551
|
+
})),
|
|
552
|
+
);
|
|
459
553
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
554
|
+
// Step 3: Unmine - clear mined status from metadata
|
|
555
|
+
for (const meta of txsToUnmine) {
|
|
556
|
+
this.#indices.markAsUnmined(meta);
|
|
557
|
+
}
|
|
464
558
|
|
|
465
|
-
|
|
466
|
-
|
|
559
|
+
// If deleteAllTxs is set (epoch prune), delete all un-mined txs and return early
|
|
560
|
+
if (options?.deleteAllTxs) {
|
|
561
|
+
const allTxHashes = txsToUnmine.map(m => m.txHash);
|
|
562
|
+
await this.#deleteTxsBatch(allTxHashes);
|
|
563
|
+
this.#log.info(
|
|
564
|
+
`Handled prune to block ${latestBlock.number} with deleteAllTxs: deleted ${allTxHashes.length} txs`,
|
|
565
|
+
);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
467
568
|
|
|
468
|
-
|
|
469
|
-
|
|
569
|
+
// Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
|
|
570
|
+
const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
|
|
470
571
|
|
|
471
|
-
|
|
472
|
-
|
|
572
|
+
// Step 5: Validate for pending pool
|
|
573
|
+
const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
|
|
473
574
|
|
|
474
|
-
|
|
475
|
-
|
|
575
|
+
// Step 6: Resolve nullifier conflicts and add winners to pending indices
|
|
576
|
+
const { toEvict } = this.#applyNullifierConflictResolution(valid);
|
|
476
577
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
578
|
+
// Step 7: Delete invalid txs and evict conflict losers
|
|
579
|
+
await this.#deleteTxsBatch(invalid);
|
|
580
|
+
await this.#evictTxs(toEvict, 'NullifierConflict');
|
|
581
|
+
|
|
582
|
+
this.#log.info(
|
|
583
|
+
`Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`,
|
|
584
|
+
{ txHashesRestored: valid.map(m => m.txHash), txHashesInvalid: invalid, txHashesEvicted: toEvict },
|
|
585
|
+
);
|
|
481
586
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
587
|
+
// Step 8: Run eviction rules for ALL pending txs (not just restored ones)
|
|
588
|
+
// This handles cases like existing pending txs with invalid fee payer balances
|
|
589
|
+
await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
|
|
590
|
+
});
|
|
485
591
|
}
|
|
486
592
|
|
|
487
593
|
async handleFailedExecution(txHashes: TxHash[]): Promise<void> {
|
|
488
|
-
|
|
489
|
-
|
|
594
|
+
await this.#store.transactionAsync(async () => {
|
|
595
|
+
await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
|
|
596
|
+
});
|
|
490
597
|
|
|
491
598
|
this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
|
|
492
599
|
}
|
|
@@ -497,27 +604,29 @@ export class TxPoolV2Impl {
|
|
|
497
604
|
// Step 1: Find mined txs at or before finalized block
|
|
498
605
|
const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
|
|
499
606
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
607
|
+
await this.#store.transactionAsync(async () => {
|
|
608
|
+
// Step 2: Collect mined txs for archiving (before deletion)
|
|
609
|
+
const txsToArchive: Tx[] = [];
|
|
610
|
+
if (this.#archive.isEnabled()) {
|
|
611
|
+
for (const txHashStr of minedTxsToFinalize) {
|
|
612
|
+
const buffer = await this.#txsDB.getAsync(txHashStr);
|
|
613
|
+
if (buffer) {
|
|
614
|
+
txsToArchive.push(Tx.fromBuffer(buffer));
|
|
615
|
+
}
|
|
507
616
|
}
|
|
508
617
|
}
|
|
509
|
-
}
|
|
510
618
|
|
|
511
|
-
|
|
512
|
-
|
|
619
|
+
// Step 3: Delete mined txs from active pool
|
|
620
|
+
await this.#deleteTxsBatch(minedTxsToFinalize);
|
|
513
621
|
|
|
514
|
-
|
|
515
|
-
|
|
622
|
+
// Step 4: Finalize soft-deleted txs
|
|
623
|
+
await this.#deletedPool.finalizeBlock(blockNumber);
|
|
516
624
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
625
|
+
// Step 5: Archive mined txs
|
|
626
|
+
if (txsToArchive.length > 0) {
|
|
627
|
+
await this.#archive.archiveTxs(txsToArchive);
|
|
628
|
+
}
|
|
629
|
+
});
|
|
521
630
|
|
|
522
631
|
if (minedTxsToFinalize.length > 0) {
|
|
523
632
|
this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
|
|
@@ -637,8 +746,17 @@ export class TxPoolV2Impl {
|
|
|
637
746
|
|
|
638
747
|
// === Metrics ===
|
|
639
748
|
|
|
640
|
-
countTxs(): {
|
|
641
|
-
|
|
749
|
+
countTxs(): {
|
|
750
|
+
pending: number;
|
|
751
|
+
protected: number;
|
|
752
|
+
mined: number;
|
|
753
|
+
softDeleted: number;
|
|
754
|
+
totalMetadataBytes: number;
|
|
755
|
+
} {
|
|
756
|
+
return {
|
|
757
|
+
...this.#indices.countTxs(),
|
|
758
|
+
softDeleted: this.#deletedPool.getSoftDeletedCount(),
|
|
759
|
+
};
|
|
642
760
|
}
|
|
643
761
|
|
|
644
762
|
// ============================================================================
|
|
@@ -672,9 +790,11 @@ export class TxPoolV2Impl {
|
|
|
672
790
|
}
|
|
673
791
|
|
|
674
792
|
const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
|
|
675
|
-
this.#log.
|
|
793
|
+
this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
|
|
676
794
|
eventName: 'tx-added-to-pool',
|
|
795
|
+
txHash: txHashStr,
|
|
677
796
|
state: stateStr,
|
|
797
|
+
source: opts.source,
|
|
678
798
|
});
|
|
679
799
|
|
|
680
800
|
return meta;
|
|
@@ -702,6 +822,29 @@ export class TxPoolV2Impl {
|
|
|
702
822
|
}
|
|
703
823
|
}
|
|
704
824
|
|
|
825
|
+
/** Evicts transactions: records eviction metric with reason, caches hashes, then deletes. */
|
|
826
|
+
async #evictTxs(txHashes: string[], reason: string): Promise<void> {
|
|
827
|
+
if (txHashes.length === 0) {
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
this.#instrumentation.recordEvictions(txHashes.length, reason);
|
|
831
|
+
for (const txHashStr of txHashes) {
|
|
832
|
+
this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
|
|
833
|
+
this.#addToEvictedCache(txHashStr);
|
|
834
|
+
}
|
|
835
|
+
await this.#deleteTxsBatch(txHashes);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */
|
|
839
|
+
#addToEvictedCache(txHashStr: string): void {
|
|
840
|
+
if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
|
|
841
|
+
// FIFO eviction: remove the first (oldest) entry
|
|
842
|
+
const oldest = this.#evictedTxHashes.values().next().value!;
|
|
843
|
+
this.#evictedTxHashes.delete(oldest);
|
|
844
|
+
}
|
|
845
|
+
this.#evictedTxHashes.add(txHashStr);
|
|
846
|
+
}
|
|
847
|
+
|
|
705
848
|
// ============================================================================
|
|
706
849
|
// PRIVATE HELPERS - Validation & Conflict Resolution
|
|
707
850
|
// ============================================================================
|
|
@@ -857,7 +1000,9 @@ export class TxPoolV2Impl {
|
|
|
857
1000
|
if (preAddResult.shouldIgnore) {
|
|
858
1001
|
// Transaction rejected - mark for deletion from DB
|
|
859
1002
|
rejected.push(meta.txHash);
|
|
860
|
-
this.#log.debug(
|
|
1003
|
+
this.#log.debug(
|
|
1004
|
+
`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`,
|
|
1005
|
+
);
|
|
861
1006
|
continue;
|
|
862
1007
|
}
|
|
863
1008
|
|
|
@@ -893,7 +1038,7 @@ export class TxPoolV2Impl {
|
|
|
893
1038
|
getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
|
|
894
1039
|
getPendingTxCount: () => this.#indices.getPendingTxCount(),
|
|
895
1040
|
getLowestPriorityPending: (limit: number) => this.#indices.getLowestPriorityPending(limit),
|
|
896
|
-
deleteTxs: (txHashes: string[]) => this.#
|
|
1041
|
+
deleteTxs: (txHashes: string[], reason?: string) => this.#evictTxs(txHashes, reason ?? 'unknown'),
|
|
897
1042
|
};
|
|
898
1043
|
}
|
|
899
1044
|
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
MAX_PROCESSABLE_L2_GAS,
|
|
3
|
+
PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
4
|
+
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
5
|
+
TX_DA_GAS_OVERHEAD,
|
|
6
|
+
} from '@aztec/constants';
|
|
2
7
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
3
8
|
import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
4
9
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
@@ -73,7 +78,10 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
73
78
|
*/
|
|
74
79
|
#validateGasLimit(tx: Tx): TxValidationResult {
|
|
75
80
|
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
76
|
-
const minGasLimits = new Gas(
|
|
81
|
+
const minGasLimits = new Gas(
|
|
82
|
+
TX_DA_GAS_OVERHEAD,
|
|
83
|
+
tx.data.forPublic ? PUBLIC_TX_L2_GAS_OVERHEAD : PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
84
|
+
);
|
|
77
85
|
|
|
78
86
|
if (minGasLimits.gtAny(gasLimits)) {
|
|
79
87
|
this.#log.verbose(`Rejecting transaction due to the gas limit(s) not being above the minimum gas limit`, {
|
|
@@ -83,7 +91,7 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
83
91
|
return { result: 'invalid', reason: [TX_ERROR_INSUFFICIENT_GAS_LIMIT] };
|
|
84
92
|
}
|
|
85
93
|
|
|
86
|
-
if (gasLimits.l2Gas >
|
|
94
|
+
if (gasLimits.l2Gas > MAX_PROCESSABLE_L2_GAS) {
|
|
87
95
|
this.#log.verbose(`Rejecting transaction due to the gas limit(s) being higher than the maximum processable gas`, {
|
|
88
96
|
gasLimits,
|
|
89
97
|
minGasLimits,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import {
|
|
3
|
+
import { TX_ERROR_INVALID_EXPIRATION_TIMESTAMP, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
4
4
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
5
5
|
|
|
6
6
|
/** Structural interface for timestamp validation. */
|
|
7
7
|
export interface HasTimestampData {
|
|
8
8
|
txHash: { toString(): string };
|
|
9
9
|
data: {
|
|
10
|
-
|
|
10
|
+
expirationTimestamp: bigint;
|
|
11
11
|
constants: {
|
|
12
12
|
anchorBlockHeader: {
|
|
13
13
|
globalVariables: {
|
|
@@ -35,21 +35,21 @@ export class TimestampTxValidator<T extends HasTimestampData> implements TxValid
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
validateTx(tx: T): Promise<TxValidationResult> {
|
|
38
|
-
const
|
|
39
|
-
// If building block 1, we skip the expiration check. For details on why see the `
|
|
38
|
+
const expirationTimestamp = tx.data.expirationTimestamp;
|
|
39
|
+
// If building block 1, we skip the expiration check. For details on why see the `validate_expiration_timestamp`
|
|
40
40
|
// function in `noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/components/validation_requests.nr`.
|
|
41
41
|
const buildingBlock1 = this.values.blockNumber === 1;
|
|
42
42
|
|
|
43
|
-
if (!buildingBlock1 &&
|
|
43
|
+
if (!buildingBlock1 && expirationTimestamp < this.values.timestamp) {
|
|
44
44
|
if (tx.data.constants.anchorBlockHeader.globalVariables.blockNumber === 0) {
|
|
45
45
|
this.#log.warn(
|
|
46
46
|
`A tx built against a genesis block failed to be included in block 1 which is the only block in which txs built against a genesis block are allowed to be included.`,
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
this.#log.verbose(
|
|
50
|
-
`Rejecting tx ${tx.txHash} for low expiration timestamp. Tx expiration timestamp: ${
|
|
50
|
+
`Rejecting tx ${tx.txHash} for low expiration timestamp. Tx expiration timestamp: ${expirationTimestamp}, timestamp: ${this.values.timestamp}.`,
|
|
51
51
|
);
|
|
52
|
-
return Promise.resolve({ result: 'invalid', reason: [
|
|
52
|
+
return Promise.resolve({ result: 'invalid', reason: [TX_ERROR_INVALID_EXPIRATION_TIMESTAMP] });
|
|
53
53
|
} else {
|
|
54
54
|
return Promise.resolve({ result: 'valid' });
|
|
55
55
|
}
|