@aztec/p2p 0.0.1-commit.ff7989d6c → 0.0.1-commit.fff30aa
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/README.md +129 -3
- package/dest/client/factory.d.ts +4 -5
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +29 -28
- package/dest/client/interface.d.ts +6 -13
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +5 -13
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +19 -88
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +1 -2
- package/dest/config.d.ts +32 -11
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +85 -31
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +4 -4
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +3 -2
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
- 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 +2 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +7 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +1 -1
- 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 +8 -6
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +2 -2
- 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/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +9 -7
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +46 -8
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +81 -17
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
- 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 +9 -10
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +5 -3
- 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 +3 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +2 -2
- 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 +50 -40
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +48 -36
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +35 -2
- package/dest/msg_validators/tx_validator/factory.d.ts +133 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +247 -60
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +67 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +104 -37
- 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/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
- package/dest/services/dummy_service.d.ts +2 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +1 -4
- package/dest/services/encoding.d.ts +6 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +14 -8
- package/dest/services/libp2p/libp2p_service.d.ts +15 -13
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +92 -92
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
- package/dest/services/reqresp/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +17 -9
- package/dest/services/service.d.ts +2 -2
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +39 -29
- package/dest/services/tx_collection/tx_source.d.ts +6 -5
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +9 -7
- package/dest/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +4 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +1 -2
- package/dest/test-helpers/mock-pubsub.d.ts +2 -3
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +2 -2
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -2
- package/dest/test-helpers/testbench-utils.d.ts +2 -2
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +2 -1
- package/dest/testbench/p2p_client_testbench_worker.js +7 -6
- package/dest/testbench/worker_client_manager.d.ts +3 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +4 -1
- package/package.json +14 -14
- package/src/client/factory.ts +49 -46
- package/src/client/interface.ts +5 -19
- package/src/client/p2p_client.ts +20 -118
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +1 -2
- package/src/config.ts +124 -34
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
- package/src/mem_pools/tx_pool/priority.ts +4 -4
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
- package/src/mem_pools/tx_pool_v2/README.md +9 -1
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +3 -2
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +11 -1
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +2 -2
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +15 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +2 -1
- package/src/mem_pools/tx_pool_v2/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/interfaces.ts +9 -7
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +113 -18
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +11 -11
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +14 -2
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +57 -39
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +63 -40
- package/src/msg_validators/tx_validator/README.md +119 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
- package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +42 -1
- package/src/msg_validators/tx_validator/factory.ts +394 -78
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +123 -27
- package/src/msg_validators/tx_validator/index.ts +2 -0
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
- package/src/services/dummy_service.ts +1 -5
- package/src/services/encoding.ts +14 -7
- package/src/services/libp2p/libp2p_service.ts +106 -101
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/reqresp.ts +19 -11
- package/src/services/service.ts +1 -1
- package/src/services/tx_collection/file_store_tx_source.ts +43 -31
- package/src/services/tx_collection/tx_source.ts +8 -7
- package/src/services/tx_provider.ts +2 -2
- package/src/test-helpers/make-test-p2p-clients.ts +0 -2
- package/src/test-helpers/mock-pubsub.ts +3 -6
- package/src/test-helpers/reqresp-nodes.ts +2 -5
- package/src/test-helpers/testbench-utils.ts +2 -1
- package/src/testbench/p2p_client_testbench_worker.ts +3 -6
- package/src/testbench/worker_client_manager.ts +11 -4
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
|
@@ -1,5 +1,6 @@
|
|
|
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';
|
|
3
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
5
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
5
6
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
@@ -16,13 +17,13 @@ import {
|
|
|
16
17
|
CheckpointProposal,
|
|
17
18
|
type CheckpointProposalCore,
|
|
18
19
|
type Gossipable,
|
|
19
|
-
P2PClientType,
|
|
20
20
|
P2PMessage,
|
|
21
21
|
type ValidationResult as P2PValidationResult,
|
|
22
22
|
PeerErrorSeverity,
|
|
23
|
+
PeerErrorSeverityByHarshness,
|
|
23
24
|
TopicType,
|
|
24
25
|
createTopicString,
|
|
25
|
-
|
|
26
|
+
getTopicsForConfig,
|
|
26
27
|
metricsTopicStrToLabels,
|
|
27
28
|
} from '@aztec/stdlib/p2p';
|
|
28
29
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -69,9 +70,11 @@ import {
|
|
|
69
70
|
} from '../../msg_validators/index.js';
|
|
70
71
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
71
72
|
import {
|
|
72
|
-
type
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
type TransactionValidator,
|
|
74
|
+
createFirstStageTxValidationsForGossipedTransactions,
|
|
75
|
+
createSecondStageTxValidationsForGossipedTransactions,
|
|
76
|
+
createTxValidatorForBlockProposalReceivedTxs,
|
|
77
|
+
createTxValidatorForReqResponseReceivedTxs,
|
|
75
78
|
} from '../../msg_validators/tx_validator/factory.js';
|
|
76
79
|
import { GossipSubEvent } from '../../types/index.js';
|
|
77
80
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
@@ -87,6 +90,9 @@ import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
|
87
90
|
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
88
91
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
89
92
|
import {
|
|
93
|
+
AuthRequest,
|
|
94
|
+
BlockTxsRequest,
|
|
95
|
+
BlockTxsResponse,
|
|
90
96
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
91
97
|
type ReqRespInterface,
|
|
92
98
|
type ReqRespResponse,
|
|
@@ -94,14 +100,9 @@ import {
|
|
|
94
100
|
type ReqRespSubProtocolHandler,
|
|
95
101
|
type ReqRespSubProtocolHandlers,
|
|
96
102
|
type ReqRespSubProtocolValidators,
|
|
103
|
+
StatusMessage,
|
|
97
104
|
type SubProtocolMap,
|
|
98
105
|
ValidationError,
|
|
99
|
-
} from '../reqresp/index.js';
|
|
100
|
-
import {
|
|
101
|
-
AuthRequest,
|
|
102
|
-
BlockTxsRequest,
|
|
103
|
-
BlockTxsResponse,
|
|
104
|
-
StatusMessage,
|
|
105
106
|
pingHandler,
|
|
106
107
|
reqGoodbyeHandler,
|
|
107
108
|
reqRespBlockHandler,
|
|
@@ -135,7 +136,7 @@ type ReceivedMessageValidationResult<T, M = undefined> =
|
|
|
135
136
|
/**
|
|
136
137
|
* Lib P2P implementation of the P2PService interface.
|
|
137
138
|
*/
|
|
138
|
-
export class LibP2PService
|
|
139
|
+
export class LibP2PService extends WithTracer implements P2PService {
|
|
139
140
|
private discoveryRunningPromise?: RunningPromise;
|
|
140
141
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
141
142
|
|
|
@@ -182,7 +183,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
182
183
|
protected logger: Logger;
|
|
183
184
|
|
|
184
185
|
constructor(
|
|
185
|
-
private clientType: T,
|
|
186
186
|
private config: P2PConfig,
|
|
187
187
|
protected node: PubSubLibp2p,
|
|
188
188
|
private peerDiscoveryService: PeerDiscoveryService,
|
|
@@ -224,10 +224,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
224
224
|
this.protocolVersion,
|
|
225
225
|
);
|
|
226
226
|
|
|
227
|
-
|
|
228
|
-
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
227
|
+
const proposalValidatorOpts = {
|
|
229
228
|
txsPermitted: !config.disableTransactions,
|
|
230
|
-
|
|
229
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
230
|
+
};
|
|
231
|
+
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
232
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
231
233
|
this.checkpointAttestationValidator = config.fishermanMode
|
|
232
234
|
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
233
235
|
: new CheckpointAttestationValidator(epochCache);
|
|
@@ -235,11 +237,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
235
237
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
236
238
|
|
|
237
239
|
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
238
|
-
this.logger.
|
|
239
|
-
`Handler not yet registered
|
|
240
|
+
this.logger.warn(
|
|
241
|
+
`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
|
|
240
242
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
241
243
|
);
|
|
242
|
-
return
|
|
244
|
+
return true;
|
|
243
245
|
};
|
|
244
246
|
|
|
245
247
|
this.checkpointReceivedCallback = (
|
|
@@ -262,8 +264,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
262
264
|
* @param txPool - The transaction pool to be accessed by the service.
|
|
263
265
|
* @returns The new service.
|
|
264
266
|
*/
|
|
265
|
-
public static async new
|
|
266
|
-
clientType: T,
|
|
267
|
+
public static async new(
|
|
267
268
|
config: P2PConfig,
|
|
268
269
|
peerId: PeerId,
|
|
269
270
|
deps: {
|
|
@@ -475,7 +476,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
475
476
|
peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
|
|
476
477
|
|
|
477
478
|
return new LibP2PService(
|
|
478
|
-
clientType,
|
|
479
479
|
config,
|
|
480
480
|
node,
|
|
481
481
|
peerDiscoveryService,
|
|
@@ -549,7 +549,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
549
549
|
await this.node.start();
|
|
550
550
|
|
|
551
551
|
// Subscribe to standard GossipSub topics by default
|
|
552
|
-
for (const topic of
|
|
552
|
+
for (const topic of getTopicsForConfig(this.config.disableTransactions)) {
|
|
553
553
|
this.subscribeToTopic(this.topicStrings[topic]);
|
|
554
554
|
}
|
|
555
555
|
|
|
@@ -818,9 +818,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
818
818
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
819
819
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
820
820
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
821
|
-
|
|
822
|
-
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
823
|
-
}
|
|
821
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
824
822
|
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
825
823
|
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
826
824
|
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
@@ -906,15 +904,45 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
906
904
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
907
905
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
908
906
|
const tx = Tx.fromBuffer(payloadData);
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
907
|
+
|
|
908
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
909
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
910
|
+
|
|
911
|
+
// Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
|
|
912
|
+
const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
913
|
+
const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
|
|
914
|
+
if (!firstStageOutcome.allPassed) {
|
|
915
|
+
const { name } = firstStageOutcome.failure;
|
|
916
|
+
let { severity } = firstStageOutcome.failure;
|
|
917
|
+
|
|
918
|
+
// Double spend validator has a special case handler. We perform more detailed examination
|
|
919
|
+
// as to how recently the nullifier was entered into the tree and if the transaction should
|
|
920
|
+
// have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
|
|
921
|
+
if (name === 'doubleSpendValidator') {
|
|
922
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1);
|
|
923
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
this.peerManager.penalizePeer(source, severity);
|
|
927
|
+
return { result: TopicValidatorResult.Reject };
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
931
|
+
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
932
|
+
if (canAdd === 'ignored') {
|
|
933
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
// Stage 2: expensive proof verification
|
|
937
|
+
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
938
|
+
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
939
|
+
if (!secondStageOutcome.allPassed) {
|
|
940
|
+
const { severity } = secondStageOutcome.failure;
|
|
941
|
+
this.peerManager.penalizePeer(source, severity);
|
|
914
942
|
return { result: TopicValidatorResult.Reject };
|
|
915
943
|
}
|
|
916
944
|
|
|
917
|
-
//
|
|
945
|
+
// Pool add: persist the tx
|
|
918
946
|
const txHash = tx.getTxHash();
|
|
919
947
|
const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
|
|
920
948
|
|
|
@@ -922,7 +950,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
922
950
|
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
923
951
|
|
|
924
952
|
this.logger.trace(`Validate propagated tx`, {
|
|
925
|
-
isValid,
|
|
926
953
|
wasAccepted,
|
|
927
954
|
wasIgnored,
|
|
928
955
|
[Attributes.P2P_ID]: source.toString(),
|
|
@@ -933,6 +960,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
933
960
|
} else if (wasIgnored) {
|
|
934
961
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
935
962
|
} else {
|
|
963
|
+
this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
|
|
964
|
+
source: source.toString(),
|
|
965
|
+
txHash: txHash.toString(),
|
|
966
|
+
});
|
|
967
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.HighToleranceError);
|
|
936
968
|
return { result: TopicValidatorResult.Reject };
|
|
937
969
|
}
|
|
938
970
|
};
|
|
@@ -1165,7 +1197,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1165
1197
|
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1166
1198
|
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1167
1199
|
if (!isValid) {
|
|
1168
|
-
this.logger.
|
|
1200
|
+
this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1169
1201
|
}
|
|
1170
1202
|
}
|
|
1171
1203
|
|
|
@@ -1537,43 +1569,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1537
1569
|
}
|
|
1538
1570
|
|
|
1539
1571
|
protected createRequestedTxValidator(): TxValidator {
|
|
1540
|
-
return
|
|
1572
|
+
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1541
1573
|
l1ChainId: this.config.l1ChainId,
|
|
1542
1574
|
rollupVersion: this.config.rollupVersion,
|
|
1543
1575
|
});
|
|
1544
1576
|
}
|
|
1545
1577
|
|
|
1546
|
-
@trackSpan('Libp2pService.validatePropagatedTx', tx => ({
|
|
1547
|
-
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
1548
|
-
}))
|
|
1549
|
-
protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
|
|
1550
|
-
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1551
|
-
|
|
1552
|
-
// We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
|
|
1553
|
-
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1554
|
-
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1555
|
-
|
|
1556
|
-
for (const validator of messageValidators) {
|
|
1557
|
-
const outcome = await this.runValidations(tx, validator);
|
|
1558
|
-
|
|
1559
|
-
if (outcome.allPassed) {
|
|
1560
|
-
continue;
|
|
1561
|
-
}
|
|
1562
|
-
const { name } = outcome.failure;
|
|
1563
|
-
let { severity } = outcome.failure;
|
|
1564
|
-
|
|
1565
|
-
// Double spend validator has a special case handler
|
|
1566
|
-
if (name === 'doubleSpendValidator') {
|
|
1567
|
-
const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
|
|
1568
|
-
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1572
|
-
return false;
|
|
1573
|
-
}
|
|
1574
|
-
return true;
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
1578
|
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
1578
1579
|
if (blockNumber === this.feesCache?.blockNumber) {
|
|
1579
1580
|
return this.feesCache.gasFees;
|
|
@@ -1601,60 +1602,62 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1601
1602
|
};
|
|
1602
1603
|
}
|
|
1603
1604
|
|
|
1604
|
-
public async
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1605
|
+
public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
|
|
1606
|
+
const validator = createTxValidatorForBlockProposalReceivedTxs(
|
|
1607
|
+
this.proofVerifier,
|
|
1608
|
+
{ l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
|
|
1609
|
+
this.logger.getBindings(),
|
|
1610
|
+
);
|
|
1610
1611
|
|
|
1611
|
-
await Promise.all(
|
|
1612
|
+
const results = await Promise.all(
|
|
1612
1613
|
txs.map(async tx => {
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
if (!outcome.allPassed) {
|
|
1616
|
-
throw new Error('Invalid tx detected', { cause: { outcome } });
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1614
|
+
const result = await validator.validateTx(tx);
|
|
1615
|
+
return result.result !== 'invalid';
|
|
1619
1616
|
}),
|
|
1620
1617
|
);
|
|
1618
|
+
if (results.some(value => value === false)) {
|
|
1619
|
+
throw new Error('Invalid tx detected');
|
|
1620
|
+
}
|
|
1621
1621
|
}
|
|
1622
1622
|
|
|
1623
|
-
/**
|
|
1624
|
-
|
|
1625
|
-
*
|
|
1626
|
-
* Each validator is a pair of a validator and a severity.
|
|
1627
|
-
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
1628
|
-
*
|
|
1629
|
-
* @param currentBlockNumber - The current synced block number.
|
|
1630
|
-
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
1631
|
-
* @returns The message validators.
|
|
1632
|
-
*/
|
|
1633
|
-
private async createMessageValidators(
|
|
1623
|
+
/** Creates the first stage (fast) validators for gossiped transactions. */
|
|
1624
|
+
protected async createFirstStageMessageValidators(
|
|
1634
1625
|
currentBlockNumber: BlockNumber,
|
|
1635
1626
|
nextSlotTimestamp: UInt64,
|
|
1636
|
-
): Promise<Record<string,
|
|
1627
|
+
): Promise<Record<string, TransactionValidator>> {
|
|
1637
1628
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
1638
|
-
const allowedInSetup =
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1629
|
+
const allowedInSetup = [
|
|
1630
|
+
...(await getDefaultAllowedSetupFunctions()),
|
|
1631
|
+
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
1632
|
+
];
|
|
1633
|
+
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1634
|
+
const l1Constants = await this.archiver.getL1Constants();
|
|
1635
|
+
|
|
1636
|
+
return createFirstStageTxValidationsForGossipedTransactions(
|
|
1643
1637
|
nextSlotTimestamp,
|
|
1644
|
-
|
|
1638
|
+
blockNumber,
|
|
1645
1639
|
this.worldStateSynchronizer,
|
|
1646
1640
|
gasFees,
|
|
1647
1641
|
this.config.l1ChainId,
|
|
1648
1642
|
this.config.rollupVersion,
|
|
1649
1643
|
protocolContractsHash,
|
|
1650
1644
|
this.archiver,
|
|
1651
|
-
this.proofVerifier,
|
|
1652
1645
|
!this.config.disableTransactions,
|
|
1653
1646
|
allowedInSetup,
|
|
1654
1647
|
this.logger.getBindings(),
|
|
1648
|
+
{
|
|
1649
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
1650
|
+
maxBlockL2Gas: this.config.validateMaxL2BlockGas,
|
|
1651
|
+
maxBlockDAGas: this.config.validateMaxDABlockGas,
|
|
1652
|
+
},
|
|
1655
1653
|
);
|
|
1656
1654
|
}
|
|
1657
1655
|
|
|
1656
|
+
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
|
|
1657
|
+
protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
|
|
1658
|
+
return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1658
1661
|
/**
|
|
1659
1662
|
* Run validations on a tx.
|
|
1660
1663
|
* @param tx - The tx to validate.
|
|
@@ -1663,7 +1666,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1663
1666
|
*/
|
|
1664
1667
|
private async runValidations(
|
|
1665
1668
|
tx: Tx,
|
|
1666
|
-
messageValidators: Record<string,
|
|
1669
|
+
messageValidators: Record<string, TransactionValidator>,
|
|
1667
1670
|
): Promise<ValidationOutcome> {
|
|
1668
1671
|
const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
|
|
1669
1672
|
const { result } = await validator.validateTx(tx);
|
|
@@ -1672,8 +1675,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1672
1675
|
|
|
1673
1676
|
// A promise that resolves when all validations have been run
|
|
1674
1677
|
const allValidations = await Promise.all(validationPromises);
|
|
1675
|
-
const
|
|
1676
|
-
if (
|
|
1678
|
+
const failures = allValidations.filter(x => !x.isValid);
|
|
1679
|
+
if (failures.length > 0) {
|
|
1680
|
+
// Pick the most severe failure (lowest tolerance = harshest penalty)
|
|
1681
|
+
const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
|
|
1677
1682
|
return {
|
|
1678
1683
|
allPassed: false,
|
|
1679
1684
|
failure: {
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# ReqResp Protocols
|
|
2
|
+
|
|
3
|
+
This module implements libp2p request-response protocols for the Aztec P2P network. All protocols share common transport-level validation (rate limiting, timeouts, Snappy decompression, error penalties) with protocol-specific logic layered on top.
|
|
4
|
+
|
|
5
|
+
## Common Transport Validation
|
|
6
|
+
|
|
7
|
+
### Rate Limiting (Responder Side)
|
|
8
|
+
|
|
9
|
+
Applied before the protocol handler runs.
|
|
10
|
+
|
|
11
|
+
| Protocol | Peer Limit | Global Limit | File |
|
|
12
|
+
|----------|-----------|-------------|------|
|
|
13
|
+
| PING | 5/s | 10/s | `rate-limiter/rate_limits.ts` |
|
|
14
|
+
| STATUS | 5/s | 10/s | same |
|
|
15
|
+
| AUTH | 5/s | 10/s | same |
|
|
16
|
+
| GOODBYE | 5/s | 10/s | same |
|
|
17
|
+
| BLOCK | 2/s | 5/s | same |
|
|
18
|
+
| BLOCK_TXS | 10/s | 200/s | same |
|
|
19
|
+
| TX | (see rate limits file) | (see rate limits file) | same |
|
|
20
|
+
|
|
21
|
+
- Per-peer limit exceeded: `HighToleranceError` penalty + `RATE_LIMIT_EXCEEDED` status. Penalty fires inside `RequestResponseRateLimiter.allow()`, not the stream handler.
|
|
22
|
+
- Global limit exceeded: `RATE_LIMIT_EXCEEDED` status only (no peer penalty).
|
|
23
|
+
|
|
24
|
+
### Response Status Byte (Requester Side)
|
|
25
|
+
|
|
26
|
+
| Rule | Consequence | File |
|
|
27
|
+
|------|-------------|------|
|
|
28
|
+
| First chunk must be exactly 1 byte | `ReqRespStatusError(UNKNOWN)` | `status.ts` |
|
|
29
|
+
| Byte must be valid `ReqRespStatus` enum (0-4, 126, 127) | `ReqRespStatusError(UNKNOWN)` | same |
|
|
30
|
+
|
|
31
|
+
Note: `prettyPrintReqRespStatus` is missing a `NOT_FOUND` case (minor logging bug).
|
|
32
|
+
|
|
33
|
+
### Snappy Decompression (Requester Side)
|
|
34
|
+
|
|
35
|
+
Per-protocol size limits checked via preamble before decompression.
|
|
36
|
+
|
|
37
|
+
### Timeouts (Requester Side)
|
|
38
|
+
|
|
39
|
+
| Timeout | Default | Penalty |
|
|
40
|
+
|---------|---------|---------|
|
|
41
|
+
| Individual request | 10s | HighToleranceError |
|
|
42
|
+
| Dial | 5s | HighToleranceError |
|
|
43
|
+
|
|
44
|
+
### Error Penalty Categorization (Requester Side)
|
|
45
|
+
|
|
46
|
+
| Error Type | Severity |
|
|
47
|
+
|------------|----------|
|
|
48
|
+
| GOODBYE subprotocol errors | None |
|
|
49
|
+
| `CollectiveReqRespTimeoutError` / `InvalidResponseError` | None |
|
|
50
|
+
| `AbortError` / connection close / muxer closed | None |
|
|
51
|
+
| `ECONNRESET` / `EPIPE` / `ECONNREFUSED` / `ERR_UNEXPECTED_EOF` | HighToleranceError |
|
|
52
|
+
| `ERR_UNSUPPORTED_PROTOCOL` | HighToleranceError |
|
|
53
|
+
| `IndividualReqRespTimeoutError` / `TimeoutError` | HighToleranceError |
|
|
54
|
+
| Catch-all | HighToleranceError |
|
|
55
|
+
|
|
56
|
+
### Request Error Penalty (Responder Side)
|
|
57
|
+
|
|
58
|
+
| Error Type | Severity |
|
|
59
|
+
|------------|----------|
|
|
60
|
+
| `BADLY_FORMED_REQUEST` | LowToleranceError |
|
|
61
|
+
| All others | None |
|
|
62
|
+
|
|
63
|
+
### Notes
|
|
64
|
+
|
|
65
|
+
- Request payloads are NOT snappy-compressed (asymmetric: only responses use snappy).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Handshake Protocols
|
|
70
|
+
|
|
71
|
+
### Connection-Level Gating (Before Any Handshake)
|
|
72
|
+
|
|
73
|
+
| Rule | Consequence | File |
|
|
74
|
+
|------|-------------|------|
|
|
75
|
+
| Deny inbound connection from IP/peerId with too many failed auth handshakes | Connection denied | `libp2p_service.ts` |
|
|
76
|
+
| Threshold: `p2pMaxFailedAuthAttemptsAllowed` (default 3) | Tracked per peerId AND per IP | `peer_manager.ts` |
|
|
77
|
+
| Failed auth entries expire after 1 hour | Peer can reconnect; no escalating penalty for repeat offenders | same |
|
|
78
|
+
|
|
79
|
+
### Handshake Trigger Logic (`peer:connect`)
|
|
80
|
+
|
|
81
|
+
1. `p2pDisableStatusHandshake` = true: no handshake
|
|
82
|
+
2. `p2pAllowOnlyValidators` = false: STATUS handshake
|
|
83
|
+
3. Peer is protected (trusted/private/preferred): STATUS handshake
|
|
84
|
+
4. Otherwise: AUTH handshake (superset of STATUS)
|
|
85
|
+
|
|
86
|
+
Config constraint: `p2pDisableStatusHandshake && p2pAllowOnlyValidators` is disallowed.
|
|
87
|
+
|
|
88
|
+
### STATUS Protocol (`/aztec/req/status/1.0.0`)
|
|
89
|
+
|
|
90
|
+
**Requester side** (`peer_manager.ts`):
|
|
91
|
+
|
|
92
|
+
| Rule | Consequence |
|
|
93
|
+
|------|-------------|
|
|
94
|
+
| Response status must be SUCCESS | Peer scheduled for disconnect |
|
|
95
|
+
| `compressedComponentsVersion` must match | Peer scheduled for disconnect |
|
|
96
|
+
| Any exception | Peer scheduled for disconnect |
|
|
97
|
+
|
|
98
|
+
`StatusMessage.validate()` currently only checks `compressedComponentsVersion`. Fields `latestBlockNumber`, `latestBlockHash`, `finalizedBlockNumber` are NOT validated (TODO in code).
|
|
99
|
+
|
|
100
|
+
**Responder side**: no validation of incoming request content (always responds with own status). This means the requester leaks its blockchain state to any peer before validation.
|
|
101
|
+
|
|
102
|
+
**Deserialization bounds**: `MAX_VERSION_STRING_LENGTH` = 64 bytes, `MAX_BLOCK_HASH_STRING_LENGTH` = 128 bytes. Expected response size: 1 KB.
|
|
103
|
+
|
|
104
|
+
### AUTH Protocol (`/aztec/req/auth/1.0.0`)
|
|
105
|
+
|
|
106
|
+
**Requester side** (`peer_manager.ts`):
|
|
107
|
+
|
|
108
|
+
| # | Rule | Consequence |
|
|
109
|
+
|---|------|-------------|
|
|
110
|
+
| 1 | Response status is SUCCESS | `markAuthHandshakeFailed` + disconnect |
|
|
111
|
+
| 2 | `compressedComponentsVersion` match | `markAuthHandshakeFailed` + disconnect |
|
|
112
|
+
| 3 | Valid ECDSA signature recovery from challenge response | `markAuthHandshakeFailed` + disconnect |
|
|
113
|
+
| 4 | Recovered address is a registered validator | `markAuthHandshakeFailed` + disconnect |
|
|
114
|
+
| 5 | Validator address not already authenticated to different peerId | Silent return (no disconnect, no failure marking -- peer stays connected but unauthenticated) |
|
|
115
|
+
| 6 | Any exception | `markAuthHandshakeFailed` + disconnect |
|
|
116
|
+
|
|
117
|
+
Challenge: random `Fr`, payload = `keccak256("Aztec Validator Challenge:" + challenge)`, signed with `eth_sign` style. Challenge is NOT bound to peer identity (transport encryption via Noise is the binding layer).
|
|
118
|
+
|
|
119
|
+
On success: peer added to authenticated maps, prior failures cleared (including IP-based ones -- shared-IP peers benefit from a legitimate validator's success).
|
|
120
|
+
|
|
121
|
+
**Responder side** (`validator-client/src/validator.ts` + `peer_manager.ts`):
|
|
122
|
+
|
|
123
|
+
| # | Rule | Consequence |
|
|
124
|
+
|---|------|-------------|
|
|
125
|
+
| 1 | Peer must be protected (`shouldTrustWithIdentity` in `peer_manager.ts`) | Returns empty buffer (SUCCESS status + empty payload -> requester gets parse error -> `markAuthHandshakeFailed`) |
|
|
126
|
+
| 2 | Node must have registered validator address | Returns empty buffer (same consequence) |
|
|
127
|
+
|
|
128
|
+
**Unauthenticated peer gossip**: when `p2pAllowOnlyValidators` is true, unauthenticated peers get `appSpecificScore = -Infinity`, completely excluding them from all gossip.
|
|
129
|
+
|
|
130
|
+
### PING Protocol (`/aztec/req/ping/1.0.0`)
|
|
131
|
+
|
|
132
|
+
No validation on either side. Responder returns `Buffer.from('pong')`. Expected response: 1 KB.
|
|
133
|
+
|
|
134
|
+
### GOODBYE Protocol (`/aztec/req/goodbye/1.0.0`)
|
|
135
|
+
|
|
136
|
+
**Responder**: buffer must be 1 byte (defaults to `UNKNOWN` on invalid length). Goodbye reason byte is NOT validated against the enum -- any byte 0-255 accepted. Peer scheduled for disconnect regardless of reason.
|
|
137
|
+
|
|
138
|
+
**Requester**: response errors are never penalized (GOODBYE subprotocol exempt from error categorization).
|
|
139
|
+
|
|
140
|
+
### Periodic Re-validation
|
|
141
|
+
|
|
142
|
+
| Rule | Interval | File |
|
|
143
|
+
|------|----------|------|
|
|
144
|
+
| Authenticated validators re-checked against current validator set | Every heartbeat (`peerCheckIntervalMS`) | `peer_manager.ts` |
|
|
145
|
+
| If validator address no longer registered, auth entry removed | Same | same |
|
|
146
|
+
|
|
147
|
+
Protected peers (private/trusted/preferred) are always considered "authenticated" without AUTH handshake.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Block Data Protocols
|
|
152
|
+
|
|
153
|
+
### BLOCK Protocol (`/aztec/req/block/1.0.0`)
|
|
154
|
+
|
|
155
|
+
**Server side**:
|
|
156
|
+
|
|
157
|
+
| Rule | Consequence | File |
|
|
158
|
+
|------|-------------|------|
|
|
159
|
+
| Request must parse as `Fr` | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block.ts` |
|
|
160
|
+
| Block lookup throws | `INTERNAL_ERROR` status | same |
|
|
161
|
+
| Block not found | SUCCESS + empty buffer (design choice; no `NOT_FOUND` status used) | same |
|
|
162
|
+
|
|
163
|
+
**Requester side** (Snappy limit: 3 MB):
|
|
164
|
+
|
|
165
|
+
| Rule | Consequence | File |
|
|
166
|
+
|------|-------------|------|
|
|
167
|
+
| Response block number must match requested | LowToleranceError; rejected | `libp2p_service.ts` (`validateRequestedBlock`) |
|
|
168
|
+
| Local block must exist for hash verification | Rejected (no penalty) | same |
|
|
169
|
+
| Response block hash must equal local block hash | MidToleranceError; rejected | same |
|
|
170
|
+
|
|
171
|
+
**Limitation**: the local-block requirement means BLOCK req/resp is unusable for initial P2P-only sync (before L1 sync provides local copies for verification). A TODO in the code acknowledges this.
|
|
172
|
+
|
|
173
|
+
### BLOCK_TXS Protocol (`/aztec/req/block_txs/1.0.0`)
|
|
174
|
+
|
|
175
|
+
**Server side**:
|
|
176
|
+
|
|
177
|
+
| Rule | Consequence | File |
|
|
178
|
+
|------|-------------|------|
|
|
179
|
+
| Request must parse as `BlockTxsRequest` (Fr + TxHashArray + BitVector) | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block_txs/block_txs_handler.ts` |
|
|
180
|
+
| BitVector length: non-negative and <= `MAX_TXS_PER_BLOCK` (65536) | Deserialization throws -> `BADLY_FORMED_REQUEST` | `protocols/block_txs/bitvector.ts` |
|
|
181
|
+
| Archive root not found and no explicit txHashes | `NOT_FOUND` status | handler |
|
|
182
|
+
| Internal error during lookup | Unhandled exception -> stream abort (no `INTERNAL_ERROR` status, unlike BLOCK) | handler |
|
|
183
|
+
|
|
184
|
+
Conditional registration: BLOCK_TXS handler only registered when `config.disableTransactions` is false. Otherwise peers get `ERR_UNSUPPORTED_PROTOCOL`.
|
|
185
|
+
|
|
186
|
+
**Requester side via `sendBatchRequest`** (Snappy limit: `max(N, 1) * 512 + 1` KB):
|
|
187
|
+
|
|
188
|
+
| Rule | Consequence | File |
|
|
189
|
+
|------|-------------|------|
|
|
190
|
+
| Archive root must match request | MidToleranceError | `libp2p_service.ts` (`validateRequestedBlockTxs`) |
|
|
191
|
+
| BitVector length must match request | MidToleranceError | same |
|
|
192
|
+
| No duplicate tx hashes | MidToleranceError | same |
|
|
193
|
+
| Tx count within bounds | MidToleranceError | same |
|
|
194
|
+
| Local block proposal must exist for archive root | Rejected (no penalty) | same |
|
|
195
|
+
| All tx hashes must be in proposal's tx list at allowed indices | LowToleranceError | same |
|
|
196
|
+
| Txs in strictly increasing index order | LowToleranceError | same |
|
|
197
|
+
| Each tx passes well-formedness (Metadata [4 fields], Size, Data, Proof) | LowToleranceError | same |
|
|
198
|
+
|
|
199
|
+
**Requester side via `BatchTxRequester`** (separate validation path):
|
|
200
|
+
|
|
201
|
+
| Rule | Consequence | File |
|
|
202
|
+
|------|-------------|------|
|
|
203
|
+
| Non-SUCCESS status: `FAILURE`/`UNKNOWN` | HighToleranceError + "bad peer" tracking | `batch-tx-requester/batch_tx_requester.ts` |
|
|
204
|
+
| `RATE_LIMIT_EXCEEDED` | Peer marked rate-limited (cooldown) | same |
|
|
205
|
+
| `NOT_FOUND` / `BADLY_FORMED_REQUEST` / `INTERNAL_ERROR` | Falls through silently (no penalty) | same |
|
|
206
|
+
| Each tx validated (Metadata + Size + Data + Proof) | LowToleranceError per invalid tx; valid txs from same response still accepted | same |
|
|
207
|
+
| Archive root match + non-empty txIndices | No penalty on mismatch; peer not promoted to "smart" | same |
|
|
208
|
+
|
|
209
|
+
**Double penalty on transport errors**: when `BatchTxRequester` encounters a transport error (e.g., ECONNRESET), both `sendRequestToPeer`'s internal handler and the `BatchTxRequester`'s catch block penalize the peer, resulting in double HighToleranceError.
|
|
210
|
+
|
|
211
|
+
See [BatchTxRequester README](batch-tx-requester/README.md) for the full architecture (peer classification, worker model, wire protocol).
|
|
212
|
+
|
|
213
|
+
### TX Protocol (`/aztec/req/tx/1.0.0`)
|
|
214
|
+
|
|
215
|
+
**Server side**:
|
|
216
|
+
|
|
217
|
+
| Rule | Consequence | File |
|
|
218
|
+
|------|-------------|------|
|
|
219
|
+
| Request must parse as `TxHashArray` | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/tx.ts` |
|
|
220
|
+
|
|
221
|
+
**Requester side** (validator registered at startup, not the default noop):
|
|
222
|
+
|
|
223
|
+
| Rule | Consequence | File |
|
|
224
|
+
|------|-------------|------|
|
|
225
|
+
| Each returned tx hash must be in the requested set | MidToleranceError | `libp2p_service.ts` (`validateRequestedTxs`) |
|
|
226
|
+
| Each tx passes well-formedness (Metadata + Size + Data + Proof) | LowToleranceError | same |
|
|
227
|
+
|
|
228
|
+
Snappy limit: `max(N, 1) * 512 + 1` KB.
|
|
229
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
|
|
2
2
|
import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { createTxValidatorForReqResponseReceivedTxs } from '../../../msg_validators/index.js';
|
|
5
5
|
|
|
6
6
|
export interface BatchRequestTxValidatorConfig {
|
|
7
7
|
l1ChainId: number;
|
|
@@ -29,7 +29,7 @@ export class BatchRequestTxValidator implements IBatchRequestTxValidator {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
static createRequestedTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
|
|
32
|
-
return
|
|
32
|
+
return createTxValidatorForReqResponseReceivedTxs(config.proofVerifier, {
|
|
33
33
|
l1ChainId: config.l1ChainId,
|
|
34
34
|
rollupVersion: config.rollupVersion,
|
|
35
35
|
});
|