@aztec/p2p 5.0.0-rc.1 → 5.0.0
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 +3 -5
- package/dest/bootstrap/bootstrap.d.ts +1 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +20 -12
- package/dest/client/factory.d.ts +1 -1
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +2 -1
- package/dest/client/interface.d.ts +14 -2
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +4 -2
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +10 -2
- package/dest/config.d.ts +7 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +10 -5
- package/dest/errors/reqresp.error.d.ts +13 -1
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +14 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +6 -2
- 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 +43 -0
- package/dest/mem_pools/instrumentation.d.ts +9 -4
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +11 -8
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +12 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +9 -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 +21 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +2 -1
- 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 +12 -4
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +10 -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 +56 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +10 -6
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +25 -12
- package/dest/msg_validators/tx_validator/phases_validator.js +2 -2
- package/dest/services/discv5/discV5_service.d.ts +12 -2
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +84 -15
- package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
- package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
- package/dest/services/discv5/persisted_enr_store.js +145 -0
- 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 +19 -6
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +25 -15
- package/dest/services/libp2p/libp2p_service.d.ts +11 -3
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +98 -34
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +21 -12
- package/dest/services/reqresp/config.d.ts +13 -1
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/config.js +11 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -3
- 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 +34 -3
- package/dest/services/service.d.ts +17 -1
- package/dest/services/service.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.d.ts +2 -1
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +3 -0
- package/package.json +16 -17
- package/src/bootstrap/bootstrap.ts +15 -9
- package/src/client/factory.ts +1 -0
- package/src/client/interface.ts +15 -0
- package/src/client/p2p_client.ts +14 -3
- package/src/config.ts +17 -4
- package/src/errors/reqresp.error.ts +19 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +6 -2
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +40 -1
- package/src/mem_pools/instrumentation.ts +13 -11
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +1 -1
- package/src/mem_pools/tx_pool_v2/interfaces.ts +13 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +23 -0
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +14 -4
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +71 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +22 -15
- package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
- package/src/services/discv5/discV5_service.ts +88 -9
- package/src/services/discv5/persisted_enr_store.ts +158 -0
- package/src/services/dummy_service.ts +6 -0
- package/src/services/encoding.ts +28 -20
- package/src/services/libp2p/libp2p_service.ts +107 -37
- package/src/services/peer-manager/peer_manager.ts +18 -11
- package/src/services/reqresp/README.md +2 -23
- package/src/services/reqresp/config.ts +17 -0
- package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -3
- package/src/services/reqresp/reqresp.ts +42 -2
- package/src/services/service.ts +19 -0
- package/src/test-helpers/testbench-utils.ts +4 -0
|
@@ -372,7 +372,7 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
372
372
|
}
|
|
373
373
|
var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _initProto;
|
|
374
374
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
375
|
-
import { maxBy, merge } from '@aztec/foundation/collection';
|
|
375
|
+
import { compactArray, maxBy, merge } from '@aztec/foundation/collection';
|
|
376
376
|
import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
377
377
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
378
378
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -407,11 +407,12 @@ import { convertToMultiaddr } from '../../util.js';
|
|
|
407
407
|
import { getVersions } from '../../versioning.js';
|
|
408
408
|
import { AztecDatastore } from '../data_store.js';
|
|
409
409
|
import { DiscV5Service } from '../discv5/discV5_service.js';
|
|
410
|
-
import { SnappyTransform,
|
|
410
|
+
import { SnappyTransform, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
|
|
411
411
|
import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
|
|
412
412
|
import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
|
|
413
413
|
import { PeerManager } from '../peer-manager/peer_manager.js';
|
|
414
414
|
import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
415
|
+
import { YAMUX_MAX_MESSAGE_SIZE_BYTES } from '../reqresp/config.js';
|
|
415
416
|
import { ReqRespSubProtocol, ValidationError, pingHandler, reqGoodbyeHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
|
|
416
417
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
417
418
|
import { P2PInstrumentation } from './instrumentation.js';
|
|
@@ -503,6 +504,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
503
504
|
protocolVersion;
|
|
504
505
|
topicStrings;
|
|
505
506
|
/** Callback invoked when a duplicate proposal is detected (triggers slashing). */ duplicateProposalCallback;
|
|
507
|
+
/** Callback invoked when an oversized block proposal is stored as slashing evidence (triggers slashing). */ oversizedProposalCallback;
|
|
506
508
|
/** Callback invoked when a duplicate attestation is detected (triggers slashing). */ duplicateAttestationCallback;
|
|
507
509
|
/** Callback invoked when a valid checkpoint attestation is accepted into the pool. */ checkpointAttestationCallback;
|
|
508
510
|
/**
|
|
@@ -593,7 +595,7 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
593
595
|
const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
|
|
594
596
|
const datastore = new AztecDatastore(peerStore);
|
|
595
597
|
const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
|
|
596
|
-
const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`, logger.getBindings()));
|
|
598
|
+
const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`, logger.getBindings()), peerStore);
|
|
597
599
|
// Seed libp2p's bootstrap discovery with private and trusted peers
|
|
598
600
|
const bootstrapNodes = [
|
|
599
601
|
...config.privatePeers,
|
|
@@ -608,19 +610,27 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
608
610
|
const versions = getVersions(config);
|
|
609
611
|
const protocolVersion = compressComponentVersions(versions);
|
|
610
612
|
const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
|
|
611
|
-
const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
613
|
+
const directPeers = compactArray(await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
614
|
+
try {
|
|
615
|
+
const peerId = await enr.peerId();
|
|
616
|
+
const address = enr.getLocationMultiaddr('tcp');
|
|
617
|
+
if (address === undefined) {
|
|
618
|
+
throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
|
|
619
|
+
}
|
|
620
|
+
return {
|
|
621
|
+
id: peerId,
|
|
622
|
+
addrs: [
|
|
623
|
+
address
|
|
624
|
+
]
|
|
625
|
+
};
|
|
626
|
+
} catch (err) {
|
|
627
|
+
// A malformed configured ENR shouldn't abort node setup — skip it and log.
|
|
628
|
+
logger.warn(`Skipping preferred peer with invalid ENR`, {
|
|
629
|
+
err
|
|
630
|
+
});
|
|
631
|
+
return undefined;
|
|
616
632
|
}
|
|
617
|
-
|
|
618
|
-
id: peerId,
|
|
619
|
-
addrs: [
|
|
620
|
-
address
|
|
621
|
-
]
|
|
622
|
-
};
|
|
623
|
-
}))).filter((peer)=>peer !== undefined);
|
|
633
|
+
})));
|
|
624
634
|
const announceTcpMultiaddr = config.p2pIp ? [
|
|
625
635
|
convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
|
|
626
636
|
] : [];
|
|
@@ -635,6 +645,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
635
645
|
maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint ?? DEFAULT_MAX_BLOCKS_PER_CHECKPOINT,
|
|
636
646
|
expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot
|
|
637
647
|
});
|
|
648
|
+
// Restrict gossipsub to exactly the topics we subscribe to. Without this, an arbitrary-topic
|
|
649
|
+
// message is transformed, msg-id'd and inserted into the seenCache before the subscription check,
|
|
650
|
+
// so a crafted topic colliding on msg id can suppress a real message as a duplicate.
|
|
651
|
+
const allowedTopics = getTopicsForConfig(config.disableTransactions).map((topic)=>createTopicString(topic, protocolVersion));
|
|
638
652
|
const node = await createLibp2p({
|
|
639
653
|
start: false,
|
|
640
654
|
peerId,
|
|
@@ -668,8 +682,11 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
668
682
|
],
|
|
669
683
|
datastore,
|
|
670
684
|
peerDiscovery,
|
|
685
|
+
// Pin the yamux frame size: MAX_REQRESP_REQUEST_SIZE_BYTES relies on a reqresp request fitting in one frame.
|
|
671
686
|
streamMuxers: [
|
|
672
|
-
yamux(
|
|
687
|
+
yamux({
|
|
688
|
+
maxMessageSize: YAMUX_MAX_MESSAGE_SIZE_BYTES
|
|
689
|
+
}),
|
|
673
690
|
mplex()
|
|
674
691
|
],
|
|
675
692
|
connectionEncryption: [
|
|
@@ -724,9 +741,13 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
724
741
|
mcacheLength: config.gossipsubMcacheLength,
|
|
725
742
|
mcacheGossip: config.gossipsubMcacheGossip,
|
|
726
743
|
seenTTL: config.gossipsubSeenTTL,
|
|
744
|
+
allowedTopics,
|
|
745
|
+
// No fastMsgIdFn: the fast-path dedup cache keys on a non-cryptographic 64-bit hash of the
|
|
746
|
+
// raw data only (no topic), so a collision — accidental or engineered via a weak seed — drops
|
|
747
|
+
// a different message with no fallback to the full id. Dedup instead rests solely on the
|
|
748
|
+
// cryptographic, topic-framed msgIdFn below.
|
|
727
749
|
msgIdFn: getMsgIdFn,
|
|
728
750
|
msgIdToStrFn: msgIdToStrFn,
|
|
729
|
-
fastMsgIdFn: fastMsgIdFn,
|
|
730
751
|
dataTransform: new SnappyTransform(),
|
|
731
752
|
metricsRegister: otelMetricsAdapter,
|
|
732
753
|
metricsTopicStrToLabel: metricsTopicStrToLabels(protocolVersion),
|
|
@@ -911,6 +932,11 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
911
932
|
this.duplicateProposalCallback = callback;
|
|
912
933
|
}
|
|
913
934
|
/**
|
|
935
|
+
* Registers a callback to be invoked when an oversized block proposal is stored as slashing evidence.
|
|
936
|
+
*/ registerOversizedProposalCallback(callback) {
|
|
937
|
+
this.oversizedProposalCallback = callback;
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
914
940
|
* Registers a callback to be invoked when a duplicate attestation is detected.
|
|
915
941
|
* A validator signing attestations for different proposals at the same slot.
|
|
916
942
|
* This callback is triggered on the first duplicate (when count goes from 1 to 2).
|
|
@@ -1357,9 +1383,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1357
1383
|
};
|
|
1358
1384
|
}
|
|
1359
1385
|
async processBlockFromPeer(payloadData, msgId, source) {
|
|
1360
|
-
const { result, obj: block, metadata: { isEquivocated } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)), msgId, source, TopicType.block_proposal);
|
|
1361
|
-
// If not accepted or
|
|
1362
|
-
|
|
1386
|
+
const { result, obj: block, metadata: { isEquivocated, isOversized } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)), msgId, source, TopicType.block_proposal);
|
|
1387
|
+
// If not accepted, equivocated, or oversized, return. Oversized proposals are re-broadcast as
|
|
1388
|
+
// slashing evidence but never attested or processed.
|
|
1389
|
+
if (result !== TopicValidatorResult.Accept || !block || isEquivocated || isOversized) {
|
|
1363
1390
|
return;
|
|
1364
1391
|
}
|
|
1365
1392
|
await this.processValidBlockProposal(block, source);
|
|
@@ -1382,6 +1409,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1382
1409
|
// Try to add the proposal: this handles existence check, cap check, and adding in one call
|
|
1383
1410
|
const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
|
|
1384
1411
|
const isEquivocated = count !== undefined && count > 1;
|
|
1412
|
+
// An oversized proposal (index at or beyond the consensus per-checkpoint limit) is structurally valid
|
|
1413
|
+
// proposer misbehavior: it is stored and re-broadcast as slashing evidence but never processed or
|
|
1414
|
+
// attested to. No-ops when maxBlocksPerCheckpoint is unset (local/test).
|
|
1415
|
+
const isOversized = this.config.maxBlocksPerCheckpoint !== undefined && block.indexWithinCheckpoint >= this.config.maxBlocksPerCheckpoint;
|
|
1385
1416
|
// Duplicate proposal received, no need to re-broadcast
|
|
1386
1417
|
if (alreadyExists) {
|
|
1387
1418
|
this.logger.debug(`Ignoring duplicate block proposal received`, {
|
|
@@ -1394,7 +1425,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1394
1425
|
result: TopicValidatorResult.Ignore,
|
|
1395
1426
|
obj: block,
|
|
1396
1427
|
metadata: {
|
|
1397
|
-
isEquivocated
|
|
1428
|
+
isEquivocated,
|
|
1429
|
+
isOversized
|
|
1398
1430
|
}
|
|
1399
1431
|
};
|
|
1400
1432
|
}
|
|
@@ -1410,11 +1442,30 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1410
1442
|
return {
|
|
1411
1443
|
result: TopicValidatorResult.Reject,
|
|
1412
1444
|
metadata: {
|
|
1413
|
-
isEquivocated
|
|
1445
|
+
isEquivocated,
|
|
1446
|
+
isOversized
|
|
1414
1447
|
},
|
|
1415
1448
|
severity: PeerErrorSeverity.HighToleranceError
|
|
1416
1449
|
};
|
|
1417
1450
|
}
|
|
1451
|
+
// The proposal was stored: if oversized, invoke the oversized callback so the proposer can be
|
|
1452
|
+
// slashed. Fired alongside (not instead of) equivocation detection below.
|
|
1453
|
+
if (isOversized) {
|
|
1454
|
+
const proposer = block.getSender();
|
|
1455
|
+
if (proposer) {
|
|
1456
|
+
this.logger.warn(`Detected oversized block proposal at slot ${block.slotNumber}`, {
|
|
1457
|
+
...block.toBlockInfo(),
|
|
1458
|
+
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
1459
|
+
maxBlocksPerCheckpoint: this.config.maxBlocksPerCheckpoint,
|
|
1460
|
+
source: peerId.toString(),
|
|
1461
|
+
proposer: proposer.toString()
|
|
1462
|
+
});
|
|
1463
|
+
this.oversizedProposalCallback?.({
|
|
1464
|
+
slot: block.slotNumber,
|
|
1465
|
+
proposer
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1418
1469
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
1419
1470
|
// and do re-broadcast it so other nodes in the network know to slash the proposer
|
|
1420
1471
|
if (isEquivocated) {
|
|
@@ -1436,14 +1487,19 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1436
1487
|
result: TopicValidatorResult.Accept,
|
|
1437
1488
|
obj: block,
|
|
1438
1489
|
metadata: {
|
|
1439
|
-
isEquivocated
|
|
1490
|
+
isEquivocated,
|
|
1491
|
+
isOversized
|
|
1440
1492
|
}
|
|
1441
1493
|
};
|
|
1442
1494
|
}
|
|
1443
1495
|
// Otherwise, we're good to go!
|
|
1444
1496
|
return {
|
|
1445
1497
|
result: TopicValidatorResult.Accept,
|
|
1446
|
-
obj: block
|
|
1498
|
+
obj: block,
|
|
1499
|
+
metadata: {
|
|
1500
|
+
isEquivocated: false,
|
|
1501
|
+
isOversized
|
|
1502
|
+
}
|
|
1447
1503
|
};
|
|
1448
1504
|
}
|
|
1449
1505
|
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
@@ -1471,9 +1527,10 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1471
1527
|
* Handle a gossiped checkpoint proposal.
|
|
1472
1528
|
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1473
1529
|
*/ async handleGossipedCheckpointProposal(payloadData, msgId, source) {
|
|
1474
|
-
const { result, obj: checkpoint, metadata: { isEquivocated, processBlock } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_proposal);
|
|
1475
|
-
//
|
|
1476
|
-
|
|
1530
|
+
const { result, obj: checkpoint, metadata: { isEquivocated, processBlock, isOversized } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_proposal);
|
|
1531
|
+
// An oversized checkpoint is re-broadcast as slashing evidence but never attested or processed.
|
|
1532
|
+
// Process checkpoint proposal if valid and neither equivocated nor oversized.
|
|
1533
|
+
const processCheckpointFn = ()=>result === TopicValidatorResult.Accept && checkpoint && !isEquivocated && !isOversized ? this.processValidCheckpointProposal(checkpoint.toCore(), source) : Promise.resolve();
|
|
1477
1534
|
// If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
|
|
1478
1535
|
// TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
|
|
1479
1536
|
const processBlockFn = ()=>processBlock && checkpoint && checkpoint.getBlockProposal() ? this.processValidBlockProposal(checkpoint.getBlockProposal(), source) : Promise.resolve();
|
|
@@ -1512,13 +1569,15 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1512
1569
|
// Extract and try to add the block proposal first if present
|
|
1513
1570
|
const blockProposal = checkpoint.getBlockProposal();
|
|
1514
1571
|
let processBlock = false;
|
|
1572
|
+
let isOversized = false;
|
|
1515
1573
|
if (blockProposal) {
|
|
1516
1574
|
this.logger.debug(`Validating block proposal from propagated checkpoint`, {
|
|
1517
1575
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1518
1576
|
[Attributes.P2P_ID]: peerId.toString()
|
|
1519
1577
|
});
|
|
1520
1578
|
const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1521
|
-
const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
|
|
1579
|
+
const { obj, metadata: { isEquivocated, isOversized: blockIsOversized } = {} } = blockProposalResult;
|
|
1580
|
+
isOversized = blockIsOversized ?? false;
|
|
1522
1581
|
if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1523
1582
|
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1524
1583
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
@@ -1530,7 +1589,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1530
1589
|
result: TopicValidatorResult.Reject,
|
|
1531
1590
|
severity: 'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError
|
|
1532
1591
|
};
|
|
1533
|
-
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1592
|
+
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated && !isOversized) {
|
|
1593
|
+
// An oversized terminal block is re-broadcast as slashing evidence but never processed.
|
|
1534
1594
|
processBlock = true;
|
|
1535
1595
|
}
|
|
1536
1596
|
}
|
|
@@ -1550,11 +1610,12 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1550
1610
|
obj: checkpoint,
|
|
1551
1611
|
metadata: {
|
|
1552
1612
|
isEquivocated,
|
|
1553
|
-
processBlock
|
|
1613
|
+
processBlock,
|
|
1614
|
+
isOversized
|
|
1554
1615
|
}
|
|
1555
1616
|
};
|
|
1556
1617
|
}
|
|
1557
|
-
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1618
|
+
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast.
|
|
1558
1619
|
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1559
1620
|
if (!added) {
|
|
1560
1621
|
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
@@ -1567,7 +1628,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1567
1628
|
obj: checkpoint,
|
|
1568
1629
|
metadata: {
|
|
1569
1630
|
isEquivocated,
|
|
1570
|
-
processBlock
|
|
1631
|
+
processBlock,
|
|
1632
|
+
isOversized
|
|
1571
1633
|
},
|
|
1572
1634
|
severity: PeerErrorSeverity.HighToleranceError
|
|
1573
1635
|
};
|
|
@@ -1594,7 +1656,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1594
1656
|
obj: checkpoint,
|
|
1595
1657
|
metadata: {
|
|
1596
1658
|
isEquivocated,
|
|
1597
|
-
processBlock
|
|
1659
|
+
processBlock,
|
|
1660
|
+
isOversized
|
|
1598
1661
|
}
|
|
1599
1662
|
};
|
|
1600
1663
|
}
|
|
@@ -1604,7 +1667,8 @@ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId
|
|
|
1604
1667
|
obj: checkpoint,
|
|
1605
1668
|
metadata: {
|
|
1606
1669
|
processBlock,
|
|
1607
|
-
isEquivocated
|
|
1670
|
+
isEquivocated,
|
|
1671
|
+
isOversized
|
|
1608
1672
|
}
|
|
1609
1673
|
};
|
|
1610
1674
|
}
|
|
@@ -188,4 +188,4 @@ export declare class PeerManager implements PeerManagerInterface {
|
|
|
188
188
|
handleAuthRequestFromPeer(_authRequest: AuthRequest, peerId: PeerId): Promise<StatusMessage>;
|
|
189
189
|
private updateAuthenticatedPeers;
|
|
190
190
|
}
|
|
191
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
191
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVlcl9tYW5hZ2VyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvcGVlci1tYW5hZ2VyL3BlZXJfbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBSTlELE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBR2hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxRQUFRLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN4RixPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzNELE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRS9ELE9BQU8sS0FBSyxFQUFjLE1BQU0sRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBTTVELE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWpELE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVoRCxPQUFPLEVBQUUsV0FBVyxFQUFnQixNQUFNLDhCQUE4QixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxhQUFhLEVBQXVCLE1BQU0saUNBQWlDLENBQUM7QUFDckYsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQy9ELE9BQU8sS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXJELE9BQU8sS0FBSyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzFELE9BQU8sS0FBSyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0QsT0FBTyxFQUFrQixLQUFLLFdBQVcsRUFBRSxNQUFNLG1C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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peer_manager.d.ts","sourceRoot":"","sources":["../../../src/services/peer-manager/peer_manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"peer_manager.d.ts","sourceRoot":"","sources":["../../../src/services/peer-manager/peer_manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAI9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAGhE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACxF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAM5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAgB,MAAM,8BAA8B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAuB,MAAM,iCAAiC,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA2BrE,qBAAa,WAAY,YAAW,oBAAoB;IAyBpD,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,oBAAoB;IAC5B,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAlC/B,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,gBAAgB,CAAa;IACrC,OAAO,CAAC,8BAA8B,CAAa;IACnD,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,uBAAuB,CAAkB;IACjD,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,uBAAuB,CAAkB;IACjD,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,qCAAqC,CAAsC;IACnF,OAAO,CAAC,qCAAqC,CAAkC;IAC/E,OAAO,CAAC,qBAAqB,CAA0B;IACvD,OAAO,CAAC,oBAAoB,CAAoD;IAChF,OAAO,CAAC,kBAAkB,CAAoB;IAC9C,OAAO,CAAC,yBAAyB,CAAkB;IAEnD,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,QAAQ,CAId;IAEF,YACU,UAAU,EAAE,UAAU,EACtB,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,EAAE,SAAS,EACzB,eAAe,EAAE,eAAe,EACxB,MAAM,oDAAmC,EACzC,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,OAAO,EACP,sBAAsB,EAAE,sBAAsB,EAC9C,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,mBAAmB,EAC/B,YAAY,GAAE,YAAiC,EAyBjE;IACD;;;;OAIG;IACG,eAAe,kBAmCpB;IAED,IAAI,MAAM,6CAET;IAEY,SAAS,kBAWrB;IAIK,2BAA2B,kBAsDhC;IAED;;;;;;;;;;OAUG;IACH,OAAO,CAAC,sBAAsB;YAsBhB,2BAA2B;IAsBzC;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAuBhC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAmB5B,8BAA8B,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAEjE;IAED;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACI,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAM1C;IAED;;;OAGG;IACI,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAQ1C;IAED;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACI,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAK5C;IAED;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAIvB;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAIvB;;;;;;OAMG;IACI,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,QAM3D;IAEM,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,QAE7D;IAEM,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1C;IAEM,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGrD;IAEM,QAAQ,CAAC,cAAc,UAAQ,GAAG,QAAQ,EAAE,CA+BlD;IAEM,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQlD;IASD;;;;OAIG;IACI,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAM9D;IAED;;;;OAIG;IACI,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;IAED,sGAAsG;IACtG,OAAO,CAAC,uBAAuB;IAe/B;;OAEG;IACH,OAAO,CAAC,QAAQ;IAoEhB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,mBAAmB;IAsB3B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;YAyBT,wBAAwB;IAgCtC,OAAO,CAAC,qBAAqB;YAYf,cAAc;YAkBd,oBAAoB;YA0EpB,QAAQ;IA4BtB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,gBAAgB;YAsBV,mBAAmB;YAenB,uBAAuB;YA2CvB,qBAAqB;IA2FnC,OAAO,CAAC,uBAAuB;IAmC/B,OAAO,CAAC,wBAAwB;IAUhC;;;OAGG;IACU,IAAI,kBAWhB;IAED,OAAO,CAAC,uBAAuB;IAI/B;;;;;;;;;SASK;IACQ,yBAAyB,CAAC,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAOxG;YAEa,wBAAwB;CAwBvC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { compactArray } from '@aztec/foundation/collection';
|
|
1
2
|
import { makeEthSignDigest, tryRecoverAddress } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
2
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -151,19 +152,27 @@ export class PeerManager {
|
|
|
151
152
|
}
|
|
152
153
|
const preferredPeersEnrs = this.config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
|
|
153
154
|
await Promise.all(preferredPeersEnrs.map((enr)=>enr.peerId())).then((peerIds)=>peerIds.forEach((peerId)=>this.preferredPeers.add(peerId.toString()))).catch((e)=>this.logger.error('Error initializing preferred peers', e));
|
|
154
|
-
const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
const directPeers = compactArray(await Promise.all(preferredPeersEnrs.map(async (enr)=>{
|
|
156
|
+
try {
|
|
157
|
+
const peerId = await enr.peerId();
|
|
158
|
+
const address = enr.getLocationMultiaddr('tcp');
|
|
159
|
+
if (address === undefined) {
|
|
160
|
+
throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
id: peerId,
|
|
164
|
+
addrs: [
|
|
165
|
+
address
|
|
166
|
+
]
|
|
167
|
+
};
|
|
168
|
+
} catch (err) {
|
|
169
|
+
// A malformed configured ENR shouldn't abort preferred-peer setup — skip it and log.
|
|
170
|
+
this.logger.warn(`Skipping preferred peer with invalid ENR`, {
|
|
171
|
+
err
|
|
172
|
+
});
|
|
173
|
+
return undefined;
|
|
159
174
|
}
|
|
160
|
-
|
|
161
|
-
id: peerId,
|
|
162
|
-
addrs: [
|
|
163
|
-
address
|
|
164
|
-
]
|
|
165
|
-
};
|
|
166
|
-
}))).filter((peer)=>peer !== undefined);
|
|
175
|
+
})));
|
|
167
176
|
await Promise.all(directPeers.map((peer)=>{
|
|
168
177
|
this.libP2PNode.services.pubsub.direct.add(peer.id.toString());
|
|
169
178
|
return this.libP2PNode.peerStore.merge(peer.id, {
|
|
@@ -3,6 +3,18 @@ export declare const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS = 10000;
|
|
|
3
3
|
export declare const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS = 10000;
|
|
4
4
|
export declare const DEFAULT_REQRESP_DIAL_TIMEOUT_MS = 5000;
|
|
5
5
|
export declare const DEFAULT_OPTIMISTIC_NEGOTIATION = false;
|
|
6
|
+
/**
|
|
7
|
+
* Max size of a yamux frame, header included. This is the library default, pinned explicitly when configuring the
|
|
8
|
+
* muxer in the libp2p service so a dependency upgrade cannot silently change it.
|
|
9
|
+
*/
|
|
10
|
+
export declare const YAMUX_MAX_MESSAGE_SIZE_BYTES: number;
|
|
11
|
+
/**
|
|
12
|
+
* Max size of a reqresp request payload. A request must fit in a single muxer frame: the responder never reassembles
|
|
13
|
+
* a request from multiple chunks (see `ReqResp.processStream`), and yamux splits writes larger than one frame into
|
|
14
|
+
* multiple frames, each of which arrives as a separate chunk. mplex only splits at 1 MiB, so yamux is the binding
|
|
15
|
+
* constraint.
|
|
16
|
+
*/
|
|
17
|
+
export declare const MAX_REQRESP_REQUEST_SIZE_BYTES: number;
|
|
6
18
|
export declare const DEFAULT_P2P_REQRESP_CONFIG: P2PReqRespConfig;
|
|
7
19
|
export interface P2PReqRespConfig {
|
|
8
20
|
/** The overall timeout for a request response operation. */
|
|
@@ -15,4 +27,4 @@ export interface P2PReqRespConfig {
|
|
|
15
27
|
dialTimeoutMs: number;
|
|
16
28
|
}
|
|
17
29
|
export declare const p2pReqRespConfigMappings: ConfigMappingsType<P2PReqRespConfig>;
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
30
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvcmVxcmVzcC9jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssa0JBQWtCLEVBQTJDLE1BQU0sMEJBQTBCLENBQUM7QUFFNUcsZUFBTyxNQUFNLHFDQUFxQyxRQUFTLENBQUM7QUFDNUQsZUFBTyxNQUFNLGtDQUFrQyxRQUFTLENBQUM7QUFDekQsZUFBTyxNQUFNLCtCQUErQixPQUFRLENBQUM7QUFDckQsZUFBTyxNQUFNLDhCQUE4QixRQUFRLENBQUM7QUFFcEQ7OztHQUdHO0FBQ0gsZUFBTyxNQUFNLDRCQUE0QixRQUFZLENBQUM7QUFLdEQ7Ozs7O0dBS0c7QUFDSCxlQUFPLE1BQU0sOEJBQThCLFFBQTJELENBQUM7QUFHdkcsZUFBTyxNQUFNLDBCQUEwQixFQUFFLGdCQUt4QyxDQUFDO0FBRUYsTUFBTSxXQUFXLGdCQUFnQjtJQUMvQiw0REFBNEQ7SUFDNUQsdUJBQXVCLEVBQUUsTUFBTSxDQUFDO0lBRWhDLHVFQUF1RTtJQUN2RSwwQkFBMEIsRUFBRSxNQUFNLENBQUM7SUFFbkMsa0hBQWtIO0lBQ2xILHdCQUF3QixFQUFFLE9BQU8sQ0FBQztJQUVsQyx1RUFBdUU7SUFDdkUsYUFBYSxFQUFFLE1BQU0sQ0FBQztDQUN2QjtBQUVELGVBQU8sTUFBTSx3QkFBd0IsRUFBRSxrQkFBa0IsQ0FBQyxnQkFBZ0IsQ0FzQnpFLENBQUMifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAA2C,MAAM,0BAA0B,CAAC;AAE5G,eAAO,MAAM,qCAAqC,QAAS,CAAC;AAC5D,eAAO,MAAM,kCAAkC,QAAS,CAAC;AACzD,eAAO,MAAM,+BAA+B,OAAQ,CAAC;AACrD,eAAO,MAAM,8BAA8B,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAA2C,MAAM,0BAA0B,CAAC;AAE5G,eAAO,MAAM,qCAAqC,QAAS,CAAC;AAC5D,eAAO,MAAM,kCAAkC,QAAS,CAAC;AACzD,eAAO,MAAM,+BAA+B,OAAQ,CAAC;AACrD,eAAO,MAAM,8BAA8B,QAAQ,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,4BAA4B,QAAY,CAAC;AAKtD;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,QAA2D,CAAC;AAGvG,eAAO,MAAM,0BAA0B,EAAE,gBAKxC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,uBAAuB,EAAE,MAAM,CAAC;IAEhC,uEAAuE;IACvE,0BAA0B,EAAE,MAAM,CAAC;IAEnC,kHAAkH;IAClH,wBAAwB,EAAE,OAAO,CAAC;IAElC,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,wBAAwB,EAAE,kBAAkB,CAAC,gBAAgB,CAsBzE,CAAC"}
|
|
@@ -3,6 +3,17 @@ export const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS = 10_000;
|
|
|
3
3
|
export const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS = 10_000; // Not currently used
|
|
4
4
|
export const DEFAULT_REQRESP_DIAL_TIMEOUT_MS = 5_000;
|
|
5
5
|
export const DEFAULT_OPTIMISTIC_NEGOTIATION = false;
|
|
6
|
+
/**
|
|
7
|
+
* Max size of a yamux frame, header included. This is the library default, pinned explicitly when configuring the
|
|
8
|
+
* muxer in the libp2p service so a dependency upgrade cannot silently change it.
|
|
9
|
+
*/ export const YAMUX_MAX_MESSAGE_SIZE_BYTES = 64 * 1024;
|
|
10
|
+
/** Size of a yamux data frame header. */ const YAMUX_HEADER_LENGTH_BYTES = 12;
|
|
11
|
+
/**
|
|
12
|
+
* Max size of a reqresp request payload. A request must fit in a single muxer frame: the responder never reassembles
|
|
13
|
+
* a request from multiple chunks (see `ReqResp.processStream`), and yamux splits writes larger than one frame into
|
|
14
|
+
* multiple frames, each of which arrives as a separate chunk. mplex only splits at 1 MiB, so yamux is the binding
|
|
15
|
+
* constraint.
|
|
16
|
+
*/ export const MAX_REQRESP_REQUEST_SIZE_BYTES = YAMUX_MAX_MESSAGE_SIZE_BYTES - YAMUX_HEADER_LENGTH_BYTES;
|
|
6
17
|
// For use in tests.
|
|
7
18
|
export const DEFAULT_P2P_REQRESP_CONFIG = {
|
|
8
19
|
overallRequestTimeoutMs: DEFAULT_OVERALL_REQUEST_TIMEOUT_MS,
|
|
@@ -8,7 +8,7 @@ export const DEFAULT_RATE_LIMITS = {
|
|
|
8
8
|
},
|
|
9
9
|
globalLimit: {
|
|
10
10
|
quotaTimeMs: 1000,
|
|
11
|
-
quotaCount:
|
|
11
|
+
quotaCount: 50
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
[ReqRespSubProtocol.STATUS]: {
|
|
@@ -18,7 +18,7 @@ export const DEFAULT_RATE_LIMITS = {
|
|
|
18
18
|
},
|
|
19
19
|
globalLimit: {
|
|
20
20
|
quotaTimeMs: 1000,
|
|
21
|
-
quotaCount:
|
|
21
|
+
quotaCount: 50
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
[ReqRespSubProtocol.AUTH]: {
|
|
@@ -48,7 +48,7 @@ export const DEFAULT_RATE_LIMITS = {
|
|
|
48
48
|
},
|
|
49
49
|
globalLimit: {
|
|
50
50
|
quotaTimeMs: 1000,
|
|
51
|
-
quotaCount:
|
|
51
|
+
quotaCount: 50
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
[ReqRespSubProtocol.BLOCK_TXS]: {
|
|
@@ -104,4 +104,4 @@ export declare class ReqResp implements ReqRespInterface {
|
|
|
104
104
|
private categorizeResponseError;
|
|
105
105
|
private categorizeConnectionErrors;
|
|
106
106
|
}
|
|
107
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
107
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxcmVzcC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3JlcXJlc3AvcmVxcmVzcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxPQUFPLEVBQWMsS0FBSyxlQUFlLEVBQWlDLE1BQU0seUJBQXlCLENBQUM7QUFFMUcsT0FBTyxLQUFLLEVBQXNCLE1BQU0sRUFBVSxNQUFNLG1CQUFtQixDQUFDO0FBQzVFLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLFFBQVEsQ0FBQztBQVdyQyxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuRSxPQUFPLEVBSUwsS0FBSyxnQkFBZ0IsRUFDdEIsTUFBTSxhQUFhLENBQUM7QUFDckIsT0FBTyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLDRDQUE0QyxDQUFDO0FBQzlGLE9BQU8sRUFDTCxLQUFLLGdCQUFnQixFQUNyQixLQUFLLGVBQWUsRUFDcEIsa0JBQWtCLEVBQ2xCLEtBQUsseUJBQXlCLEVBQzlCLEtBQUssMEJBQTBCLEVBQy9CLEtBQUssNEJBQTRCLEVBQ2pDLEtBQUssZ0JBQWdCLEVBR3RCLE1BQU0sZ0JBQWdCLENBQUM7QUFTeEI7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILHFCQUFhLE9BQVEsWUFBVyxnQkFBZ0I7SUFpQjVDLE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLFdBQVc7SUFDbkIsT0FBTyxDQUFDLE1BQU07SUFsQmhCLE9BQU8sQ0FBQywwQkFBMEIsQ0FBaUQ7SUFDbkYsT0FBTyxDQUFDLGFBQWEsQ0FBMkM7SUFFaEUsT0FBTyxDQUFDLG1CQUFtQixDQUEyQztJQUV0RSxPQUFPLENBQUMsaUJBQWlCLENBQW9CO0lBQzdDLE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBRWhELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBRXpDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBK0I7SUFFdkQsT0FBTyxDQUFDLE9BQU8sQ0FBaUI7SUFFaEMsWUFDRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQ2hCLE1BQU0sRUFBRSxNQUFNLEVBQ2QsV0FBVyxFQUFFLFdBQVcsRUFDeEIsTUFBTSx5Q0FBOEIsRUFDNUMsVUFBVSxHQUFFLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBTSxFQUN0RCxlQUFlLEdBQUUsZUFBc0MsRUFnQnhEO0lBRU0sWUFBWSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxJQUFJLENBUTNEO0lBRU0sbUJBQW1CLENBQUMsT0FBTyxFQUFFLGdCQUFnQixHQUFHLElBQUksQ0FFMUQ7SUFFRCxJQUFJLE1BQU0sNkNBRVQ7SUFFRDs7T0FFRztJQUNILG9CQUFvQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRSx1Q0FBdUMsQ0FBQyxDQUV2RjtJQUVEOztPQUVHO0lBQ0csS0FBSyxDQUFDLG1CQUFtQixFQUFFLDBCQUEwQixpQkFnQjFEO0lBRUssY0FBYyxDQUFDLFdBQVcsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVV2RztJQUVEOztPQUVHO0lBQ0csSUFBSSxrQkFrQlQ7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09Bd0JHO0lBS1UsaUJBQWlCLENBQzVCLE1BQU0sRUFBRSxNQUFNLEVBQ2QsV0FBVyxFQUFFLGtCQUFrQixFQUMvQixPQUFPLEVBQUUsTUFBTSxFQUNmLFdBQVcsR0FBRSxNQUEyQixHQUN2QyxPQUFPLENBQUMsZUFBZSxDQUFDLENBZ0UxQjtJQUVEOzs7Ozs7Ozs7T0FTRztJQUNILE9BQU8sQ0FBQyxtQkFBbUI7WUF5QmIsV0FBVztZQXNFWCxhQUFhO1lBMEViLGFBQWE7WUE0Q2IsWUFBWTtJQW1DMUIsT0FBTyxDQUFDLGtCQUFrQjtJQU8xQjs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLHNCQUFzQjtJQWlCOUI7Ozs7T0FJRztJQUNILE9BQU8sQ0FBQyx1QkFBdUI7SUF5Qy9CLE9BQU8sQ0FBQywwQkFBMEI7Q0E4RG5DIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/reqresp.ts"],"names":[],"mappings":"AAKA,OAAO,EAAc,KAAK,eAAe,EAAiC,MAAM,yBAAyB,CAAC;AAE1G,OAAO,KAAK,EAAsB,MAAM,EAAU,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/reqresp.ts"],"names":[],"mappings":"AAKA,OAAO,EAAc,KAAK,eAAe,EAAiC,MAAM,yBAAyB,CAAC;AAE1G,OAAO,KAAK,EAAsB,MAAM,EAAU,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAWrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,iBAAiB,EAAiB,MAAM,4CAA4C,CAAC;AAC9F,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AASxB;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAQ,YAAW,gBAAgB;IAiB5C,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAlBhB,OAAO,CAAC,0BAA0B,CAAiD;IACnF,OAAO,CAAC,aAAa,CAA2C;IAEhE,OAAO,CAAC,mBAAmB,CAA2C;IAEtE,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,WAAW,CAA6B;IAEhD,OAAO,CAAC,eAAe,CAAkB;IAEzC,OAAO,CAAC,gBAAgB,CAA+B;IAEvD,OAAO,CAAC,OAAO,CAAiB;IAEhC,YACE,MAAM,EAAE,gBAAgB,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,MAAM,yCAA8B,EAC5C,UAAU,GAAE,OAAO,CAAC,4BAA4B,CAAM,EACtD,eAAe,GAAE,eAAsC,EAgBxD;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAQ3D;IAEM,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAE1D;IAED,IAAI,MAAM,6CAET;IAED;;OAEG;IACH,oBAAoB,IAAI,IAAI,CAAC,iBAAiB,EAAE,uCAAuC,CAAC,CAEvF;IAED;;OAEG;IACG,KAAK,CAAC,mBAAmB,EAAE,0BAA0B,iBAgB1D;IAEK,cAAc,CAAC,WAAW,EAAE,kBAAkB,EAAE,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUvG;IAED;;OAEG;IACG,IAAI,kBAkBT;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IAKU,iBAAiB,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAA2B,GACvC,OAAO,CAAC,eAAe,CAAC,CAgE1B;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;YAyBb,WAAW;YAsEX,aAAa;YA0Eb,aAAa;YA4Cb,YAAY;IAmC1B,OAAO,CAAC,kBAAkB;IAO1B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAiB9B;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAyC/B,OAAO,CAAC,0BAA0B;CA8DnC"}
|
|
@@ -378,9 +378,9 @@ import { executeTimeout } from '@aztec/foundation/timer';
|
|
|
378
378
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
379
379
|
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
380
380
|
import { pipeline } from 'node:stream/promises';
|
|
381
|
-
import { IndividualReqRespTimeoutError } from '../../errors/reqresp.error.js';
|
|
382
|
-
import { OversizedSnappyResponseError, SnappyTransform } from '../encoding.js';
|
|
383
|
-
import { DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS, DEFAULT_REQRESP_DIAL_TIMEOUT_MS } from './config.js';
|
|
381
|
+
import { IndividualReqRespTimeoutError, OversizedReqRespRequestError } from '../../errors/reqresp.error.js';
|
|
382
|
+
import { DEFAULT_MAX_RESPONSE_SIZE_KB, OversizedSnappyResponseError, ResponseSizeLimitExceededError, SnappyTransform } from '../encoding.js';
|
|
383
|
+
import { DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS, DEFAULT_REQRESP_DIAL_TIMEOUT_MS, MAX_REQRESP_REQUEST_SIZE_BYTES } from './config.js';
|
|
384
384
|
import { ConnectionSampler, RandomSampler } from './connection-sampler/connection_sampler.js';
|
|
385
385
|
import { ReqRespSubProtocol, UNAUTHENTICATED_ALLOWED_PROTOCOLS, subProtocolSizeCalculators } from './interface.js';
|
|
386
386
|
import { ReqRespMetrics } from './metrics.js';
|
|
@@ -524,6 +524,10 @@ _dec = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
|
|
|
524
524
|
* If the stream is not closed by the dialled peer, and a timeout occurs, then
|
|
525
525
|
* the stream is closed on the requester's end and sender (us) updates its peer score
|
|
526
526
|
*/ async sendRequestToPeer(peerId, subProtocol, payload, dialTimeout = this.dialTimeoutMs) {
|
|
527
|
+
// Thrown before the try block so the generic error handling below does not penalize the peer for our own bug.
|
|
528
|
+
if (payload.length > MAX_REQRESP_REQUEST_SIZE_BYTES) {
|
|
529
|
+
throw new OversizedReqRespRequestError(subProtocol, payload.length, MAX_REQRESP_REQUEST_SIZE_BYTES);
|
|
530
|
+
}
|
|
527
531
|
let stream;
|
|
528
532
|
try {
|
|
529
533
|
this.metrics.recordRequestSent(subProtocol);
|
|
@@ -596,15 +600,32 @@ _dec = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
|
|
|
596
600
|
* - The first chunk should contain a control byte, indicating the status of the response see `ReqRespStatus`
|
|
597
601
|
* - The second chunk should contain the response data
|
|
598
602
|
*
|
|
603
|
+
* To bound memory usage we abort reception as soon as the accumulated compressed bytes exceed a
|
|
604
|
+
* bound derived from `maxSizeKb`, before the full stream has been buffered. Without this a peer we
|
|
605
|
+
* dialed could stream data up to the request timeout, forcing us to buffer arbitrarily much (the
|
|
606
|
+
* `maxSizeKb` guard in `inboundTransformData` only runs after the whole compressed payload is
|
|
607
|
+
* concatenated, so it does nothing to cap reception memory). Snappy can expand incompressible input
|
|
608
|
+
* to ~1.17x its size, so we allow 2x `maxSizeKb`: comfortably above the worst-case expansion of a
|
|
609
|
+
* legitimate max-size response, while still capping buffered memory at twice the permitted size.
|
|
610
|
+
*
|
|
599
611
|
* @param source - The async iterable source of data chunks
|
|
600
612
|
* @param maxSizeKb - Optional maximum expected size in KB for the decompressed response
|
|
601
613
|
*/ async readMessage(source, maxSizeKb) {
|
|
602
614
|
let status;
|
|
603
615
|
const chunks = [];
|
|
616
|
+
const maxAccumulatedBytes = (maxSizeKb ?? DEFAULT_MAX_RESPONSE_SIZE_KB) * 1024 * 2;
|
|
617
|
+
let accumulatedBytes = 0;
|
|
604
618
|
try {
|
|
605
619
|
for await (const chunk of source){
|
|
606
620
|
const statusParsed = status !== undefined;
|
|
607
621
|
if (statusParsed) {
|
|
622
|
+
// Use `byteLength` (the logical length) rather than `chunk.subarray().length`: calling
|
|
623
|
+
// `subarray()` on a `Uint8ArrayList` consolidates its backing buffers into a single copy,
|
|
624
|
+
// which would materialize the very chunk we are trying to reject.
|
|
625
|
+
accumulatedBytes += chunk.byteLength;
|
|
626
|
+
if (accumulatedBytes > maxAccumulatedBytes) {
|
|
627
|
+
throw new ResponseSizeLimitExceededError(accumulatedBytes, maxAccumulatedBytes);
|
|
628
|
+
}
|
|
608
629
|
chunks.push(chunk.subarray());
|
|
609
630
|
continue;
|
|
610
631
|
}
|
|
@@ -711,6 +732,9 @@ _dec = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
|
|
|
711
732
|
const snappy = this.snappyTransform;
|
|
712
733
|
const SUCCESS = Uint8Array.of(ReqRespStatus.SUCCESS);
|
|
713
734
|
await pipeline(stream.source, async function*(source) {
|
|
735
|
+
// Req/resp is one-request-one-response: an honest sender writes a single payload and half-closes.
|
|
736
|
+
// Process only the first chunk and return, so extra frames a peer queues on the same stream cannot
|
|
737
|
+
// drive further handler invocations that bypass the per-stream rate-limit check in streamHandler.
|
|
714
738
|
for await (const chunk of source){
|
|
715
739
|
const response = await handler(connection.remotePeer, chunk.subarray());
|
|
716
740
|
if (protocol === ReqRespSubProtocol.GOODBYE) {
|
|
@@ -722,6 +746,7 @@ _dec = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
|
|
|
722
746
|
stream.metadata.written = true; // Mark the stream as written to;
|
|
723
747
|
yield SUCCESS;
|
|
724
748
|
yield snappy.outboundTransformData(response);
|
|
749
|
+
return;
|
|
725
750
|
}
|
|
726
751
|
}, stream.sink);
|
|
727
752
|
}
|
|
@@ -804,6 +829,12 @@ _dec = trackSpan('ReqResp.sendRequestToPeer', (peerId, subProtocol, _)=>({
|
|
|
804
829
|
this.logger.warn(`Oversized response from peer ${peerId.toString()} in ${subProtocol}: ${e.message}`, logTags);
|
|
805
830
|
return PeerErrorSeverity.LowToleranceError;
|
|
806
831
|
}
|
|
832
|
+
// Response exceeded the reception buffer bound: the peer streamed more compressed data than the
|
|
833
|
+
// per-request size limit allows. Same protocol violation as above, penalize harshly.
|
|
834
|
+
if (e instanceof ResponseSizeLimitExceededError) {
|
|
835
|
+
this.logger.warn(`Oversized response from peer ${peerId.toString()} in ${subProtocol}: ${e.message}`, logTags);
|
|
836
|
+
return PeerErrorSeverity.LowToleranceError;
|
|
837
|
+
}
|
|
807
838
|
return this.categorizeConnectionErrors(e, peerId, subProtocol);
|
|
808
839
|
}
|
|
809
840
|
/*
|