@aztec/p2p 0.0.1-commit.e588bc7e5 → 0.0.1-commit.e5a3663dd
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 +17 -16
- package/dest/client/p2p_client.d.ts +1 -1
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +9 -2
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +4 -1
- package/dest/config.d.ts +107 -99
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +16 -7
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -2
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +5 -3
- 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/eviction/index.d.ts +2 -1
- 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 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +4 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +5 -2
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +8 -5
- 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 +2 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +9 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +34 -10
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -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 +2 -2
- package/dest/msg_validators/clock_tolerance.d.ts +12 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +57 -0
- 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 +41 -9
- package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
- package/dest/msg_validators/tx_validator/factory.d.ts +2 -2
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +3 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +36 -4
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +50 -33
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +5 -5
- package/dest/services/dummy_service.d.ts +2 -1
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +1 -0
- package/dest/services/gossipsub/topic_score_params.d.ts +13 -2
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +21 -4
- package/dest/services/libp2p/instrumentation.d.ts +3 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +14 -0
- package/dest/services/libp2p/libp2p_service.d.ts +7 -18
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +52 -74
- 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 +15 -2
- package/dest/services/peer-manager/peer_scoring.d.ts +3 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +4 -0
- package/dest/services/reqresp/config.d.ts +3 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/interface.d.ts +14 -9
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +10 -11
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +0 -1
- package/dest/services/reqresp/protocols/index.d.ts +1 -2
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +0 -1
- package/dest/services/reqresp/protocols/tx.d.ts +1 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +1 -3
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
- package/dest/services/reqresp/reqresp.d.ts +4 -2
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +11 -2
- 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 +4 -1
- package/dest/test-helpers/mock-pubsub.d.ts +11 -3
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +36 -11
- package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +5 -3
- package/dest/test-helpers/testbench-utils.d.ts +1 -1
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +1 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +29 -2
- package/dest/testbench/worker_client_manager.d.ts +8 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +49 -0
- package/package.json +14 -14
- package/src/client/factory.ts +24 -19
- package/src/client/p2p_client.ts +11 -3
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +2 -0
- package/src/config.ts +28 -7
- package/src/mem_pools/attestation_pool/attestation_pool.ts +5 -3
- 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/eviction/index.ts +1 -0
- package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/interfaces.ts +3 -0
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +13 -7
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +2 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +38 -7
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +12 -2
- package/src/msg_validators/clock_tolerance.ts +75 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +11 -2
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +16 -2
- package/src/msg_validators/proposal_validator/proposal_validator.ts +47 -7
- package/src/msg_validators/tx_validator/README.md +11 -3
- package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/factory.ts +3 -1
- package/src/msg_validators/tx_validator/gas_validator.ts +82 -33
- package/src/services/data_store.ts +5 -13
- package/src/services/dummy_service.ts +1 -0
- package/src/services/gossipsub/topic_score_params.ts +36 -4
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +52 -70
- package/src/services/peer-manager/peer_manager.ts +17 -2
- package/src/services/peer-manager/peer_scoring.ts +6 -0
- package/src/services/reqresp/config.ts +2 -2
- package/src/services/reqresp/interface.ts +21 -11
- package/src/services/reqresp/metrics.ts +0 -1
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +1 -3
- package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
- package/src/services/reqresp/reqresp.ts +18 -1
- package/src/test-helpers/make-test-p2p-clients.ts +2 -0
- package/src/test-helpers/mock-pubsub.ts +34 -5
- package/src/test-helpers/reqresp-nodes.ts +4 -2
- package/src/test-helpers/testbench-utils.ts +1 -0
- package/src/testbench/p2p_client_testbench_worker.ts +30 -0
- package/src/testbench/worker_client_manager.ts +55 -0
- package/dest/services/reqresp/protocols/block.d.ts +0 -9
- package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
- package/dest/services/reqresp/protocols/block.js +0 -32
- package/src/services/reqresp/protocols/block.ts +0 -37
|
@@ -36,6 +36,18 @@ export interface HasGasLimitData {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/** Structural interface for types that carry max fee per gas data, used by {@link MaxFeePerGasValidator}. */
|
|
40
|
+
export interface HasMaxFeePerGasData {
|
|
41
|
+
txHash: { toString(): string };
|
|
42
|
+
data: {
|
|
43
|
+
constants: {
|
|
44
|
+
txContext: {
|
|
45
|
+
gasSettings: { maxFeesPerGas: GasFees };
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
/**
|
|
40
52
|
* Validates that a transaction's gas limits are within acceptable bounds.
|
|
41
53
|
*
|
|
@@ -87,7 +99,12 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
|
|
|
87
99
|
gasLimits,
|
|
88
100
|
minGasLimits,
|
|
89
101
|
});
|
|
90
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
result: 'invalid',
|
|
104
|
+
reason: [
|
|
105
|
+
`${TX_ERROR_INSUFFICIENT_GAS_LIMIT} (required=da:${minGasLimits.daGas},l2:${minGasLimits.l2Gas} got=da:${gasLimits.daGas},l2:${gasLimits.l2Gas})`,
|
|
106
|
+
],
|
|
107
|
+
};
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
|
|
@@ -97,7 +114,10 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
|
|
|
97
114
|
rollupManaLimit: this.#rollupManaLimit,
|
|
98
115
|
maxBlockL2Gas: this.#maxBlockL2Gas,
|
|
99
116
|
});
|
|
100
|
-
return {
|
|
117
|
+
return {
|
|
118
|
+
result: 'invalid',
|
|
119
|
+
reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (l2Gas=${gasLimits.l2Gas}, max=${this.#effectiveMaxL2Gas})`],
|
|
120
|
+
};
|
|
101
121
|
}
|
|
102
122
|
|
|
103
123
|
if (gasLimits.daGas > this.#effectiveMaxDAGas) {
|
|
@@ -106,22 +126,70 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
|
|
|
106
126
|
effectiveMaxDAGas: this.#effectiveMaxDAGas,
|
|
107
127
|
maxBlockDAGas: this.#maxBlockDAGas,
|
|
108
128
|
});
|
|
109
|
-
return {
|
|
129
|
+
return {
|
|
130
|
+
result: 'invalid',
|
|
131
|
+
reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (daGas=${gasLimits.daGas}, max=${this.#effectiveMaxDAGas})`],
|
|
132
|
+
};
|
|
110
133
|
}
|
|
111
134
|
|
|
112
135
|
return { result: 'valid' };
|
|
113
136
|
}
|
|
114
137
|
}
|
|
115
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Validates that a transaction's max fee per gas meets the current block's gas fees.
|
|
141
|
+
*
|
|
142
|
+
* Rejects transactions whose maxFeesPerGas is below the current block's gas fees
|
|
143
|
+
* on either dimension (DA or L2). This is a cheap, stateless check.
|
|
144
|
+
*
|
|
145
|
+
* Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
|
|
146
|
+
* (used during pending pool migration).
|
|
147
|
+
*
|
|
148
|
+
* Used by: pending pool migration (via factory), and indirectly by {@link GasTxValidator}.
|
|
149
|
+
*/
|
|
150
|
+
export class MaxFeePerGasValidator<T extends HasMaxFeePerGasData> implements TxValidator<T> {
|
|
151
|
+
#log: Logger;
|
|
152
|
+
#gasFees: GasFees;
|
|
153
|
+
|
|
154
|
+
constructor(gasFees: GasFees, bindings?: LoggerBindings) {
|
|
155
|
+
this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
|
|
156
|
+
this.#gasFees = gasFees;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
validateTx(tx: T): Promise<TxValidationResult> {
|
|
160
|
+
return Promise.resolve(this.validateMaxFeePerGas(tx));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Checks maxFeesPerGas >= current block gas fees on both dimensions. */
|
|
164
|
+
validateMaxFeePerGas(tx: T): TxValidationResult {
|
|
165
|
+
const maxFeesPerGas = tx.data.constants.txContext.gasSettings.maxFeesPerGas;
|
|
166
|
+
const notEnoughMaxFees =
|
|
167
|
+
maxFeesPerGas.feePerDaGas < this.#gasFees.feePerDaGas || maxFeesPerGas.feePerL2Gas < this.#gasFees.feePerL2Gas;
|
|
168
|
+
|
|
169
|
+
if (notEnoughMaxFees) {
|
|
170
|
+
this.#log.verbose(`Rejecting transaction ${tx.txHash.toString()} due to insufficient fee per gas`, {
|
|
171
|
+
txMaxFeesPerGas: maxFeesPerGas.toInspect(),
|
|
172
|
+
currentGasFees: this.#gasFees.toInspect(),
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
result: 'invalid',
|
|
176
|
+
reason: [
|
|
177
|
+
`${TX_ERROR_INSUFFICIENT_FEE_PER_GAS} (maxFee=da:${maxFeesPerGas.feePerDaGas},l2:${maxFeesPerGas.feePerL2Gas} required=da:${this.#gasFees.feePerDaGas},l2:${this.#gasFees.feePerL2Gas})`,
|
|
178
|
+
],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return { result: 'valid' };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
116
185
|
/**
|
|
117
186
|
* Validates that a transaction can pay its gas fees.
|
|
118
187
|
*
|
|
119
188
|
* Runs three checks in order:
|
|
120
189
|
* 1. **Gas limits** (delegates to {@link GasLimitsValidator}) — rejects if limits are
|
|
121
190
|
* out of bounds.
|
|
122
|
-
* 2. **Max fee per gas** —
|
|
123
|
-
* the current block's gas fees.
|
|
124
|
-
* become eligible in a later block with lower fees.
|
|
191
|
+
* 2. **Max fee per gas** — rejects the tx if its maxFeesPerGas is below
|
|
192
|
+
* the current block's gas fees.
|
|
125
193
|
* 3. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
|
|
126
194
|
* adds any pending claim from a setup-phase `_increase_public_balance` call, and
|
|
127
195
|
* rejects if the total is less than the tx's fee limit (gasLimits * maxFeePerGas).
|
|
@@ -155,37 +223,15 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
155
223
|
bindings: this.bindings,
|
|
156
224
|
}).validateGasLimit(tx);
|
|
157
225
|
if (gasLimitValidation.result === 'invalid') {
|
|
158
|
-
return
|
|
226
|
+
return gasLimitValidation;
|
|
159
227
|
}
|
|
160
|
-
|
|
161
|
-
|
|
228
|
+
const maxFeeValidation = new MaxFeePerGasValidator(this.#gasFees, this.bindings).validateMaxFeePerGas(tx);
|
|
229
|
+
if (maxFeeValidation.result === 'invalid') {
|
|
230
|
+
return maxFeeValidation;
|
|
162
231
|
}
|
|
163
232
|
return await this.validateTxFee(tx);
|
|
164
233
|
}
|
|
165
234
|
|
|
166
|
-
/**
|
|
167
|
-
* Check whether the tx's max fees are valid for the current block, and skip if not.
|
|
168
|
-
* We skip instead of invalidating since the tx may become eligible later.
|
|
169
|
-
* Note that circuits check max fees even if fee payer is unset, so we
|
|
170
|
-
* keep this validation even if the tx does not pay fees.
|
|
171
|
-
*/
|
|
172
|
-
#shouldSkip(tx: Tx): boolean {
|
|
173
|
-
const gasSettings = tx.data.constants.txContext.gasSettings;
|
|
174
|
-
|
|
175
|
-
// Skip the tx if its max fees are not enough for the current block's gas fees.
|
|
176
|
-
const maxFeesPerGas = gasSettings.maxFeesPerGas;
|
|
177
|
-
const notEnoughMaxFees =
|
|
178
|
-
maxFeesPerGas.feePerDaGas < this.#gasFees.feePerDaGas || maxFeesPerGas.feePerL2Gas < this.#gasFees.feePerL2Gas;
|
|
179
|
-
|
|
180
|
-
if (notEnoughMaxFees) {
|
|
181
|
-
this.#log.verbose(`Skipping transaction ${tx.getTxHash().toString()} due to insufficient fee per gas`, {
|
|
182
|
-
txMaxFeesPerGas: maxFeesPerGas.toInspect(),
|
|
183
|
-
currentGasFees: this.#gasFees.toInspect(),
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
return notEnoughMaxFees;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
235
|
/**
|
|
190
236
|
* Checks the fee payer has enough FeeJuice balance to cover the tx's fee limit.
|
|
191
237
|
* Accounts for any pending claim from a setup-phase `_increase_public_balance` call.
|
|
@@ -212,7 +258,10 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
212
258
|
balance,
|
|
213
259
|
feeLimit,
|
|
214
260
|
});
|
|
215
|
-
return {
|
|
261
|
+
return {
|
|
262
|
+
result: 'invalid',
|
|
263
|
+
reason: [`${TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE} (required=${feeLimit}, available=${balance})`],
|
|
264
|
+
};
|
|
216
265
|
}
|
|
217
266
|
return { result: 'valid' };
|
|
218
267
|
}
|
|
@@ -28,8 +28,6 @@ export class AztecDatastore implements Datastore {
|
|
|
28
28
|
#memoryDatastore: Map<string, MemoryItem>;
|
|
29
29
|
#dbDatastore: AztecAsyncMap<string, Uint8Array>;
|
|
30
30
|
|
|
31
|
-
#batchOps: BatchOp[] = [];
|
|
32
|
-
|
|
33
31
|
private maxMemoryItems: number;
|
|
34
32
|
|
|
35
33
|
constructor(db: AztecAsyncKVStore, { maxMemoryItems } = { maxMemoryItems: 50 }) {
|
|
@@ -92,23 +90,17 @@ export class AztecDatastore implements Datastore {
|
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
batch(): Batch {
|
|
93
|
+
const ops: BatchOp[] = [];
|
|
95
94
|
return {
|
|
96
95
|
put: (key, value) => {
|
|
97
|
-
|
|
98
|
-
type: 'put',
|
|
99
|
-
key,
|
|
100
|
-
value,
|
|
101
|
-
});
|
|
96
|
+
ops.push({ type: 'put', key, value });
|
|
102
97
|
},
|
|
103
98
|
delete: key => {
|
|
104
|
-
|
|
105
|
-
type: 'del',
|
|
106
|
-
key,
|
|
107
|
-
});
|
|
99
|
+
ops.push({ type: 'del', key });
|
|
108
100
|
},
|
|
109
101
|
commit: async () => {
|
|
110
102
|
await this.#db.transactionAsync(async () => {
|
|
111
|
-
for (const op of
|
|
103
|
+
for (const op of ops) {
|
|
112
104
|
if (op.type === 'put' && op.value) {
|
|
113
105
|
await this.put(op.key, op.value);
|
|
114
106
|
} else if (op.type === 'del') {
|
|
@@ -116,7 +108,7 @@ export class AztecDatastore implements Datastore {
|
|
|
116
108
|
}
|
|
117
109
|
}
|
|
118
110
|
});
|
|
119
|
-
|
|
111
|
+
ops.length = 0;
|
|
120
112
|
},
|
|
121
113
|
};
|
|
122
114
|
}
|
|
@@ -287,6 +287,7 @@ export class DummyPeerManager implements PeerManagerInterface {
|
|
|
287
287
|
|
|
288
288
|
export class DummyReqResp implements ReqRespInterface {
|
|
289
289
|
updateConfig(_config: Partial<P2PReqRespConfig>): void {}
|
|
290
|
+
setShouldRejectPeer(): void {}
|
|
290
291
|
start(
|
|
291
292
|
_subProtocolHandlers: ReqRespSubProtocolHandlers,
|
|
292
293
|
_subProtocolValidators: ReqRespSubProtocolValidators,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TopicType, createTopicString } from '@aztec/stdlib/p2p';
|
|
2
|
-
import {
|
|
2
|
+
import { createCheckpointTimingModel } from '@aztec/stdlib/timetable';
|
|
3
3
|
|
|
4
4
|
import { createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
5
5
|
|
|
@@ -9,12 +9,18 @@ import { createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
|
9
9
|
export type TopicScoringNetworkParams = {
|
|
10
10
|
/** L2 slot duration in milliseconds */
|
|
11
11
|
slotDurationMs: number;
|
|
12
|
+
/** L1 slot duration in seconds */
|
|
13
|
+
ethereumSlotDuration: number;
|
|
12
14
|
/** Gossipsub heartbeat interval in milliseconds */
|
|
13
15
|
heartbeatIntervalMs: number;
|
|
14
16
|
/** Target committee size (number of validators expected to attest per slot) */
|
|
15
17
|
targetCommitteeSize: number;
|
|
16
18
|
/** Duration per block in milliseconds when building multiple blocks per slot. If undefined, single block mode. */
|
|
17
19
|
blockDurationMs?: number;
|
|
20
|
+
/** Time budget in seconds reserved for L1 publishing. Defaults to ethereumSlotDuration. */
|
|
21
|
+
l1PublishingTime?: number;
|
|
22
|
+
/** One-way proposal/attestation propagation budget in seconds. */
|
|
23
|
+
p2pPropagationTime?: number;
|
|
18
24
|
/** Expected number of block proposals per slot for scoring override. 0 disables scoring, undefined falls back to blocksPerSlot - 1. */
|
|
19
25
|
expectedBlockProposalsPerSlot?: number;
|
|
20
26
|
};
|
|
@@ -25,10 +31,32 @@ export type TopicScoringNetworkParams = {
|
|
|
25
31
|
*
|
|
26
32
|
* @param slotDurationMs - L2 slot duration in milliseconds
|
|
27
33
|
* @param blockDurationMs - Duration per block in milliseconds (undefined = single block mode)
|
|
34
|
+
* @param opts - Shared checkpoint timing inputs used by the sequencer and validators
|
|
28
35
|
* @returns Number of blocks per slot
|
|
29
36
|
*/
|
|
30
|
-
export function calculateBlocksPerSlot(
|
|
31
|
-
|
|
37
|
+
export function calculateBlocksPerSlot(
|
|
38
|
+
slotDurationMs: number,
|
|
39
|
+
blockDurationMs: number | undefined,
|
|
40
|
+
opts?: {
|
|
41
|
+
ethereumSlotDuration: number;
|
|
42
|
+
l1PublishingTime?: number;
|
|
43
|
+
p2pPropagationTime?: number;
|
|
44
|
+
},
|
|
45
|
+
): number {
|
|
46
|
+
if (!opts) {
|
|
47
|
+
return createCheckpointTimingModel({
|
|
48
|
+
aztecSlotDuration: slotDurationMs / 1000,
|
|
49
|
+
blockDuration: blockDurationMs ? blockDurationMs / 1000 : undefined,
|
|
50
|
+
}).calculateMaxBlocksPerSlot();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return createCheckpointTimingModel({
|
|
54
|
+
aztecSlotDuration: slotDurationMs / 1000,
|
|
55
|
+
ethereumSlotDuration: opts.ethereumSlotDuration,
|
|
56
|
+
blockDuration: blockDurationMs ? blockDurationMs / 1000 : undefined,
|
|
57
|
+
l1PublishingTime: opts.l1PublishingTime ?? opts.ethereumSlotDuration,
|
|
58
|
+
p2pPropagationTime: opts.p2pPropagationTime,
|
|
59
|
+
}).calculateMaxBlocksPerSlot();
|
|
32
60
|
}
|
|
33
61
|
|
|
34
62
|
/**
|
|
@@ -279,7 +307,11 @@ export class TopicScoreParamsFactory {
|
|
|
279
307
|
const { slotDurationMs, heartbeatIntervalMs, blockDurationMs } = params;
|
|
280
308
|
|
|
281
309
|
// Compute values that are the same for all topics
|
|
282
|
-
this.blocksPerSlot = calculateBlocksPerSlot(slotDurationMs, blockDurationMs
|
|
310
|
+
this.blocksPerSlot = calculateBlocksPerSlot(slotDurationMs, blockDurationMs, {
|
|
311
|
+
ethereumSlotDuration: params.ethereumSlotDuration,
|
|
312
|
+
l1PublishingTime: params.l1PublishingTime,
|
|
313
|
+
p2pPropagationTime: params.p2pPropagationTime,
|
|
314
|
+
});
|
|
283
315
|
this.heartbeatsPerSlot = slotDurationMs / heartbeatIntervalMs;
|
|
284
316
|
this.invalidDecay = computeDecay(heartbeatIntervalMs, slotDurationMs, INVALID_DECAY_WINDOW_SLOTS);
|
|
285
317
|
|
|
@@ -18,6 +18,7 @@ export class P2PInstrumentation {
|
|
|
18
18
|
private messagePrevalidationCount: UpDownCounter;
|
|
19
19
|
private messageLatency: Histogram;
|
|
20
20
|
private txReceivedCount: UpDownCounter;
|
|
21
|
+
private slowValidationCount: UpDownCounter;
|
|
21
22
|
|
|
22
23
|
private aggLatencyHisto = new Map<TopicType, RecordableHistogram>();
|
|
23
24
|
private aggValidationHisto = new Map<TopicType, RecordableHistogram>();
|
|
@@ -48,6 +49,15 @@ export class P2PInstrumentation {
|
|
|
48
49
|
|
|
49
50
|
this.txReceivedCount = createUpDownCounterWithDefault(meter, Metrics.P2P_GOSSIP_TX_RECEIVED_COUNT);
|
|
50
51
|
|
|
52
|
+
this.slowValidationCount = createUpDownCounterWithDefault(meter, Metrics.P2P_GOSSIP_SLOW_VALIDATION_COUNT, {
|
|
53
|
+
[Attributes.TOPIC_NAME]: [
|
|
54
|
+
TopicType.tx,
|
|
55
|
+
TopicType.block_proposal,
|
|
56
|
+
TopicType.checkpoint_proposal,
|
|
57
|
+
TopicType.checkpoint_attestation,
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
|
|
51
61
|
this.aggLatencyMetrics = {
|
|
52
62
|
avg: meter.createObservableGauge(Metrics.P2P_GOSSIP_AGG_MESSAGE_LATENCY_AVG),
|
|
53
63
|
max: meter.createObservableGauge(Metrics.P2P_GOSSIP_AGG_MESSAGE_LATENCY_MAX),
|
|
@@ -87,6 +97,10 @@ export class P2PInstrumentation {
|
|
|
87
97
|
this.txReceivedCount.add(count);
|
|
88
98
|
}
|
|
89
99
|
|
|
100
|
+
public incSlowValidation(topicName: TopicType) {
|
|
101
|
+
this.slowValidationCount.add(1, { [Attributes.TOPIC_NAME]: topicName });
|
|
102
|
+
}
|
|
103
|
+
|
|
90
104
|
public incMessagePrevalidationStatus(passed: boolean, topicName: TopicType | undefined) {
|
|
91
105
|
this.messagePrevalidationCount.add(1, { [Attributes.TOPIC_NAME]: topicName, [Attributes.OK]: passed });
|
|
92
106
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import { maxBy } from '@aztec/foundation/collection';
|
|
4
|
-
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import { maxBy, merge } from '@aztec/foundation/collection';
|
|
5
4
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
6
5
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
7
6
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
7
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
9
8
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
10
|
-
import type { EthAddress,
|
|
9
|
+
import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
|
|
11
10
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
12
|
-
import { GasFees } from '@aztec/stdlib/gas';
|
|
11
|
+
import { type BlockMinFeesProvider, GasFees } from '@aztec/stdlib/gas';
|
|
13
12
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
14
13
|
import {
|
|
15
14
|
BlockProposal,
|
|
@@ -105,7 +104,6 @@ import {
|
|
|
105
104
|
ValidationError,
|
|
106
105
|
pingHandler,
|
|
107
106
|
reqGoodbyeHandler,
|
|
108
|
-
reqRespBlockHandler,
|
|
109
107
|
reqRespBlockTxsHandler,
|
|
110
108
|
reqRespStatusHandler,
|
|
111
109
|
reqRespTxHandler,
|
|
@@ -148,8 +146,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
148
146
|
private protocolVersion = '';
|
|
149
147
|
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
|
|
150
148
|
|
|
151
|
-
private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
|
|
152
|
-
|
|
153
149
|
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */
|
|
154
150
|
private duplicateProposalCallback?: (info: {
|
|
155
151
|
slot: SlotNumber;
|
|
@@ -199,6 +195,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
199
195
|
private epochCache: EpochCacheInterface,
|
|
200
196
|
private proofVerifier: ClientProtocolCircuitVerifier,
|
|
201
197
|
private worldStateSynchronizer: WorldStateSynchronizer,
|
|
198
|
+
private blockMinFeesProvider: BlockMinFeesProvider,
|
|
202
199
|
telemetry: TelemetryClient,
|
|
203
200
|
logger: Logger = createLogger('p2p:libp2p_service'),
|
|
204
201
|
) {
|
|
@@ -230,15 +227,27 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
230
227
|
this.protocolVersion,
|
|
231
228
|
);
|
|
232
229
|
|
|
230
|
+
const p2pPropagationTime = config.attestationPropagationTime;
|
|
233
231
|
const proposalValidatorOpts = {
|
|
234
232
|
txsPermitted: !config.disableTransactions,
|
|
235
233
|
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
234
|
+
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
|
|
235
|
+
p2pPropagationTime,
|
|
236
|
+
signatureContext: {
|
|
237
|
+
chainId: config.l1ChainId,
|
|
238
|
+
rollupAddress: config.l1Contracts.rollupAddress,
|
|
239
|
+
},
|
|
236
240
|
};
|
|
237
241
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
238
242
|
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
243
|
+
const attestationValidatorOpts = {
|
|
244
|
+
l1PublishingTime: config.l1PublishingTime,
|
|
245
|
+
p2pPropagationTime,
|
|
246
|
+
signatureContext: proposalValidatorOpts.signatureContext,
|
|
247
|
+
};
|
|
239
248
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
240
|
-
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
241
|
-
: new CheckpointAttestationValidator(epochCache);
|
|
249
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, attestationValidatorOpts)
|
|
250
|
+
: new CheckpointAttestationValidator(epochCache, attestationValidatorOpts);
|
|
242
251
|
|
|
243
252
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
244
253
|
|
|
@@ -263,8 +272,9 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
263
272
|
};
|
|
264
273
|
}
|
|
265
274
|
|
|
266
|
-
public updateConfig(config: Partial<P2PReqRespConfig
|
|
275
|
+
public updateConfig(config: Partial<P2PReqRespConfig & Pick<P2PConfig, 'skipIncomingProposals'>>) {
|
|
267
276
|
this.reqresp.updateConfig(config);
|
|
277
|
+
this.config = merge(this.config, config);
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
/**
|
|
@@ -283,6 +293,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
283
293
|
proofVerifier: ClientProtocolCircuitVerifier;
|
|
284
294
|
worldStateSynchronizer: WorldStateSynchronizer;
|
|
285
295
|
peerStore: AztecAsyncKVStore;
|
|
296
|
+
blockMinFeesProvider: BlockMinFeesProvider;
|
|
286
297
|
telemetry: TelemetryClient;
|
|
287
298
|
logger: Logger;
|
|
288
299
|
packageVersion: string;
|
|
@@ -295,6 +306,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
295
306
|
mempools,
|
|
296
307
|
proofVerifier,
|
|
297
308
|
peerStore,
|
|
309
|
+
blockMinFeesProvider,
|
|
298
310
|
telemetry,
|
|
299
311
|
logger,
|
|
300
312
|
packageVersion,
|
|
@@ -348,9 +360,12 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
348
360
|
const l1Constants = epochCache.getL1Constants();
|
|
349
361
|
const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
|
|
350
362
|
slotDurationMs: l1Constants.slotDuration * 1000,
|
|
363
|
+
ethereumSlotDuration: l1Constants.ethereumSlotDuration,
|
|
351
364
|
heartbeatIntervalMs: config.gossipsubInterval,
|
|
352
365
|
targetCommitteeSize: l1Constants.targetCommitteeSize,
|
|
353
366
|
blockDurationMs: config.blockDurationMs,
|
|
367
|
+
l1PublishingTime: config.l1PublishingTime,
|
|
368
|
+
p2pPropagationTime: config.attestationPropagationTime,
|
|
354
369
|
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
|
|
355
370
|
});
|
|
356
371
|
|
|
@@ -475,6 +490,9 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
475
490
|
epochCache,
|
|
476
491
|
);
|
|
477
492
|
|
|
493
|
+
// Gate req/resp data protocols for unauthenticated peers when p2pAllowOnlyValidators is enabled
|
|
494
|
+
reqresp.setShouldRejectPeer(peerId => peerManager.shouldDisableP2PGossip(peerId));
|
|
495
|
+
|
|
478
496
|
// Configure application-specific scoring for gossipsub.
|
|
479
497
|
// The weight scales app score to align with gossipsub thresholds:
|
|
480
498
|
// - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
|
|
@@ -495,6 +513,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
495
513
|
epochCache,
|
|
496
514
|
proofVerifier,
|
|
497
515
|
worldStateSynchronizer,
|
|
516
|
+
blockMinFeesProvider,
|
|
498
517
|
telemetry,
|
|
499
518
|
logger,
|
|
500
519
|
);
|
|
@@ -520,14 +539,12 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
520
539
|
// Create request response protocol handlers
|
|
521
540
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
522
541
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
523
|
-
const blockHandler = reqRespBlockHandler(this.archiver);
|
|
524
542
|
const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
|
|
525
543
|
|
|
526
544
|
const requestResponseHandlers: Partial<ReqRespSubProtocolHandlers> = {
|
|
527
545
|
[ReqRespSubProtocol.PING]: pingHandler,
|
|
528
546
|
[ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
|
|
529
547
|
[ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
|
|
530
|
-
[ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
|
|
531
548
|
};
|
|
532
549
|
|
|
533
550
|
if (!this.config.disableTransactions) {
|
|
@@ -548,7 +565,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
548
565
|
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
549
566
|
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
550
567
|
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
551
|
-
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
552
568
|
};
|
|
553
569
|
|
|
554
570
|
await this.peerManager.initializePeers();
|
|
@@ -835,6 +851,15 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
835
851
|
|
|
836
852
|
// Process the message, optionally within a linked span for trace propagation
|
|
837
853
|
const processMessage = async () => {
|
|
854
|
+
if (
|
|
855
|
+
this.config.skipIncomingProposals &&
|
|
856
|
+
(msg.topic === this.topicStrings[TopicType.block_proposal] ||
|
|
857
|
+
msg.topic === this.topicStrings[TopicType.checkpoint_proposal])
|
|
858
|
+
) {
|
|
859
|
+
this.logger.warn(`Ignoring incoming proposal (skipIncomingProposals is set)`, { topic: msg.topic });
|
|
860
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
838
863
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
839
864
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
840
865
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
@@ -912,6 +937,17 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
912
937
|
this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
|
|
913
938
|
}
|
|
914
939
|
|
|
940
|
+
const validationTimeMs = timer.ms();
|
|
941
|
+
const mcacheWindowMs = this.config.gossipsubMcacheLength * this.config.gossipsubInterval;
|
|
942
|
+
if (validationTimeMs > mcacheWindowMs * 0.75) {
|
|
943
|
+
this.instrumentation.incSlowValidation(topicType);
|
|
944
|
+
this.logger.warn(
|
|
945
|
+
`Gossip validation for ${topicType} took ${validationTimeMs}ms, approaching mcache eviction window of ${mcacheWindowMs}ms. ` +
|
|
946
|
+
`Message forwarding may be skipped if validation exceeds the window.`,
|
|
947
|
+
{ msgId, source: source.toString(), topicType, validationTimeMs, mcacheWindowMs },
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
|
|
915
951
|
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
916
952
|
this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
|
|
917
953
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
@@ -1574,53 +1610,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1574
1610
|
}
|
|
1575
1611
|
}
|
|
1576
1612
|
|
|
1577
|
-
/**
|
|
1578
|
-
* Validates a BLOCK response.
|
|
1579
|
-
*
|
|
1580
|
-
* If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
|
|
1581
|
-
* Penalizes on block number mismatch or hash mismatch.
|
|
1582
|
-
*
|
|
1583
|
-
* @param requestedBlockNumber - The requested block number.
|
|
1584
|
-
* @param responseBlock - The block returned by the peer.
|
|
1585
|
-
* @param peerId - The peer that returned the block.
|
|
1586
|
-
* @returns True if the response is valid, false otherwise.
|
|
1587
|
-
*/
|
|
1588
|
-
@trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
|
|
1589
|
-
[Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
|
|
1590
|
-
}))
|
|
1591
|
-
protected async validateRequestedBlock(
|
|
1592
|
-
requestedBlockNumber: Fr,
|
|
1593
|
-
responseBlock: L2Block,
|
|
1594
|
-
peerId: PeerId,
|
|
1595
|
-
): Promise<boolean> {
|
|
1596
|
-
try {
|
|
1597
|
-
const reqNum = Number(requestedBlockNumber.toString());
|
|
1598
|
-
if (responseBlock.number !== reqNum) {
|
|
1599
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
1600
|
-
return false;
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
|
-
const local = await this.archiver.getBlock(BlockNumber(reqNum));
|
|
1604
|
-
if (!local) {
|
|
1605
|
-
// We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
|
|
1606
|
-
// TODO: Consider extending this validator to accept an expected hash or
|
|
1607
|
-
// performing quorum-based checks when using P2P syncing prior to L1 sync.
|
|
1608
|
-
this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
|
|
1609
|
-
return false;
|
|
1610
|
-
}
|
|
1611
|
-
const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
|
|
1612
|
-
if (!localHash.equals(respHash)) {
|
|
1613
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
1614
|
-
return false;
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
return true;
|
|
1618
|
-
} catch (e) {
|
|
1619
|
-
this.logger.warn(`Error validating requested block`, e);
|
|
1620
|
-
return false;
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
|
|
1624
1613
|
protected async validateRequestedTx(
|
|
1625
1614
|
tx: Tx,
|
|
1626
1615
|
peerId: PeerId,
|
|
@@ -1647,15 +1636,8 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1647
1636
|
});
|
|
1648
1637
|
}
|
|
1649
1638
|
|
|
1650
|
-
private
|
|
1651
|
-
|
|
1652
|
-
return this.feesCache.gasFees;
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
const header = await this.archiver.getBlockHeader(blockNumber);
|
|
1656
|
-
const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
|
|
1657
|
-
this.feesCache = { blockNumber, gasFees };
|
|
1658
|
-
return gasFees;
|
|
1639
|
+
private getGasFees(): Promise<GasFees> {
|
|
1640
|
+
return this.blockMinFeesProvider.getCurrentMinFees();
|
|
1659
1641
|
}
|
|
1660
1642
|
|
|
1661
1643
|
/**
|
|
@@ -1697,7 +1679,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1697
1679
|
currentBlockNumber: BlockNumber,
|
|
1698
1680
|
nextSlotTimestamp: UInt64,
|
|
1699
1681
|
): Promise<Record<string, TransactionValidator>> {
|
|
1700
|
-
const gasFees = await this.getGasFees(
|
|
1682
|
+
const gasFees = await this.getGasFees();
|
|
1701
1683
|
const allowedInSetup = [
|
|
1702
1684
|
...(await getDefaultAllowedSetupFunctions()),
|
|
1703
1685
|
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
@@ -728,6 +728,12 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
728
728
|
return;
|
|
729
729
|
}
|
|
730
730
|
|
|
731
|
+
// Don't dial peers that have exceeded the auth failure threshold
|
|
732
|
+
if (!this.isNodeAllowedToConnect(peerId)) {
|
|
733
|
+
this.logger.trace(`Skipping peer ${peerId} due to failed auth handshake attempts`);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
731
737
|
const [multiaddrTcp] = await Promise.all([enr.getFullMultiaddr('tcp')]);
|
|
732
738
|
|
|
733
739
|
this.logger.trace(`Handling discovered peer ${peerId} at ${multiaddrTcp?.toString() ?? 'undefined address'}`);
|
|
@@ -985,14 +991,14 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
985
991
|
const peerIdStr = peerId.toString();
|
|
986
992
|
|
|
987
993
|
const existingEntry = this.failedAuthHandshakes.get(peerIdStr);
|
|
994
|
+
const failureCount = (existingEntry?.count || 0) + 1;
|
|
988
995
|
this.failedAuthHandshakes.set(peerIdStr, {
|
|
989
|
-
count:
|
|
996
|
+
count: failureCount,
|
|
990
997
|
lastFailureTimestamp: now,
|
|
991
998
|
});
|
|
992
999
|
|
|
993
1000
|
const connections = this.libP2PNode.getConnections(peerId);
|
|
994
1001
|
connections.forEach(conn => {
|
|
995
|
-
// We mark the IP address
|
|
996
1002
|
const address = conn.remoteAddr.nodeAddress().address;
|
|
997
1003
|
const existingAddressEntry = this.failedAuthHandshakes.get(address);
|
|
998
1004
|
this.failedAuthHandshakes.set(address, {
|
|
@@ -1000,6 +1006,15 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
1000
1006
|
lastFailureTimestamp: now,
|
|
1001
1007
|
});
|
|
1002
1008
|
});
|
|
1009
|
+
|
|
1010
|
+
// Ban the peer from being re-dialed for a cooldown period (exponential backoff)
|
|
1011
|
+
const banTimeMs = this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS;
|
|
1012
|
+
const backoffMs = banTimeMs * Math.pow(2, Math.min(failureCount - 1, 5));
|
|
1013
|
+
this.timedOutPeers.set(peerIdStr, {
|
|
1014
|
+
peerId: peerIdStr,
|
|
1015
|
+
timeoutUntilMs: now + backoffMs,
|
|
1016
|
+
});
|
|
1017
|
+
this.cachedPeers.delete(peerIdStr);
|
|
1003
1018
|
}
|
|
1004
1019
|
|
|
1005
1020
|
/*
|
|
@@ -135,6 +135,12 @@ export class PeerScoring {
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
/** Resets all peer scores. Useful for benchmarks to prevent cross-case contamination. */
|
|
139
|
+
resetAllScores(): void {
|
|
140
|
+
this.scores.clear();
|
|
141
|
+
this.lastUpdateTime.clear();
|
|
142
|
+
}
|
|
143
|
+
|
|
138
144
|
removePeer(peerId: string): void {
|
|
139
145
|
this.scores.delete(peerId);
|
|
140
146
|
this.lastUpdateTime.delete(peerId);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ConfigMappingsType, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
|
|
2
2
|
|
|
3
3
|
export const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS = 10_000;
|
|
4
4
|
export const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS = 10_000; // Not currently used
|
|
@@ -27,7 +27,7 @@ export interface P2PReqRespConfig {
|
|
|
27
27
|
dialTimeoutMs: number;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export const p2pReqRespConfigMappings:
|
|
30
|
+
export const p2pReqRespConfigMappings: ConfigMappingsType<P2PReqRespConfig> = {
|
|
31
31
|
overallRequestTimeoutMs: {
|
|
32
32
|
env: 'P2P_REQRESP_OVERALL_REQUEST_TIMEOUT_MS',
|
|
33
33
|
description: 'The overall timeout for a request response operation.',
|