@aztec/p2p 0.0.1-commit.e3c1de76 → 0.0.1-commit.e558bd1c

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.
Files changed (188) hide show
  1. package/dest/client/factory.d.ts +3 -3
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +5 -3
  4. package/dest/client/interface.d.ts +9 -2
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +7 -4
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +22 -7
  9. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +1 -1
  10. package/dest/config.d.ts +9 -3
  11. package/dest/config.d.ts.map +1 -1
  12. package/dest/config.js +3 -1
  13. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +94 -87
  14. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  15. package/dest/mem_pools/attestation_pool/attestation_pool.js +411 -3
  16. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
  17. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  18. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +351 -85
  19. package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
  20. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
  21. package/dest/mem_pools/attestation_pool/index.js +1 -2
  22. package/dest/mem_pools/index.d.ts +2 -2
  23. package/dest/mem_pools/index.d.ts.map +1 -1
  24. package/dest/mem_pools/index.js +1 -1
  25. package/dest/mem_pools/interface.d.ts +3 -3
  26. package/dest/mem_pools/interface.d.ts.map +1 -1
  27. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
  28. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
  29. package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
  30. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +43 -0
  31. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
  32. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +103 -0
  33. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +47 -0
  34. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -0
  35. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +119 -0
  36. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +17 -0
  37. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  38. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +90 -0
  39. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +19 -0
  40. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -0
  41. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +89 -0
  42. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +10 -0
  43. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -0
  44. package/dest/mem_pools/tx_pool_v2/eviction/index.js +11 -0
  45. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +131 -0
  46. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
  47. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +17 -0
  48. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
  49. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  50. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +63 -0
  51. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +17 -0
  52. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  53. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +91 -0
  54. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +16 -0
  55. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  56. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +70 -0
  57. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +20 -0
  58. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -0
  59. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +63 -0
  60. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
  61. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
  62. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
  63. package/dest/mem_pools/tx_pool_v2/index.d.ts +5 -0
  64. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
  65. package/dest/mem_pools/tx_pool_v2/index.js +4 -0
  66. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +197 -0
  67. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
  68. package/dest/mem_pools/tx_pool_v2/interfaces.js +6 -0
  69. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +71 -0
  70. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -0
  71. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +95 -0
  72. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts +26 -0
  73. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts.map +1 -0
  74. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.js +70 -0
  75. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +99 -0
  76. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
  77. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +332 -0
  78. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +55 -0
  79. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -0
  80. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +156 -0
  81. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +69 -0
  82. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -0
  83. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +748 -0
  84. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
  85. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  86. package/dest/services/dummy_service.d.ts +6 -2
  87. package/dest/services/dummy_service.d.ts.map +1 -1
  88. package/dest/services/dummy_service.js +3 -0
  89. package/dest/services/index.d.ts +2 -1
  90. package/dest/services/index.d.ts.map +1 -1
  91. package/dest/services/index.js +1 -0
  92. package/dest/services/libp2p/libp2p_service.d.ts +74 -33
  93. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  94. package/dest/services/libp2p/libp2p_service.js +299 -228
  95. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -4
  96. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  97. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +8 -8
  98. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +6 -4
  99. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  100. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +16 -11
  101. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +15 -10
  102. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  103. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +12 -11
  104. package/dest/services/service.d.ts +18 -1
  105. package/dest/services/service.d.ts.map +1 -1
  106. package/dest/services/tx_collection/config.d.ts +3 -3
  107. package/dest/services/tx_collection/config.js +3 -3
  108. package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -5
  109. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  110. package/dest/services/tx_collection/fast_tx_collection.js +10 -14
  111. package/dest/services/tx_collection/index.d.ts +1 -1
  112. package/dest/services/tx_collection/proposal_tx_collector.d.ts +12 -12
  113. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  114. package/dest/services/tx_collection/proposal_tx_collector.js +4 -5
  115. package/dest/services/tx_file_store/config.d.ts +18 -0
  116. package/dest/services/tx_file_store/config.d.ts.map +1 -0
  117. package/dest/services/tx_file_store/config.js +26 -0
  118. package/dest/services/tx_file_store/index.d.ts +4 -0
  119. package/dest/services/tx_file_store/index.d.ts.map +1 -0
  120. package/dest/services/tx_file_store/index.js +3 -0
  121. package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
  122. package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
  123. package/dest/services/tx_file_store/instrumentation.js +29 -0
  124. package/dest/services/tx_file_store/tx_file_store.d.ts +47 -0
  125. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
  126. package/dest/services/tx_file_store/tx_file_store.js +149 -0
  127. package/dest/test-helpers/testbench-utils.d.ts +10 -16
  128. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  129. package/dest/test-helpers/testbench-utils.js +32 -30
  130. package/dest/testbench/p2p_client_testbench_worker.js +1 -1
  131. package/package.json +14 -14
  132. package/src/client/factory.ts +7 -4
  133. package/src/client/interface.ts +13 -1
  134. package/src/client/p2p_client.ts +30 -8
  135. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +1 -1
  136. package/src/config.ts +8 -1
  137. package/src/mem_pools/attestation_pool/attestation_pool.ts +444 -90
  138. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +436 -100
  139. package/src/mem_pools/attestation_pool/index.ts +9 -2
  140. package/src/mem_pools/index.ts +1 -1
  141. package/src/mem_pools/interface.ts +2 -2
  142. package/src/mem_pools/tx_pool_v2/README.md +209 -0
  143. package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
  144. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +120 -0
  145. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +147 -0
  146. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +118 -0
  147. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +111 -0
  148. package/src/mem_pools/tx_pool_v2/eviction/index.ts +23 -0
  149. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +164 -0
  150. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
  151. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
  152. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +86 -0
  153. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +72 -0
  154. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +31 -0
  155. package/src/mem_pools/tx_pool_v2/index.ts +11 -0
  156. package/src/mem_pools/tx_pool_v2/interfaces.ts +227 -0
  157. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +161 -0
  158. package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
  159. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +417 -0
  160. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +212 -0
  161. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +882 -0
  162. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +2 -2
  163. package/src/services/dummy_service.ts +6 -0
  164. package/src/services/index.ts +1 -0
  165. package/src/services/libp2p/libp2p_service.ts +304 -230
  166. package/src/services/reqresp/batch-tx-requester/README.md +7 -7
  167. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +11 -11
  168. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +22 -13
  169. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +21 -15
  170. package/src/services/service.ts +20 -0
  171. package/src/services/tx_collection/config.ts +6 -6
  172. package/src/services/tx_collection/fast_tx_collection.ts +14 -24
  173. package/src/services/tx_collection/index.ts +1 -1
  174. package/src/services/tx_collection/proposal_tx_collector.ts +12 -14
  175. package/src/services/tx_file_store/config.ts +43 -0
  176. package/src/services/tx_file_store/index.ts +3 -0
  177. package/src/services/tx_file_store/instrumentation.ts +36 -0
  178. package/src/services/tx_file_store/tx_file_store.ts +173 -0
  179. package/src/test-helpers/testbench-utils.ts +18 -39
  180. package/src/testbench/p2p_client_testbench_worker.ts +1 -1
  181. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -40
  182. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
  183. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -218
  184. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -31
  185. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
  186. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -180
  187. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -320
  188. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -264
@@ -370,7 +370,7 @@ function applyDecs2203RFactory() {
370
370
  function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
371
371
  return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
372
372
  }
373
- var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _initProto;
373
+ var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _initProto;
374
374
  import { BlockNumber } from '@aztec/foundation/branded-types';
375
375
  import { randomInt } from '@aztec/foundation/crypto/random';
376
376
  import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
@@ -395,12 +395,9 @@ import { mplex } from '@libp2p/mplex';
395
395
  import { tcp } from '@libp2p/tcp';
396
396
  import { ENR } from '@nethermindeth/enr';
397
397
  import { createLibp2p } from 'libp2p';
398
- import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
399
- import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, FishermanAttestationValidator } from '../../msg_validators/index.js';
398
+ import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, DoubleSpendTxValidator, FishermanAttestationValidator, getDefaultAllowedSetupFunctions } from '../../msg_validators/index.js';
400
399
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
401
- import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
402
400
  import { createTxMessageValidators, createTxReqRespValidator } from '../../msg_validators/tx_validator/factory.js';
403
- import { DoubleSpendTxValidator } from '../../msg_validators/tx_validator/index.js';
404
401
  import { GossipSubEvent } from '../../types/index.js';
405
402
  import { convertToMultiaddr } from '../../util.js';
406
403
  import { getVersions } from '../../versioning.js';
@@ -410,36 +407,37 @@ import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encod
410
407
  import { gossipScoreThresholds } from '../gossipsub/scoring.js';
411
408
  import { PeerManager } from '../peer-manager/peer_manager.js';
412
409
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
413
- import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/interface.js';
414
- import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
415
- import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
416
- import { pingHandler, reqRespBlockHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/protocols/index.js';
410
+ import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/index.js';
411
+ import { pingHandler, reqGoodbyeHandler, reqRespBlockHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
417
412
  import { ReqResp } from '../reqresp/reqresp.js';
418
413
  import { P2PInstrumentation } from './instrumentation.js';
419
- _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
414
+ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation)=>({
415
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString()
416
+ })), _dec1 = trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block)=>({
417
+ [Attributes.BLOCK_NUMBER]: block.blockNumber.toString(),
418
+ [Attributes.SLOT_NUMBER]: block.slotNumber.toString()
419
+ })), _dec2 = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
420
420
  [Attributes.SLOT_NUMBER]: block.slotNumber,
421
421
  [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
422
422
  [Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then((i)=>i.toString())
423
- })), _dec1 = trackSpan('Libp2pService.processValidCheckpointProposal', async (checkpoint)=>({
423
+ })), _dec3 = trackSpan('Libp2pService.validateAndStoreCheckpointProposal', (_peerId, checkpoint)=>({
424
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString()
425
+ })), _dec4 = trackSpan('Libp2pService.processValidCheckpointProposal', async (checkpoint)=>({
424
426
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
425
427
  [Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
426
428
  [Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then((i)=>i.toString())
427
- })), _dec2 = trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
429
+ })), _dec5 = trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
428
430
  [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString()
429
- })), _dec3 = trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
431
+ })), _dec6 = trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
430
432
  [Attributes.TX_HASH]: requestedTxHash.toString()
431
- })), _dec4 = trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock)=>({
433
+ })), _dec7 = trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock)=>({
432
434
  [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString()
433
- })), _dec5 = trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
435
+ })), _dec8 = trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
434
436
  [Attributes.TX_HASH]: tx.getTxHash().toString()
435
- })), _dec6 = trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation)=>({
437
+ })), _dec9 = trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation)=>({
436
438
  [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
437
439
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
438
440
  [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then((i)=>i.toString())
439
- })), _dec7 = trackSpan('Libp2pService.validateBlockProposal', (_peerId, block)=>({
440
- [Attributes.SLOT_NUMBER]: block.slotNumber.toString()
441
- })), _dec8 = trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint)=>({
442
- [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString()
443
441
  }));
444
442
  /**
445
443
  * Lib P2P implementation of the P2PService interface.
@@ -460,47 +458,52 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
460
458
  [
461
459
  _dec,
462
460
  2,
463
- "processValidBlockProposal"
461
+ "validateAndStoreCheckpointAttestation"
464
462
  ],
465
463
  [
466
464
  _dec1,
467
465
  2,
468
- "processValidCheckpointProposal"
466
+ "validateAndStoreBlockProposal"
469
467
  ],
470
468
  [
471
469
  _dec2,
472
470
  2,
473
- "validateRequestedBlockTxs"
471
+ "processValidBlockProposal"
474
472
  ],
475
473
  [
476
474
  _dec3,
477
475
  2,
478
- "validateRequestedTxs"
476
+ "validateAndStoreCheckpointProposal"
479
477
  ],
480
478
  [
481
479
  _dec4,
482
480
  2,
483
- "validateRequestedBlock"
481
+ "processValidCheckpointProposal"
484
482
  ],
485
483
  [
486
484
  _dec5,
487
485
  2,
488
- "validatePropagatedTx"
486
+ "validateRequestedBlockTxs"
489
487
  ],
490
488
  [
491
489
  _dec6,
492
490
  2,
493
- "validateCheckpointAttestation"
491
+ "validateRequestedTxs"
494
492
  ],
495
493
  [
496
494
  _dec7,
497
495
  2,
498
- "validateBlockProposal"
496
+ "validateRequestedBlock"
499
497
  ],
500
498
  [
501
499
  _dec8,
502
500
  2,
503
- "validateCheckpointProposal"
501
+ "validatePropagatedTx"
502
+ ],
503
+ [
504
+ _dec9,
505
+ 2,
506
+ "validateCheckpointAttestation"
504
507
  ]
505
508
  ], []));
506
509
  }
@@ -513,6 +516,7 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
513
516
  protocolVersion;
514
517
  topicStrings;
515
518
  feesCache;
519
+ /** Callback invoked when a duplicate proposal is detected (triggers slashing). */ duplicateProposalCallback;
516
520
  /**
517
521
  * Callback for when a block is received from a peer.
518
522
  * @param block - The block received from the peer.
@@ -776,7 +780,7 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
776
780
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
777
781
  };
778
782
  if (!this.config.disableTransactions) {
779
- const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
783
+ const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.archiver, this.mempools.txPool);
780
784
  requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
781
785
  }
782
786
  if (!this.config.disableTransactions) {
@@ -876,6 +880,12 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
876
880
  this.checkpointReceivedCallback = callback;
877
881
  }
878
882
  /**
883
+ * Registers a callback to be invoked when a duplicate proposal is detected.
884
+ * This callback is triggered on the first duplicate (when count goes from 1 to 2).
885
+ */ registerDuplicateProposalCallback(callback) {
886
+ this.duplicateProposalCallback = callback;
887
+ }
888
+ /**
879
889
  * Subscribes to a topic.
880
890
  * @param topic - The topic to subscribe to.
881
891
  */ subscribeToTopic(topic) {
@@ -1102,114 +1112,159 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
1102
1112
  * Process a checkpoint attestation from a peer.
1103
1113
  * Validates the attestation and adds it to the pool.
1104
1114
  */ async processCheckpointAttestationFromPeer(payloadData, msgId, source) {
1105
- const validationFunc = async ()=>{
1106
- const attestation = CheckpointAttestation.fromBuffer(payloadData);
1107
- const pool = this.mempools.attestationPool;
1108
- const validationResult = await this.validateCheckpointAttestation(source, attestation);
1109
- const isValid = validationResult.result === 'accept';
1110
- const exists = isValid && await pool.hasCheckpointAttestation(attestation);
1111
- let canAdd = true;
1112
- if (isValid && !exists) {
1113
- const slot = attestation.payload.header.slotNumber;
1114
- const { committee } = await this.epochCache.getCommittee(slot);
1115
- const committeeSize = committee?.length ?? 0;
1116
- canAdd = await pool.canAddCheckpointAttestation(attestation, committeeSize);
1117
- }
1118
- this.logger.trace(`Validate propagated checkpoint attestation`, {
1119
- isValid,
1120
- exists,
1121
- canAdd,
1122
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
1123
- [Attributes.P2P_ID]: source.toString()
1124
- });
1125
- if (validationResult.result === 'reject') {
1126
- return {
1127
- result: TopicValidatorResult.Reject
1128
- };
1129
- } else if (validationResult.result === 'ignore' || exists) {
1130
- return {
1131
- result: TopicValidatorResult.Ignore,
1132
- obj: attestation
1133
- };
1134
- } else if (!canAdd) {
1135
- this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
1136
- slot: attestation.payload.header.slotNumber.toString(),
1137
- archive: attestation.archive.toString(),
1138
- source: source.toString()
1139
- });
1140
- return {
1141
- result: TopicValidatorResult.Ignore,
1142
- obj: attestation
1143
- };
1144
- } else {
1145
- return {
1146
- result: TopicValidatorResult.Accept,
1147
- obj: attestation
1148
- };
1149
- }
1150
- };
1151
- const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.checkpoint_attestation);
1115
+ const { result, obj: attestation } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_attestation);
1152
1116
  if (result !== TopicValidatorResult.Accept || !attestation) {
1153
1117
  return;
1154
1118
  }
1155
- this.logger.debug(`Received checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`, {
1119
+ this.logger.verbose(`Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`, {
1156
1120
  p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
1157
1121
  slot: attestation.slotNumber,
1158
1122
  archive: attestation.archive.toString(),
1159
1123
  source: source.toString()
1160
1124
  });
1161
- await this.mempools.attestationPool.addCheckpointAttestations([
1162
- attestation
1163
- ]);
1164
1125
  }
1165
- async processBlockFromPeer(payloadData, msgId, source) {
1166
- const validationFunc = async ()=>{
1167
- const block = BlockProposal.fromBuffer(payloadData);
1168
- const validationResult = await this.validateBlockProposal(source, block);
1169
- const isValid = validationResult.result === 'accept';
1170
- const pool = this.mempools.attestationPool;
1171
- const exists = isValid && await pool.hasBlockProposal(block);
1172
- const canAdd = isValid && await pool.canAddProposal(block);
1173
- this.logger.trace(`Validate propagated block proposal`, {
1174
- isValid,
1175
- exists,
1176
- canAdd,
1177
- [Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
1178
- [Attributes.P2P_ID]: source.toString()
1126
+ /** Validates a checkpoint attestation and adds it to the pool. Penalizes the peer if validation fails. */ async validateAndStoreCheckpointAttestation(peerId, attestation) {
1127
+ const validationResult = await this.checkpointAttestationValidator.validate(attestation);
1128
+ if (validationResult.result === 'reject') {
1129
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1130
+ this.peerManager.penalizePeer(peerId, validationResult.severity);
1131
+ return {
1132
+ result: TopicValidatorResult.Reject
1133
+ };
1134
+ }
1135
+ if (validationResult.result === 'ignore') {
1136
+ return {
1137
+ result: TopicValidatorResult.Ignore,
1138
+ obj: attestation
1139
+ };
1140
+ }
1141
+ // Get committee size for the attestation's slot
1142
+ const slot = attestation.payload.header.slotNumber;
1143
+ const { committee } = await this.epochCache.getCommittee(slot);
1144
+ const committeeSize = committee?.length ?? 0;
1145
+ // Try to add the attestation: this handles existence check, cap check, and adding in one call
1146
+ const { added, alreadyExists } = await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation, committeeSize);
1147
+ this.logger.trace(`Validate propagated checkpoint attestation`, {
1148
+ added,
1149
+ alreadyExists,
1150
+ [Attributes.SLOT_NUMBER]: slot.toString(),
1151
+ [Attributes.P2P_ID]: peerId.toString()
1152
+ });
1153
+ // Duplicate attestation received, no need to re-broadcast
1154
+ if (alreadyExists) {
1155
+ return {
1156
+ result: TopicValidatorResult.Ignore,
1157
+ obj: attestation
1158
+ };
1159
+ }
1160
+ // Could not add (cap reached), no need to re-broadcast
1161
+ if (!added) {
1162
+ this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
1163
+ slot: slot.toString(),
1164
+ archive: attestation.archive.toString(),
1165
+ source: peerId.toString()
1179
1166
  });
1180
- if (validationResult.result === 'reject') {
1181
- return {
1182
- result: TopicValidatorResult.Reject
1183
- };
1184
- } else if (validationResult.result === 'ignore' || exists) {
1185
- return {
1186
- result: TopicValidatorResult.Ignore,
1187
- obj: block
1188
- };
1189
- } else if (!canAdd) {
1190
- this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
1191
- this.logger.warn(`Penalizing peer for block proposal exceeding per-slot cap`, {
1192
- slot: block.slotNumber.toString(),
1193
- archive: block.archive.toString(),
1194
- source: source.toString()
1195
- });
1196
- return {
1197
- result: TopicValidatorResult.Reject
1198
- };
1199
- } else {
1200
- return {
1201
- result: TopicValidatorResult.Accept,
1202
- obj: block
1203
- };
1204
- }
1167
+ return {
1168
+ result: TopicValidatorResult.Ignore,
1169
+ obj: attestation
1170
+ };
1171
+ }
1172
+ // Attestation was added successfully
1173
+ return {
1174
+ result: TopicValidatorResult.Accept,
1175
+ obj: attestation
1205
1176
  };
1206
- const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_proposal);
1207
- if (!result || !block) {
1177
+ }
1178
+ async processBlockFromPeer(payloadData, msgId, source) {
1179
+ const { result, obj: block, metadata: { isEquivocated } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)), msgId, source, TopicType.block_proposal);
1180
+ // If not accepted or equivocated, return
1181
+ if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
1208
1182
  return;
1209
1183
  }
1210
1184
  await this.processValidBlockProposal(block, source);
1211
1185
  }
1212
- // REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
1186
+ /** Validates a block proposal. Triggers a penalization to the peer that sent it if invalid. Adds to the mempool if valid. */ async validateAndStoreBlockProposal(peerId, block) {
1187
+ const validationResult = await this.blockProposalValidator.validate(block);
1188
+ if (validationResult.result === 'reject') {
1189
+ this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
1190
+ this.peerManager.penalizePeer(peerId, validationResult.severity);
1191
+ return {
1192
+ result: TopicValidatorResult.Reject
1193
+ };
1194
+ }
1195
+ if (validationResult.result === 'ignore') {
1196
+ return {
1197
+ result: TopicValidatorResult.Ignore,
1198
+ obj: block
1199
+ };
1200
+ }
1201
+ // Try to add the proposal: this handles existence check, cap check, and adding in one call
1202
+ const { added, alreadyExists, totalForPosition } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1203
+ const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
1204
+ // Duplicate proposal received, no need to re-broadcast
1205
+ if (alreadyExists) {
1206
+ this.logger.debug(`Ignoring duplicate block proposal received`, {
1207
+ ...block.toBlockInfo(),
1208
+ indexWithinCheckpoint: block.indexWithinCheckpoint,
1209
+ proposer: block.getSender()?.toString(),
1210
+ source: peerId.toString()
1211
+ });
1212
+ return {
1213
+ result: TopicValidatorResult.Ignore,
1214
+ obj: block,
1215
+ metadata: {
1216
+ isEquivocated
1217
+ }
1218
+ };
1219
+ }
1220
+ // Too many blocks received for this slot and index, penalize peer and do not re-broadcast
1221
+ if (!added) {
1222
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1223
+ this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1224
+ ...block.toBlockInfo(),
1225
+ indexWithinCheckpoint: block.indexWithinCheckpoint,
1226
+ totalForPosition,
1227
+ proposer: block.getSender()?.toString(),
1228
+ source: peerId.toString()
1229
+ });
1230
+ return {
1231
+ result: TopicValidatorResult.Reject,
1232
+ metadata: {
1233
+ isEquivocated
1234
+ }
1235
+ };
1236
+ }
1237
+ // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
1238
+ // and do re-broadcast it so other nodes in the network know to slash the proposer
1239
+ if (isEquivocated) {
1240
+ const proposer = block.getSender();
1241
+ this.logger.warn(`Detected duplicate block proposal (equivocation) at slot ${block.slotNumber}`, {
1242
+ ...block.toBlockInfo(),
1243
+ source: peerId.toString(),
1244
+ proposer: proposer?.toString()
1245
+ });
1246
+ // Invoke the duplicate callback on the first duplicate spotted only
1247
+ if (proposer && totalForPosition === 2) {
1248
+ this.duplicateProposalCallback?.({
1249
+ slot: block.slotNumber,
1250
+ proposer,
1251
+ type: 'block'
1252
+ });
1253
+ }
1254
+ return {
1255
+ result: TopicValidatorResult.Accept,
1256
+ obj: block,
1257
+ metadata: {
1258
+ isEquivocated
1259
+ }
1260
+ };
1261
+ }
1262
+ // Otherwise, we're good to go!
1263
+ return {
1264
+ result: TopicValidatorResult.Accept,
1265
+ obj: block
1266
+ };
1267
+ }
1213
1268
  // REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
1214
1269
  // should not be here as it does not deal with p2p networking.
1215
1270
  async processValidBlockProposal(block, sender) {
@@ -1219,21 +1274,6 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
1219
1274
  source: sender.toString(),
1220
1275
  ...block.toBlockInfo()
1221
1276
  });
1222
- // Attempt to add proposal
1223
- try {
1224
- await this.mempools.attestationPool.addBlockProposal(block);
1225
- } catch (err) {
1226
- // Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
1227
- if (err instanceof ProposalSlotCapExceededError) {
1228
- this.logger.warn(`Dropping block proposal due to per-slot proposal cap`, {
1229
- slot: String(slot),
1230
- archive: block.archive.toString(),
1231
- error: err.message
1232
- });
1233
- return;
1234
- }
1235
- throw err;
1236
- }
1237
1277
  // Mark the txs in this proposal as non-evictable
1238
1278
  await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
1239
1279
  // Call the block received callback to validate the proposal.
@@ -1247,57 +1287,135 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
1247
1287
  * Handle a gossiped checkpoint proposal.
1248
1288
  * Validates and processes the checkpoint proposal, then triggers the callback for attestation.
1249
1289
  */ async handleGossipedCheckpointProposal(payloadData, msgId, source) {
1250
- // TODO(palla/mbps): This pattern is repeated across multiple message handlers, consider abstracting it.
1251
- const validationFunc = async ()=>{
1252
- const checkpoint = CheckpointProposal.fromBuffer(payloadData);
1253
- const validationResult = await this.validateCheckpointProposal(source, checkpoint);
1254
- const isValid = validationResult.result === 'accept';
1255
- const pool = this.mempools.attestationPool;
1256
- const exists = isValid && await pool.hasCheckpointProposal(checkpoint);
1257
- const canAdd = isValid && await pool.canAddCheckpointProposal(checkpoint);
1258
- this.logger.trace(`Validate propagated checkpoint proposal`, {
1259
- isValid,
1260
- exists,
1261
- canAdd,
1290
+ const { result, obj: checkpoint, metadata: { isEquivocated, processBlock } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_proposal);
1291
+ // If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
1292
+ // TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
1293
+ if (processBlock && checkpoint?.getBlockProposal()) {
1294
+ await this.processValidBlockProposal(checkpoint.getBlockProposal(), source);
1295
+ }
1296
+ if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
1297
+ return;
1298
+ }
1299
+ await this.processValidCheckpointProposal(checkpoint.toCore(), source);
1300
+ }
1301
+ /**
1302
+ * Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
1303
+ * its last block (if present) to the mempool if valid. Triggers equivocation detection on both.
1304
+ */ async validateAndStoreCheckpointProposal(peerId, checkpoint) {
1305
+ const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
1306
+ if (validationResult.result === 'reject') {
1307
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1308
+ this.peerManager.penalizePeer(peerId, validationResult.severity);
1309
+ return {
1310
+ result: TopicValidatorResult.Reject
1311
+ };
1312
+ }
1313
+ if (validationResult.result === 'ignore') {
1314
+ return {
1315
+ result: TopicValidatorResult.Ignore,
1316
+ obj: checkpoint
1317
+ };
1318
+ }
1319
+ // Extract and try to add the block proposal first if present
1320
+ const blockProposal = checkpoint.getBlockProposal();
1321
+ let processBlock = false;
1322
+ if (blockProposal) {
1323
+ this.logger.debug(`Validating block proposal from propagated checkpoint`, {
1262
1324
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1263
- [Attributes.P2P_ID]: source.toString()
1325
+ [Attributes.P2P_ID]: peerId.toString()
1264
1326
  });
1265
- if (validationResult.result === 'reject') {
1266
- return {
1267
- result: TopicValidatorResult.Reject
1268
- };
1269
- } else if (validationResult.result === 'ignore' || exists) {
1270
- return {
1271
- result: TopicValidatorResult.Ignore,
1272
- obj: checkpoint
1273
- };
1274
- } else if (!canAdd) {
1275
- this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
1276
- this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1277
- slot: checkpoint.slotNumber.toString(),
1278
- archive: checkpoint.archive.toString(),
1279
- source: source.toString()
1327
+ const { result, obj, metadata: { isEquivocated } = {} } = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1328
+ if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1329
+ this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
1330
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1331
+ [Attributes.P2P_ID]: peerId.toString(),
1332
+ isEquivocated,
1333
+ result
1280
1334
  });
1281
1335
  return {
1282
1336
  result: TopicValidatorResult.Reject
1283
1337
  };
1284
- } else {
1285
- return {
1286
- result: TopicValidatorResult.Accept,
1287
- obj: checkpoint
1288
- };
1338
+ } else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1339
+ processBlock = true;
1289
1340
  }
1290
- };
1291
- const { result, obj: checkpoint } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.checkpoint_proposal);
1292
- if (result !== TopicValidatorResult.Accept || !checkpoint) {
1293
- return;
1294
1341
  }
1295
- await this.processValidCheckpointProposal(checkpoint, source);
1342
+ // Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
1343
+ const checkpointCore = checkpoint.toCore();
1344
+ const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
1345
+ const { added, alreadyExists, totalForPosition } = tryAddResult;
1346
+ const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
1347
+ // Duplicate proposal received, do not re-broadcast
1348
+ if (alreadyExists) {
1349
+ this.logger.debug(`Ignoring duplicate checkpoint proposal received`, {
1350
+ ...checkpoint.toCheckpointInfo(),
1351
+ source: peerId.toString()
1352
+ });
1353
+ return {
1354
+ result: TopicValidatorResult.Ignore,
1355
+ obj: checkpoint,
1356
+ metadata: {
1357
+ isEquivocated,
1358
+ processBlock
1359
+ }
1360
+ };
1361
+ }
1362
+ // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
1363
+ // Note: We still return the checkpoint obj so the lastBlock can be processed if valid
1364
+ if (!added) {
1365
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1366
+ this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1367
+ ...checkpoint.toCheckpointInfo(),
1368
+ totalForPosition,
1369
+ source: peerId.toString()
1370
+ });
1371
+ return {
1372
+ result: TopicValidatorResult.Reject,
1373
+ obj: checkpoint,
1374
+ metadata: {
1375
+ isEquivocated,
1376
+ processBlock
1377
+ }
1378
+ };
1379
+ }
1380
+ // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
1381
+ // and do re-broadcast it so other nodes in the network know to slash the proposer
1382
+ if (isEquivocated) {
1383
+ const proposer = checkpoint.getSender();
1384
+ this.logger.warn(`Detected duplicate checkpoint proposal (equivocation) at slot ${checkpoint.slotNumber}`, {
1385
+ ...checkpoint.toCheckpointInfo(),
1386
+ source: peerId.toString(),
1387
+ proposer: proposer?.toString()
1388
+ });
1389
+ // Invoke the duplicate callback on the first duplicate spotted only
1390
+ if (proposer && totalForPosition === 2) {
1391
+ this.duplicateProposalCallback?.({
1392
+ slot: checkpoint.slotNumber,
1393
+ proposer,
1394
+ type: 'checkpoint'
1395
+ });
1396
+ }
1397
+ return {
1398
+ result: TopicValidatorResult.Accept,
1399
+ obj: checkpoint,
1400
+ metadata: {
1401
+ isEquivocated,
1402
+ processBlock
1403
+ }
1404
+ };
1405
+ }
1406
+ // Otherwise, we're good to go!
1407
+ return {
1408
+ result: TopicValidatorResult.Accept,
1409
+ obj: checkpoint,
1410
+ metadata: {
1411
+ processBlock,
1412
+ isEquivocated
1413
+ }
1414
+ };
1296
1415
  }
1297
1416
  /**
1298
1417
  * Process a validated checkpoint proposal.
1299
- * Extracts and processes the last block proposal (if present) first, then processes the checkpoint.
1300
- * The block callback is invoked before the checkpoint callback.
1418
+ * Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
1301
1419
  */ async processValidCheckpointProposal(checkpoint, sender) {
1302
1420
  const slot = checkpoint.slotNumber;
1303
1421
  this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
@@ -1306,33 +1424,12 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
1306
1424
  archive: checkpoint.archive.toString(),
1307
1425
  source: sender.toString()
1308
1426
  });
1309
- // Extract block proposal before adding to pool (pool stores them separately)
1310
- const blockProposal = checkpoint.getBlockProposal();
1311
- // Add proposal to the pool (this extracts and stores block proposal separately)
1312
- await this.mempools.attestationPool.addCheckpointProposal(checkpoint);
1313
- // Mark txs as non-evictable if present (from the last block)
1314
- if (checkpoint.txHashes.length > 0) {
1315
- await this.mempools.txPool.markTxsAsNonEvictable(checkpoint.txHashes);
1316
- }
1317
- // If there was a last block proposal, invoke the block callback first for validation.
1318
- // Note: The block proposal is already stored in the pool by addCheckpointProposal.
1319
- if (blockProposal) {
1320
- const isValid = await this.blockReceivedCallback(blockProposal, sender);
1321
- if (!isValid) {
1322
- this.logger.warn(`Block proposal from checkpoint failed validation`, {
1323
- slot: slot.toString(),
1324
- archive: checkpoint.archive.toString(),
1325
- blockNumber: blockProposal.blockNumber.toString()
1326
- });
1327
- return;
1328
- }
1329
- }
1330
1427
  // Call the checkpoint received callback with the core version (without lastBlock)
1331
1428
  // to validate and potentially generate attestations
1332
- const attestations = await this.checkpointReceivedCallback(checkpoint.toCore(), sender);
1429
+ const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
1333
1430
  if (attestations && attestations.length > 0) {
1334
1431
  // If the callback returned attestations, add them to the pool and propagate them
1335
- await this.mempools.attestationPool.addCheckpointAttestations(attestations);
1432
+ await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
1336
1433
  for (const attestation of attestations){
1337
1434
  await this.propagate(attestation);
1338
1435
  }
@@ -1659,33 +1756,7 @@ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
1659
1756
  */ async validateCheckpointAttestation(peerId, attestation) {
1660
1757
  const result = await this.checkpointAttestationValidator.validate(attestation);
1661
1758
  if (result.result === 'reject') {
1662
- this.logger.debug(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1663
- this.peerManager.penalizePeer(peerId, result.severity);
1664
- }
1665
- return result;
1666
- }
1667
- /**
1668
- * Validate a block proposal.
1669
- *
1670
- * @param block - The block proposal to validate.
1671
- * @returns True if the block proposal is valid, false otherwise.
1672
- */ async validateBlockProposal(peerId, block) {
1673
- const result = await this.blockProposalValidator.validate(block);
1674
- if (result.result === 'reject') {
1675
- this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
1676
- this.peerManager.penalizePeer(peerId, result.severity);
1677
- }
1678
- return result;
1679
- }
1680
- /**
1681
- * Validate a checkpoint proposal.
1682
- *
1683
- * @param checkpoint - The checkpoint proposal to validate.
1684
- * @returns True if the checkpoint proposal is valid, false otherwise.
1685
- */ async validateCheckpointProposal(peerId, checkpoint) {
1686
- const result = await this.checkpointProposalValidator.validate(checkpoint);
1687
- if (result.result === 'reject') {
1688
- this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1759
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1689
1760
  this.peerManager.penalizePeer(peerId, result.severity);
1690
1761
  }
1691
1762
  return result;