@aztec/p2p 0.0.1-commit.fcb71a6 → 0.0.1-commit.fffb133c
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/interface.d.ts +18 -5
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +10 -13
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +449 -118
- package/dest/config.js +2 -2
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +61 -42
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +237 -263
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +21 -18
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +113 -108
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -16
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +89 -128
- package/dest/mem_pools/attestation_pool/mocks.d.ts +9 -6
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +16 -12
- 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 +4 -13
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +15 -10
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +91 -50
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +19 -5
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +59 -3
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +79 -5
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +47 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +2 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -4
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +51 -18
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -5
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +18 -14
- package/dest/msg_validators/clock_tolerance.d.ts +21 -0
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
- package/dest/msg_validators/clock_tolerance.js +37 -0
- package/dest/msg_validators/index.d.ts +2 -2
- package/dest/msg_validators/index.d.ts.map +1 -1
- package/dest/msg_validators/index.js +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
- package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/index.js +3 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.js +104 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +212 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
- 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/fee_payer_balance.d.ts +10 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
- 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 +8 -14
- package/dest/msg_validators/tx_validator/index.d.ts +2 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +1 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/size_validator.d.ts +6 -0
- package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/size_validator.js +20 -0
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/services/dummy_service.d.ts +6 -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 +6 -5
- package/dest/services/libp2p/instrumentation.d.ts +1 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +20 -73
- package/dest/services/libp2p/libp2p_service.d.ts +28 -11
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +711 -152
- package/dest/services/peer-manager/metrics.d.ts +1 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +6 -26
- package/dest/services/peer-manager/peer_manager.d.ts +2 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +0 -10
- package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +2 -5
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/constants.d.ts +12 -0
- package/dest/services/reqresp/constants.d.ts.map +1 -0
- package/dest/services/reqresp/constants.js +7 -0
- 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 +5 -21
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +7 -0
- package/dest/services/reqresp/protocols/status.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +4 -1
- package/dest/services/reqresp/reqresp.js +402 -24
- package/dest/services/service.d.ts +16 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +4 -14
- package/dest/services/tx_collection/slow_tx_collection.d.ts +3 -3
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.d.ts +5 -5
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.js +6 -19
- package/dest/testbench/p2p_client_testbench_worker.js +30 -17
- package/dest/testbench/worker_client_manager.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +6 -1
- package/package.json +16 -16
- package/src/client/interface.ts +19 -4
- package/src/client/p2p_client.ts +82 -132
- package/src/config.ts +2 -2
- package/src/mem_pools/attestation_pool/attestation_pool.ts +68 -41
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +239 -287
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +162 -140
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -164
- package/src/mem_pools/attestation_pool/mocks.ts +19 -13
- package/src/mem_pools/instrumentation.ts +9 -18
- package/src/mem_pools/tx_pool/README.md +28 -13
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +130 -75
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +66 -5
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +119 -4
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +4 -2
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +36 -21
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +13 -16
- package/src/msg_validators/clock_tolerance.ts +51 -0
- package/src/msg_validators/index.ts +1 -1
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
- package/src/msg_validators/proposal_validator/index.ts +3 -0
- package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
- package/src/msg_validators/tx_validator/block_header_validator.ts +3 -1
- package/src/msg_validators/tx_validator/data_validator.ts +12 -4
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +8 -25
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
- package/src/msg_validators/tx_validator/size_validator.ts +18 -0
- package/src/msg_validators/tx_validator/timestamp_validator.ts +3 -1
- package/src/services/dummy_service.ts +6 -0
- package/src/services/encoding.ts +5 -4
- package/src/services/libp2p/instrumentation.ts +19 -73
- package/src/services/libp2p/libp2p_service.ts +351 -115
- package/src/services/peer-manager/metrics.ts +5 -26
- package/src/services/peer-manager/peer_manager.ts +1 -2
- package/src/services/peer-manager/peer_scoring.ts +1 -5
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +3 -1
- package/src/services/reqresp/constants.ts +14 -0
- package/src/services/reqresp/metrics.ts +7 -23
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +9 -0
- package/src/services/reqresp/protocols/status.ts +7 -4
- package/src/services/service.ts +19 -4
- package/src/services/tx_collection/instrumentation.ts +4 -21
- package/src/services/tx_collection/slow_tx_collection.ts +2 -2
- package/src/services/tx_collection/tx_collection.ts +4 -4
- package/src/services/tx_provider.ts +2 -2
- package/src/services/tx_provider_instrumentation.ts +11 -24
- package/src/testbench/p2p_client_testbench_worker.ts +40 -21
- package/src/testbench/worker_client_manager.ts +6 -1
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +0 -15
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +0 -88
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -82
- package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.js +0 -1
- package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +0 -108
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -97
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import { BlockNumber
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { randomInt } from '@aztec/foundation/crypto/random';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
@@ -13,11 +13,14 @@ import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
|
13
13
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
14
14
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
15
15
|
import {
|
|
16
|
-
BlockAttestation,
|
|
17
16
|
BlockProposal,
|
|
17
|
+
CheckpointAttestation,
|
|
18
|
+
CheckpointProposal,
|
|
19
|
+
type CheckpointProposalCore,
|
|
18
20
|
type Gossipable,
|
|
19
21
|
P2PClientType,
|
|
20
22
|
P2PMessage,
|
|
23
|
+
type ValidationResult as P2PValidationResult,
|
|
21
24
|
PeerErrorSeverity,
|
|
22
25
|
TopicType,
|
|
23
26
|
createTopicString,
|
|
@@ -28,7 +31,14 @@ import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
|
28
31
|
import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
29
32
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
30
33
|
import { compressComponentVersions } from '@aztec/stdlib/versioning';
|
|
31
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
Attributes,
|
|
36
|
+
OtelMetricsAdapter,
|
|
37
|
+
SpanStatusCode,
|
|
38
|
+
type TelemetryClient,
|
|
39
|
+
WithTracer,
|
|
40
|
+
trackSpan,
|
|
41
|
+
} from '@aztec/telemetry-client';
|
|
32
42
|
|
|
33
43
|
import {
|
|
34
44
|
type GossipSub,
|
|
@@ -53,9 +63,11 @@ import type { P2PConfig } from '../../config.js';
|
|
|
53
63
|
import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
|
|
54
64
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
55
65
|
import {
|
|
56
|
-
AttestationValidator,
|
|
57
66
|
BlockProposalValidator,
|
|
67
|
+
CheckpointAttestationValidator,
|
|
68
|
+
CheckpointProposalValidator,
|
|
58
69
|
FishermanAttestationValidator,
|
|
70
|
+
SizeTxValidator,
|
|
59
71
|
} from '../../msg_validators/index.js';
|
|
60
72
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
61
73
|
import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
|
|
@@ -101,7 +113,12 @@ import {
|
|
|
101
113
|
reqRespTxHandler,
|
|
102
114
|
} from '../reqresp/protocols/index.js';
|
|
103
115
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
104
|
-
import type {
|
|
116
|
+
import type {
|
|
117
|
+
P2PBlockReceivedCallback,
|
|
118
|
+
P2PCheckpointReceivedCallback,
|
|
119
|
+
P2PService,
|
|
120
|
+
PeerDiscoveryService,
|
|
121
|
+
} from '../service.js';
|
|
105
122
|
import { P2PInstrumentation } from './instrumentation.js';
|
|
106
123
|
|
|
107
124
|
interface ValidationResult {
|
|
@@ -125,8 +142,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
125
142
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
126
143
|
|
|
127
144
|
// Message validators
|
|
128
|
-
private attestationValidator: AttestationValidator;
|
|
129
145
|
private blockProposalValidator: BlockProposalValidator;
|
|
146
|
+
private checkpointProposalValidator: CheckpointProposalValidator;
|
|
147
|
+
private checkpointAttestationValidator: CheckpointAttestationValidator;
|
|
130
148
|
|
|
131
149
|
private protocolVersion = '';
|
|
132
150
|
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
|
|
@@ -140,10 +158,19 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
140
158
|
*/
|
|
141
159
|
private blockReceivedCallback: P2PBlockReceivedCallback;
|
|
142
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Callback for when a checkpoint proposal is received from a peer.
|
|
163
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
164
|
+
* @returns The attestations for the checkpoint, if any.
|
|
165
|
+
*/
|
|
166
|
+
private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
167
|
+
|
|
143
168
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
144
169
|
|
|
145
170
|
private instrumentation: P2PInstrumentation;
|
|
146
171
|
|
|
172
|
+
private telemetry: TelemetryClient;
|
|
173
|
+
|
|
147
174
|
protected logger: Logger;
|
|
148
175
|
|
|
149
176
|
constructor(
|
|
@@ -162,6 +189,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
162
189
|
logger: Logger = createLogger('p2p:libp2p_service'),
|
|
163
190
|
) {
|
|
164
191
|
super(telemetry, 'LibP2PService');
|
|
192
|
+
this.telemetry = telemetry;
|
|
165
193
|
|
|
166
194
|
// Create child logger with fisherman prefix if in fisherman mode
|
|
167
195
|
this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
|
|
@@ -170,7 +198,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
170
198
|
|
|
171
199
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
172
200
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
173
|
-
this.msgIdSeenValidators[TopicType.
|
|
201
|
+
this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
202
|
+
this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
174
203
|
|
|
175
204
|
const versions = getVersions(config);
|
|
176
205
|
this.protocolVersion = compressComponentVersions(versions);
|
|
@@ -178,25 +207,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
178
207
|
|
|
179
208
|
this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
|
|
180
209
|
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
181
|
-
this.topicStrings[TopicType.
|
|
182
|
-
TopicType.
|
|
210
|
+
this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(
|
|
211
|
+
TopicType.checkpoint_proposal,
|
|
212
|
+
this.protocolVersion,
|
|
213
|
+
);
|
|
214
|
+
this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(
|
|
215
|
+
TopicType.checkpoint_attestation,
|
|
183
216
|
this.protocolVersion,
|
|
184
217
|
);
|
|
185
218
|
|
|
186
|
-
// Use FishermanAttestationValidator in fisherman mode to validate attestation payloads against proposals
|
|
187
|
-
this.attestationValidator = config.fishermanMode
|
|
188
|
-
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
189
|
-
: new AttestationValidator(epochCache);
|
|
190
219
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
|
|
220
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
221
|
+
txsPermitted: !config.disableTransactions,
|
|
222
|
+
});
|
|
223
|
+
this.checkpointAttestationValidator = config.fishermanMode
|
|
224
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
225
|
+
: new CheckpointAttestationValidator(epochCache);
|
|
191
226
|
|
|
192
227
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
193
228
|
|
|
194
|
-
this.blockReceivedCallback = async (block: BlockProposal): Promise<
|
|
229
|
+
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
195
230
|
this.logger.debug(
|
|
196
231
|
`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
|
|
197
232
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
198
233
|
);
|
|
199
|
-
return
|
|
234
|
+
return false;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
this.checkpointReceivedCallback = (
|
|
238
|
+
checkpoint: CheckpointProposalCore,
|
|
239
|
+
): Promise<CheckpointAttestation[] | undefined> => {
|
|
240
|
+
this.logger.debug(
|
|
241
|
+
`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
|
|
242
|
+
);
|
|
243
|
+
return Promise.resolve(undefined);
|
|
200
244
|
};
|
|
201
245
|
}
|
|
202
246
|
|
|
@@ -265,7 +309,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
265
309
|
|
|
266
310
|
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
267
311
|
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
268
|
-
const
|
|
312
|
+
const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
|
|
313
|
+
const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
|
|
269
314
|
|
|
270
315
|
const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
|
|
271
316
|
const directPeers = (
|
|
@@ -387,12 +432,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
387
432
|
invalidMessageDeliveriesWeight: -20,
|
|
388
433
|
invalidMessageDeliveriesDecay: 0.5,
|
|
389
434
|
}),
|
|
390
|
-
[
|
|
435
|
+
[blockProposalTopic]: createTopicScoreParams({
|
|
391
436
|
topicWeight: 1,
|
|
392
437
|
invalidMessageDeliveriesWeight: -20,
|
|
393
438
|
invalidMessageDeliveriesDecay: 0.5,
|
|
394
439
|
}),
|
|
395
|
-
[
|
|
440
|
+
[checkpointProposalTopic]: createTopicScoreParams({
|
|
441
|
+
topicWeight: 1,
|
|
442
|
+
invalidMessageDeliveriesWeight: -20,
|
|
443
|
+
invalidMessageDeliveriesDecay: 0.5,
|
|
444
|
+
}),
|
|
445
|
+
[checkpointAttestationTopic]: createTopicScoreParams({
|
|
396
446
|
topicWeight: 1,
|
|
397
447
|
invalidMessageDeliveriesWeight: -20,
|
|
398
448
|
invalidMessageDeliveriesDecay: 0.5,
|
|
@@ -462,17 +512,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
462
512
|
}
|
|
463
513
|
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
464
514
|
|
|
465
|
-
await this.peerManager.initializePeers();
|
|
466
|
-
if (!this.config.p2pDiscoveryDisabled) {
|
|
467
|
-
await this.peerDiscoveryService.start();
|
|
468
|
-
}
|
|
469
|
-
await this.node.start();
|
|
470
|
-
|
|
471
|
-
// Subscribe to standard GossipSub topics by default
|
|
472
|
-
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
|
|
473
|
-
this.subscribeToTopic(this.topicStrings[topic]);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
515
|
// Create request response protocol handlers
|
|
477
516
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
478
517
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
@@ -495,10 +534,32 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
495
534
|
requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
|
|
496
535
|
}
|
|
497
536
|
|
|
537
|
+
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
538
|
+
const reqrespSubProtocolValidators = {
|
|
539
|
+
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
540
|
+
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
541
|
+
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
542
|
+
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
await this.peerManager.initializePeers();
|
|
546
|
+
|
|
547
|
+
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
548
|
+
|
|
549
|
+
await this.node.start();
|
|
550
|
+
|
|
551
|
+
// Subscribe to standard GossipSub topics by default
|
|
552
|
+
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
|
|
553
|
+
this.subscribeToTopic(this.topicStrings[topic]);
|
|
554
|
+
}
|
|
555
|
+
|
|
498
556
|
// add GossipSub listener
|
|
499
557
|
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
500
558
|
|
|
501
559
|
// Start running promise for peer discovery and metrics collection
|
|
560
|
+
if (!this.config.p2pDiscoveryDisabled) {
|
|
561
|
+
await this.peerDiscoveryService.start();
|
|
562
|
+
}
|
|
502
563
|
this.discoveryRunningPromise = new RunningPromise(
|
|
503
564
|
async () => {
|
|
504
565
|
await this.peerManager.heartbeat();
|
|
@@ -508,14 +569,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
508
569
|
);
|
|
509
570
|
this.discoveryRunningPromise.start();
|
|
510
571
|
|
|
511
|
-
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
512
|
-
const reqrespSubProtocolValidators = {
|
|
513
|
-
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
514
|
-
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
515
|
-
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
516
|
-
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
517
|
-
};
|
|
518
|
-
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
519
572
|
this.logger.info(`Started P2P service`, {
|
|
520
573
|
listen: this.config.listenAddress,
|
|
521
574
|
port: this.config.p2pPort,
|
|
@@ -601,6 +654,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
601
654
|
this.blockReceivedCallback = callback;
|
|
602
655
|
}
|
|
603
656
|
|
|
657
|
+
public registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
658
|
+
this.checkpointReceivedCallback = callback;
|
|
659
|
+
}
|
|
660
|
+
|
|
604
661
|
/**
|
|
605
662
|
* Subscribes to a topic.
|
|
606
663
|
* @param topic - The topic to subscribe to.
|
|
@@ -622,7 +679,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
622
679
|
if (!this.node.services.pubsub) {
|
|
623
680
|
throw new Error('Pubsub service not available.');
|
|
624
681
|
}
|
|
625
|
-
const
|
|
682
|
+
const isBlockProposal = topic === this.topicStrings[TopicType.block_proposal];
|
|
683
|
+
const traceContext =
|
|
684
|
+
this.config.debugP2PInstrumentMessages && isBlockProposal ? this.telemetry.getTraceContext() : undefined;
|
|
685
|
+
const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages, traceContext);
|
|
626
686
|
const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
|
|
627
687
|
return result.recipients.length;
|
|
628
688
|
}
|
|
@@ -643,12 +703,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
643
703
|
case this.topicStrings[TopicType.tx]:
|
|
644
704
|
topicType = TopicType.tx;
|
|
645
705
|
break;
|
|
646
|
-
case this.topicStrings[TopicType.block_attestation]:
|
|
647
|
-
topicType = TopicType.block_attestation;
|
|
648
|
-
break;
|
|
649
706
|
case this.topicStrings[TopicType.block_proposal]:
|
|
650
707
|
topicType = TopicType.block_proposal;
|
|
651
708
|
break;
|
|
709
|
+
case this.topicStrings[TopicType.checkpoint_proposal]:
|
|
710
|
+
topicType = TopicType.checkpoint_proposal;
|
|
711
|
+
break;
|
|
712
|
+
case this.topicStrings[TopicType.checkpoint_attestation]:
|
|
713
|
+
topicType = TopicType.checkpoint_attestation;
|
|
714
|
+
break;
|
|
652
715
|
default:
|
|
653
716
|
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
654
717
|
break;
|
|
@@ -707,23 +770,74 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
707
770
|
return;
|
|
708
771
|
}
|
|
709
772
|
|
|
773
|
+
// Determine topic type for attributes
|
|
710
774
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
711
775
|
topicType = TopicType.tx;
|
|
712
|
-
|
|
776
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
777
|
+
topicType = TopicType.checkpoint_attestation;
|
|
778
|
+
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
779
|
+
topicType = TopicType.block_proposal;
|
|
780
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
781
|
+
topicType = TopicType.checkpoint_proposal;
|
|
713
782
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
783
|
+
|
|
784
|
+
// Process the message, optionally within a linked span for trace propagation
|
|
785
|
+
const processMessage = async () => {
|
|
786
|
+
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
787
|
+
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
788
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
789
|
+
if (this.clientType === P2PClientType.Full) {
|
|
790
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
791
|
+
}
|
|
792
|
+
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
793
|
+
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
794
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
795
|
+
await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
|
|
796
|
+
} else {
|
|
797
|
+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
718
798
|
}
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
799
|
+
};
|
|
800
|
+
|
|
801
|
+
const latency = p2pMessage.timestamp !== undefined ? msgReceivedTime - p2pMessage.timestamp.getTime() : undefined;
|
|
802
|
+
const propagatedContext = p2pMessage.traceContext
|
|
803
|
+
? this.telemetry.extractPropagatedContext(p2pMessage.traceContext)
|
|
804
|
+
: undefined;
|
|
805
|
+
|
|
806
|
+
if (propagatedContext) {
|
|
807
|
+
await this.tracer.startActiveSpan(
|
|
808
|
+
'LibP2PService.processMessage',
|
|
809
|
+
{
|
|
810
|
+
attributes: {
|
|
811
|
+
[Attributes.TOPIC_NAME]: topicType!,
|
|
812
|
+
[Attributes.PEER_ID]: source.toString(),
|
|
813
|
+
},
|
|
814
|
+
},
|
|
815
|
+
propagatedContext,
|
|
816
|
+
async span => {
|
|
817
|
+
try {
|
|
818
|
+
await processMessage();
|
|
819
|
+
span.setStatus({
|
|
820
|
+
code: SpanStatusCode.OK,
|
|
821
|
+
});
|
|
822
|
+
} catch (err) {
|
|
823
|
+
span.setStatus({
|
|
824
|
+
code: SpanStatusCode.ERROR,
|
|
825
|
+
message: String(err),
|
|
826
|
+
});
|
|
827
|
+
if (typeof err === 'string' || (err && err instanceof Error)) {
|
|
828
|
+
span.recordException(err);
|
|
829
|
+
}
|
|
830
|
+
throw err;
|
|
831
|
+
} finally {
|
|
832
|
+
span.end();
|
|
833
|
+
}
|
|
834
|
+
},
|
|
835
|
+
);
|
|
836
|
+
} else {
|
|
837
|
+
await processMessage();
|
|
723
838
|
}
|
|
724
839
|
|
|
725
|
-
if (
|
|
726
|
-
const latency = msgReceivedTime - p2pMessage.timestamp.getTime();
|
|
840
|
+
if (latency !== undefined && topicType !== undefined) {
|
|
727
841
|
this.instrumentation.recordMessageLatency(topicType, latency);
|
|
728
842
|
}
|
|
729
843
|
|
|
@@ -800,27 +914,30 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
800
914
|
}
|
|
801
915
|
|
|
802
916
|
/**
|
|
803
|
-
* Process
|
|
804
|
-
*
|
|
805
|
-
*
|
|
806
|
-
* @param attestation - The attestation to process.
|
|
917
|
+
* Process a checkpoint attestation from a peer.
|
|
918
|
+
* Validates the attestation and adds it to the pool.
|
|
807
919
|
*/
|
|
808
|
-
private async
|
|
809
|
-
|
|
810
|
-
|
|
920
|
+
private async processCheckpointAttestationFromPeer(
|
|
921
|
+
payloadData: Buffer,
|
|
922
|
+
msgId: string,
|
|
923
|
+
source: PeerId,
|
|
924
|
+
): Promise<void> {
|
|
925
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointAttestation>> = async () => {
|
|
926
|
+
const attestation = CheckpointAttestation.fromBuffer(payloadData);
|
|
811
927
|
const pool = this.mempools.attestationPool;
|
|
812
|
-
const
|
|
813
|
-
const
|
|
928
|
+
const validationResult = await this.validateCheckpointAttestation(source, attestation);
|
|
929
|
+
const isValid = validationResult.result === 'accept';
|
|
930
|
+
const exists = isValid && (await pool.hasCheckpointAttestation(attestation));
|
|
814
931
|
|
|
815
932
|
let canAdd = true;
|
|
816
933
|
if (isValid && !exists) {
|
|
817
934
|
const slot = attestation.payload.header.slotNumber;
|
|
818
935
|
const { committee } = await this.epochCache.getCommittee(slot);
|
|
819
936
|
const committeeSize = committee?.length ?? 0;
|
|
820
|
-
canAdd = await pool.
|
|
937
|
+
canAdd = await pool.canAddCheckpointAttestation(attestation, committeeSize);
|
|
821
938
|
}
|
|
822
939
|
|
|
823
|
-
this.logger.trace(`Validate propagated
|
|
940
|
+
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
824
941
|
isValid,
|
|
825
942
|
exists,
|
|
826
943
|
canAdd,
|
|
@@ -828,12 +945,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
828
945
|
[Attributes.P2P_ID]: source.toString(),
|
|
829
946
|
});
|
|
830
947
|
|
|
831
|
-
if (
|
|
948
|
+
if (validationResult.result === 'reject') {
|
|
832
949
|
return { result: TopicValidatorResult.Reject };
|
|
833
|
-
} else if (exists) {
|
|
950
|
+
} else if (validationResult.result === 'ignore' || exists) {
|
|
834
951
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
835
952
|
} else if (!canAdd) {
|
|
836
|
-
this.logger.warn(`Dropping
|
|
953
|
+
this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
|
|
837
954
|
slot: attestation.payload.header.slotNumber.toString(),
|
|
838
955
|
archive: attestation.archive.toString(),
|
|
839
956
|
source: source.toString(),
|
|
@@ -844,11 +961,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
844
961
|
}
|
|
845
962
|
};
|
|
846
963
|
|
|
847
|
-
const { result, obj: attestation } = await this.validateReceivedMessage<
|
|
964
|
+
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
848
965
|
validationFunc,
|
|
849
966
|
msgId,
|
|
850
967
|
source,
|
|
851
|
-
TopicType.
|
|
968
|
+
TopicType.checkpoint_attestation,
|
|
852
969
|
);
|
|
853
970
|
|
|
854
971
|
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
@@ -856,7 +973,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
856
973
|
}
|
|
857
974
|
|
|
858
975
|
this.logger.debug(
|
|
859
|
-
`Received attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
976
|
+
`Received checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
860
977
|
{
|
|
861
978
|
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
862
979
|
slot: attestation.slotNumber,
|
|
@@ -865,13 +982,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
865
982
|
},
|
|
866
983
|
);
|
|
867
984
|
|
|
868
|
-
await this.mempools.attestationPool.
|
|
985
|
+
await this.mempools.attestationPool.addCheckpointAttestations([attestation]);
|
|
869
986
|
}
|
|
870
987
|
|
|
871
988
|
private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
872
989
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
|
|
873
990
|
const block = BlockProposal.fromBuffer(payloadData);
|
|
874
|
-
const
|
|
991
|
+
const validationResult = await this.validateBlockProposal(source, block);
|
|
992
|
+
const isValid = validationResult.result === 'accept';
|
|
875
993
|
const pool = this.mempools.attestationPool;
|
|
876
994
|
|
|
877
995
|
const exists = isValid && (await pool.hasBlockProposal(block));
|
|
@@ -881,13 +999,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
881
999
|
isValid,
|
|
882
1000
|
exists,
|
|
883
1001
|
canAdd,
|
|
884
|
-
[Attributes.SLOT_NUMBER]: block.
|
|
1002
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
885
1003
|
[Attributes.P2P_ID]: source.toString(),
|
|
886
1004
|
});
|
|
887
1005
|
|
|
888
|
-
if (
|
|
1006
|
+
if (validationResult.result === 'reject') {
|
|
889
1007
|
return { result: TopicValidatorResult.Reject };
|
|
890
|
-
} else if (exists) {
|
|
1008
|
+
} else if (validationResult.result === 'ignore' || exists) {
|
|
891
1009
|
return { result: TopicValidatorResult.Ignore, obj: block };
|
|
892
1010
|
} else if (!canAdd) {
|
|
893
1011
|
this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
|
|
@@ -917,6 +1035,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
917
1035
|
}
|
|
918
1036
|
|
|
919
1037
|
// REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
1038
|
+
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
1039
|
+
// should not be here as it does not deal with p2p networking.
|
|
920
1040
|
@trackSpan('Libp2pService.processValidBlockProposal', async block => ({
|
|
921
1041
|
[Attributes.SLOT_NUMBER]: block.slotNumber,
|
|
922
1042
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
@@ -924,17 +1044,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
924
1044
|
}))
|
|
925
1045
|
private async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
|
|
926
1046
|
const slot = block.slotNumber;
|
|
927
|
-
const previousSlot = SlotNumber(slot - 1);
|
|
928
1047
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
929
1048
|
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
930
|
-
slot: block.slotNumber,
|
|
931
|
-
archive: block.archive.toString(),
|
|
932
1049
|
source: sender.toString(),
|
|
1050
|
+
...block.toBlockInfo(),
|
|
933
1051
|
});
|
|
934
|
-
const attestationsForPreviousSlot = await this.mempools.attestationPool.getAttestationsForSlot(previousSlot);
|
|
935
|
-
this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
|
|
936
1052
|
|
|
937
|
-
// Attempt to add proposal
|
|
1053
|
+
// Attempt to add proposal
|
|
938
1054
|
try {
|
|
939
1055
|
await this.mempools.attestationPool.addBlockProposal(block);
|
|
940
1056
|
} catch (err: unknown) {
|
|
@@ -949,34 +1065,126 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
949
1065
|
}
|
|
950
1066
|
throw err;
|
|
951
1067
|
}
|
|
1068
|
+
|
|
1069
|
+
// Mark the txs in this proposal as non-evictable
|
|
952
1070
|
await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
|
|
953
|
-
const attestations = await this.blockReceivedCallback(block, sender);
|
|
954
1071
|
|
|
955
|
-
//
|
|
956
|
-
//
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1072
|
+
// Call the block received callback to validate the proposal.
|
|
1073
|
+
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1074
|
+
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1075
|
+
if (!isValid) {
|
|
1076
|
+
this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* Handle a gossiped checkpoint proposal.
|
|
1082
|
+
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1083
|
+
*/
|
|
1084
|
+
private async handleGossipedCheckpointProposal(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1085
|
+
// TODO(palla/mbps): This pattern is repeated across multiple message handlers, consider abstracting it.
|
|
1086
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointProposal>> = async () => {
|
|
1087
|
+
const checkpoint = CheckpointProposal.fromBuffer(payloadData);
|
|
1088
|
+
const validationResult = await this.validateCheckpointProposal(source, checkpoint);
|
|
1089
|
+
const isValid = validationResult.result === 'accept';
|
|
1090
|
+
const pool = this.mempools.attestationPool;
|
|
1091
|
+
|
|
1092
|
+
const exists = isValid && (await pool.hasCheckpointProposal(checkpoint));
|
|
1093
|
+
const canAdd = isValid && (await pool.canAddCheckpointProposal(checkpoint));
|
|
1094
|
+
|
|
1095
|
+
this.logger.trace(`Validate propagated checkpoint proposal`, {
|
|
1096
|
+
isValid,
|
|
1097
|
+
exists,
|
|
1098
|
+
canAdd,
|
|
1099
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1100
|
+
[Attributes.P2P_ID]: source.toString(),
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
if (validationResult.result === 'reject') {
|
|
1104
|
+
return { result: TopicValidatorResult.Reject };
|
|
1105
|
+
} else if (validationResult.result === 'ignore' || exists) {
|
|
1106
|
+
return { result: TopicValidatorResult.Ignore, obj: checkpoint };
|
|
1107
|
+
} else if (!canAdd) {
|
|
1108
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
|
|
1109
|
+
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1110
|
+
slot: checkpoint.slotNumber.toString(),
|
|
1111
|
+
archive: checkpoint.archive.toString(),
|
|
1112
|
+
source: source.toString(),
|
|
963
1113
|
});
|
|
964
|
-
|
|
1114
|
+
return { result: TopicValidatorResult.Reject };
|
|
1115
|
+
} else {
|
|
1116
|
+
return { result: TopicValidatorResult.Accept, obj: checkpoint };
|
|
965
1117
|
}
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
const { result, obj: checkpoint } = await this.validateReceivedMessage<CheckpointProposal>(
|
|
1121
|
+
validationFunc,
|
|
1122
|
+
msgId,
|
|
1123
|
+
source,
|
|
1124
|
+
TopicType.checkpoint_proposal,
|
|
1125
|
+
);
|
|
1126
|
+
|
|
1127
|
+
if (result !== TopicValidatorResult.Accept || !checkpoint) {
|
|
1128
|
+
return;
|
|
966
1129
|
}
|
|
1130
|
+
|
|
1131
|
+
await this.processValidCheckpointProposal(checkpoint, source);
|
|
967
1132
|
}
|
|
968
1133
|
|
|
969
1134
|
/**
|
|
970
|
-
*
|
|
971
|
-
*
|
|
1135
|
+
* Process a validated checkpoint proposal.
|
|
1136
|
+
* Extracts and processes the last block proposal (if present) first, then processes the checkpoint.
|
|
1137
|
+
* The block callback is invoked before the checkpoint callback.
|
|
972
1138
|
*/
|
|
973
|
-
@trackSpan('Libp2pService.
|
|
974
|
-
[Attributes.SLOT_NUMBER]:
|
|
975
|
-
[Attributes.BLOCK_ARCHIVE]:
|
|
976
|
-
[Attributes.P2P_ID]: await
|
|
1139
|
+
@trackSpan('Libp2pService.processValidCheckpointProposal', async checkpoint => ({
|
|
1140
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
|
|
1141
|
+
[Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
|
|
1142
|
+
[Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
977
1143
|
}))
|
|
978
|
-
private async
|
|
979
|
-
|
|
1144
|
+
private async processValidCheckpointProposal(checkpoint: CheckpointProposal, sender: PeerId) {
|
|
1145
|
+
const slot = checkpoint.slotNumber;
|
|
1146
|
+
this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1147
|
+
p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
|
|
1148
|
+
slot: checkpoint.slotNumber,
|
|
1149
|
+
archive: checkpoint.archive.toString(),
|
|
1150
|
+
source: sender.toString(),
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
// Extract block proposal before adding to pool (pool stores them separately)
|
|
1154
|
+
const blockProposal = checkpoint.getBlockProposal();
|
|
1155
|
+
|
|
1156
|
+
// Add proposal to the pool (this extracts and stores block proposal separately)
|
|
1157
|
+
await this.mempools.attestationPool.addCheckpointProposal(checkpoint);
|
|
1158
|
+
|
|
1159
|
+
// Mark txs as non-evictable if present (from the last block)
|
|
1160
|
+
if (checkpoint.txHashes.length > 0) {
|
|
1161
|
+
await this.mempools.txPool.markTxsAsNonEvictable(checkpoint.txHashes);
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// If there was a last block proposal, invoke the block callback first for validation.
|
|
1165
|
+
// Note: The block proposal is already stored in the pool by addCheckpointProposal.
|
|
1166
|
+
if (blockProposal) {
|
|
1167
|
+
const isValid = await this.blockReceivedCallback(blockProposal, sender);
|
|
1168
|
+
if (!isValid) {
|
|
1169
|
+
this.logger.warn(`Block proposal from checkpoint failed validation`, {
|
|
1170
|
+
slot: slot.toString(),
|
|
1171
|
+
archive: checkpoint.archive.toString(),
|
|
1172
|
+
blockNumber: blockProposal.blockNumber.toString(),
|
|
1173
|
+
});
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1179
|
+
// to validate and potentially generate attestations
|
|
1180
|
+
const attestations = await this.checkpointReceivedCallback(checkpoint.toCore(), sender);
|
|
1181
|
+
if (attestations && attestations.length > 0) {
|
|
1182
|
+
// If the callback returned attestations, add them to the pool and propagate them
|
|
1183
|
+
await this.mempools.attestationPool.addCheckpointAttestations(attestations);
|
|
1184
|
+
for (const attestation of attestations) {
|
|
1185
|
+
await this.propagate(attestation);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
980
1188
|
}
|
|
981
1189
|
|
|
982
1190
|
/**
|
|
@@ -1167,6 +1375,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1167
1375
|
private createRequestedTxValidator(): TxValidator {
|
|
1168
1376
|
return new AggregateTxValidator(
|
|
1169
1377
|
new DataTxValidator(),
|
|
1378
|
+
new SizeTxValidator(),
|
|
1170
1379
|
new MetadataTxValidator({
|
|
1171
1380
|
l1ChainId: new Fr(this.config.l1ChainId),
|
|
1172
1381
|
rollupVersion: new Fr(this.config.rollupVersion),
|
|
@@ -1361,24 +1570,28 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1361
1570
|
}
|
|
1362
1571
|
|
|
1363
1572
|
/**
|
|
1364
|
-
* Validate
|
|
1573
|
+
* Validate a checkpoint attestation.
|
|
1365
1574
|
*
|
|
1366
|
-
* @param attestation - The attestation to validate.
|
|
1367
|
-
* @returns True if the attestation is valid, false otherwise.
|
|
1575
|
+
* @param attestation - The checkpoint attestation to validate.
|
|
1576
|
+
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1368
1577
|
*/
|
|
1369
|
-
@trackSpan('Libp2pService.
|
|
1578
|
+
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1370
1579
|
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1371
1580
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1372
1581
|
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1373
1582
|
}))
|
|
1374
|
-
public async
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1583
|
+
public async validateCheckpointAttestation(
|
|
1584
|
+
peerId: PeerId,
|
|
1585
|
+
attestation: CheckpointAttestation,
|
|
1586
|
+
): Promise<P2PValidationResult> {
|
|
1587
|
+
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1588
|
+
|
|
1589
|
+
if (result.result === 'reject') {
|
|
1590
|
+
this.logger.debug(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1591
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1379
1592
|
}
|
|
1380
1593
|
|
|
1381
|
-
return
|
|
1594
|
+
return result;
|
|
1382
1595
|
}
|
|
1383
1596
|
|
|
1384
1597
|
/**
|
|
@@ -1388,17 +1601,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1388
1601
|
* @returns True if the block proposal is valid, false otherwise.
|
|
1389
1602
|
*/
|
|
1390
1603
|
@trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
|
|
1391
|
-
[Attributes.SLOT_NUMBER]: block.
|
|
1604
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1392
1605
|
}))
|
|
1393
|
-
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<
|
|
1394
|
-
const
|
|
1395
|
-
|
|
1606
|
+
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<P2PValidationResult> {
|
|
1607
|
+
const result = await this.blockProposalValidator.validate(block);
|
|
1608
|
+
|
|
1609
|
+
if (result.result === 'reject') {
|
|
1396
1610
|
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1397
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1398
|
-
return false;
|
|
1611
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1399
1612
|
}
|
|
1400
1613
|
|
|
1401
|
-
return
|
|
1614
|
+
return result;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
/**
|
|
1618
|
+
* Validate a checkpoint proposal.
|
|
1619
|
+
*
|
|
1620
|
+
* @param checkpoint - The checkpoint proposal to validate.
|
|
1621
|
+
* @returns True if the checkpoint proposal is valid, false otherwise.
|
|
1622
|
+
*/
|
|
1623
|
+
@trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1624
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1625
|
+
}))
|
|
1626
|
+
public async validateCheckpointProposal(
|
|
1627
|
+
peerId: PeerId,
|
|
1628
|
+
checkpoint: CheckpointProposal,
|
|
1629
|
+
): Promise<P2PValidationResult> {
|
|
1630
|
+
const result = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1631
|
+
|
|
1632
|
+
if (result.result === 'reject') {
|
|
1633
|
+
this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1634
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
return result;
|
|
1402
1638
|
}
|
|
1403
1639
|
|
|
1404
1640
|
public getPeerScore(peerId: PeerId): number {
|