@aztec/p2p 0.0.1-commit.934299a21 → 0.0.1-commit.949a33fd8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -3
- package/dest/client/factory.d.ts +6 -6
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +29 -14
- package/dest/client/interface.d.ts +12 -5
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +6 -5
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +47 -39
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +21 -8
- package/dest/config.d.ts +128 -100
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +97 -34
- package/dest/errors/p2p-service.error.d.ts +9 -0
- package/dest/errors/p2p-service.error.d.ts.map +1 -0
- package/dest/errors/p2p-service.error.js +10 -0
- package/dest/index.d.ts +1 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +0 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +7 -5
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +16 -9
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +6 -4
- package/dest/mem_pools/index.d.ts +1 -2
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.d.ts +4 -2
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +33 -15
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +2 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +2 -0
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +7 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +8 -6
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +12 -5
- 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_metadata.d.ts +44 -12
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +81 -22
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +26 -44
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +4 -2
- 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 +6 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +2 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +62 -29
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +9 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +37 -12
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +2 -2
- package/dest/msg_validators/clock_tolerance.d.ts +12 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +61 -3
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +8 -4
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +8 -4
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +17 -8
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +83 -48
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
- package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +35 -2
- package/dest/msg_validators/tx_validator/factory.d.ts +23 -4
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +37 -11
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +48 -7
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +88 -41
- package/dest/msg_validators/tx_validator/index.d.ts +2 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +1 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/data_store.js +5 -5
- package/dest/services/dummy_service.d.ts +6 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +6 -1
- package/dest/services/encoding.d.ts +6 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +14 -8
- package/dest/services/gossipsub/topic_score_params.d.ts +13 -2
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +21 -4
- package/dest/services/libp2p/instrumentation.d.ts +3 -1
- package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
- package/dest/services/libp2p/instrumentation.js +14 -0
- package/dest/services/libp2p/libp2p_service.d.ts +23 -32
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +202 -151
- package/dest/services/peer-manager/metrics.d.ts +3 -1
- package/dest/services/peer-manager/metrics.d.ts.map +1 -1
- package/dest/services/peer-manager/metrics.js +6 -0
- package/dest/services/peer-manager/peer_manager.d.ts +6 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +39 -11
- package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_scoring.js +32 -10
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -8
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +69 -65
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +3 -2
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
- package/dest/services/reqresp/config.d.ts +3 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/interface.d.ts +14 -9
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +10 -11
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.js +0 -1
- package/dest/services/reqresp/protocols/index.d.ts +1 -2
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +0 -1
- package/dest/services/reqresp/protocols/tx.d.ts +1 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +1 -3
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
- package/dest/services/reqresp/reqresp.d.ts +4 -2
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +30 -12
- package/dest/services/service.d.ts +5 -2
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -4
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +57 -73
- package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +39 -29
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +6 -7
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
- package/dest/services/tx_collection/request_tracker.d.ts +53 -0
- package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/request_tracker.js +84 -0
- package/dest/services/tx_collection/slow_tx_collection.js +1 -1
- package/dest/services/tx_collection/tx_collection.d.ts +3 -6
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.d.ts +6 -5
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +9 -7
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +4 -2
- package/dest/test-helpers/mock-pubsub.d.ts +12 -5
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +37 -12
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +6 -4
- package/dest/test-helpers/testbench-utils.d.ts +1 -1
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +23 -3
- package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +78 -21
- package/dest/testbench/worker_client_manager.d.ts +10 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +55 -3
- package/dest/util.d.ts +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +48 -19
- package/src/client/interface.ts +12 -10
- package/src/client/p2p_client.ts +52 -51
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +22 -11
- package/src/config.ts +146 -36
- package/src/errors/p2p-service.error.ts +11 -0
- package/src/index.ts +0 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +17 -12
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
- package/src/mem_pools/attestation_pool/mocks.ts +13 -8
- package/src/mem_pools/index.ts +0 -3
- package/src/mem_pools/instrumentation.ts +22 -14
- package/src/mem_pools/tx_pool_v2/README.md +9 -1
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +2 -1
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -0
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
- package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +11 -1
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +15 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +2 -1
- package/src/mem_pools/tx_pool_v2/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/interfaces.ts +12 -4
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +121 -27
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +29 -43
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +16 -1
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +70 -26
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +41 -9
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +12 -2
- package/src/msg_validators/clock_tolerance.ts +79 -3
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +22 -4
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +33 -7
- package/src/msg_validators/proposal_validator/proposal_validator.ts +99 -49
- package/src/msg_validators/tx_validator/README.md +15 -3
- package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
- package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
- package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +42 -1
- package/src/msg_validators/tx_validator/factory.ts +46 -4
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +121 -39
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
- package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
- package/src/services/data_store.ts +5 -13
- package/src/services/dummy_service.ts +8 -2
- package/src/services/encoding.ts +14 -7
- package/src/services/gossipsub/topic_score_params.ts +36 -4
- package/src/services/libp2p/instrumentation.ts +14 -0
- package/src/services/libp2p/libp2p_service.ts +206 -164
- package/src/services/peer-manager/metrics.ts +7 -0
- package/src/services/peer-manager/peer_manager.ts +45 -11
- package/src/services/peer-manager/peer_scoring.ts +27 -5
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/README.md +46 -7
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +64 -69
- package/src/services/reqresp/batch-tx-requester/interface.ts +2 -1
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
- package/src/services/reqresp/config.ts +2 -2
- package/src/services/reqresp/interface.ts +21 -11
- package/src/services/reqresp/metrics.ts +0 -1
- package/src/services/reqresp/protocols/index.ts +0 -1
- package/src/services/reqresp/protocols/tx.ts +1 -3
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
- package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
- package/src/services/reqresp/reqresp.ts +40 -13
- package/src/services/service.ts +6 -1
- package/src/services/tx_collection/fast_tx_collection.ts +57 -83
- package/src/services/tx_collection/file_store_tx_source.ts +43 -31
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -13
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/slow_tx_collection.ts +1 -1
- package/src/services/tx_collection/tx_collection.ts +3 -5
- package/src/services/tx_collection/tx_source.ts +8 -7
- package/src/test-helpers/make-test-p2p-clients.ts +3 -3
- package/src/test-helpers/mock-pubsub.ts +37 -11
- package/src/test-helpers/reqresp-nodes.ts +7 -8
- package/src/test-helpers/testbench-utils.ts +30 -3
- package/src/testbench/p2p_client_testbench_worker.ts +77 -21
- package/src/testbench/worker_client_manager.ts +68 -6
- package/src/util.ts +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
- package/dest/mem_pools/tx_pool/index.d.ts +0 -3
- package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/index.js +0 -2
- package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
- package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/priority.js +0 -15
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
- package/dest/services/reqresp/protocols/block.d.ts +0 -9
- package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
- package/dest/services/reqresp/protocols/block.js +0 -32
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
- package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
- package/src/mem_pools/tx_pool/README.md +0 -270
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
- package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
- package/src/mem_pools/tx_pool/index.ts +0 -2
- package/src/mem_pools/tx_pool/priority.ts +0 -20
- package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
- package/src/services/reqresp/protocols/block.ts +0 -37
- package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
|
@@ -11,7 +11,14 @@ import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-clien
|
|
|
11
11
|
import EventEmitter from 'node:events';
|
|
12
12
|
|
|
13
13
|
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
AddTxsResult,
|
|
16
|
+
PoolReadAccess,
|
|
17
|
+
TxPoolV2,
|
|
18
|
+
TxPoolV2Config,
|
|
19
|
+
TxPoolV2Dependencies,
|
|
20
|
+
TxPoolV2Events,
|
|
21
|
+
} from './interfaces.js';
|
|
15
22
|
import type { TxState } from './tx_metadata.js';
|
|
16
23
|
import { TxPoolV2Impl } from './tx_pool_v2_impl.js';
|
|
17
24
|
|
|
@@ -58,6 +65,9 @@ export class AztecKVTxPoolV2 extends (EventEmitter as new () => TypedEventEmitte
|
|
|
58
65
|
const hashes = txHashes.map(h => (typeof h === 'string' ? TxHash.fromString(h) : TxHash.fromBigInt(h)));
|
|
59
66
|
this.emit('txs-removed', { txHashes: hashes });
|
|
60
67
|
},
|
|
68
|
+
onTxsMined: (txHashes: string[]) => {
|
|
69
|
+
this.#metrics?.transactionsRemoved(txHashes);
|
|
70
|
+
},
|
|
61
71
|
};
|
|
62
72
|
|
|
63
73
|
// Create the implementation
|
|
@@ -162,6 +172,11 @@ export class AztecKVTxPoolV2 extends (EventEmitter as new () => TypedEventEmitte
|
|
|
162
172
|
return this.#queue.put(() => Promise.resolve(this.#impl.getLowestPriorityPending(limit)));
|
|
163
173
|
}
|
|
164
174
|
|
|
175
|
+
/** Returns read-only access to the pool. Used for testing. */
|
|
176
|
+
getPoolReadAccess(): PoolReadAccess {
|
|
177
|
+
return this.#impl.getPoolReadAccess();
|
|
178
|
+
}
|
|
179
|
+
|
|
165
180
|
// === Configuration ===
|
|
166
181
|
|
|
167
182
|
updateConfig(config: Partial<TxPoolV2Config>): Promise<void> {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
EvictionManager,
|
|
18
18
|
FeePayerBalanceEvictionRule,
|
|
19
19
|
FeePayerBalancePreAddRule,
|
|
20
|
+
InsufficientFeePerGasEvictionRule,
|
|
20
21
|
InvalidTxsAfterMiningRule,
|
|
21
22
|
InvalidTxsAfterReorgRule,
|
|
22
23
|
LowPriorityEvictionRule,
|
|
@@ -45,6 +46,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
|
|
|
45
46
|
export interface TxPoolV2Callbacks {
|
|
46
47
|
onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
|
|
47
48
|
onTxsRemoved: (txHashes: string[] | bigint[]) => void;
|
|
49
|
+
onTxsMined: (txHashes: string[]) => void;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
/**
|
|
@@ -61,6 +63,7 @@ export class TxPoolV2Impl {
|
|
|
61
63
|
#l2BlockSource: L2BlockSource;
|
|
62
64
|
#worldStateSynchronizer: WorldStateSynchronizer;
|
|
63
65
|
#createTxValidator: TxPoolV2Dependencies['createTxValidator'];
|
|
66
|
+
#checkAllowedSetupCalls: TxPoolV2Dependencies['checkAllowedSetupCalls'];
|
|
64
67
|
|
|
65
68
|
// === In-Memory Indices ===
|
|
66
69
|
#indices: TxPoolIndices = new TxPoolIndices();
|
|
@@ -92,6 +95,7 @@ export class TxPoolV2Impl {
|
|
|
92
95
|
this.#l2BlockSource = deps.l2BlockSource;
|
|
93
96
|
this.#worldStateSynchronizer = deps.worldStateSynchronizer;
|
|
94
97
|
this.#createTxValidator = deps.createTxValidator;
|
|
98
|
+
this.#checkAllowedSetupCalls = deps.checkAllowedSetupCalls;
|
|
95
99
|
|
|
96
100
|
this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
|
|
97
101
|
this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
|
|
@@ -113,6 +117,7 @@ export class TxPoolV2Impl {
|
|
|
113
117
|
|
|
114
118
|
// Post-event eviction rules (run after events to check ALL pending txs)
|
|
115
119
|
this.#evictionManager.registerRule(new InvalidTxsAfterMiningRule());
|
|
120
|
+
this.#evictionManager.registerRule(new InsufficientFeePerGasEvictionRule(deps.blockMinFeesProvider));
|
|
116
121
|
this.#evictionManager.registerRule(new InvalidTxsAfterReorgRule(deps.worldStateSynchronizer));
|
|
117
122
|
this.#evictionManager.registerRule(new FeePayerBalanceEvictionRule(deps.worldStateSynchronizer));
|
|
118
123
|
// LowPriorityEvictionRule handles cases where txs become pending via prepareForSlot (unprotect)
|
|
@@ -187,9 +192,35 @@ export class TxPoolV2Impl {
|
|
|
187
192
|
const errors = new Map<string, TxPoolRejectionError>();
|
|
188
193
|
const acceptedPending = new Set<string>();
|
|
189
194
|
|
|
195
|
+
// Phase 1: Pre-compute all throwable I/O outside the transaction.
|
|
196
|
+
// If any pre-computation throws, the entire call fails before mutations happen.
|
|
197
|
+
const precomputed = new Map<string, { meta: TxMetaData; minedBlockId: L2BlockId | undefined; isValid: boolean }>();
|
|
198
|
+
|
|
199
|
+
const validator = await this.#createTxValidator();
|
|
200
|
+
|
|
201
|
+
for (const tx of txs) {
|
|
202
|
+
const txHash = tx.getTxHash();
|
|
203
|
+
const txHashStr = txHash.toString();
|
|
204
|
+
|
|
205
|
+
const meta = await buildTxMetaData(tx);
|
|
206
|
+
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
207
|
+
|
|
208
|
+
// Validate non-mined txs (mined and pre-protected txs bypass validation inside the transaction)
|
|
209
|
+
let isValid = true;
|
|
210
|
+
if (!minedBlockId) {
|
|
211
|
+
isValid = await this.#validateMeta(meta, validator);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
precomputed.set(txHashStr, { meta, minedBlockId, isValid });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Phase 2: Apply mutations inside the transaction using only pre-computed results,
|
|
218
|
+
// in-memory reads, and buffered DB writes. Nothing here can throw an unhandled exception.
|
|
190
219
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
191
220
|
const preAddContext: PreAddContext | undefined =
|
|
192
|
-
opts.feeComparisonOnly !== undefined
|
|
221
|
+
opts.feeComparisonOnly !== undefined
|
|
222
|
+
? { feeComparisonOnly: opts.feeComparisonOnly, priceBumpPercentage: this.#config.priceBumpPercentage }
|
|
223
|
+
: undefined;
|
|
193
224
|
|
|
194
225
|
await this.#store.transactionAsync(async () => {
|
|
195
226
|
for (const tx of txs) {
|
|
@@ -202,22 +233,25 @@ export class TxPoolV2Impl {
|
|
|
202
233
|
continue;
|
|
203
234
|
}
|
|
204
235
|
|
|
205
|
-
|
|
206
|
-
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
236
|
+
const { meta, minedBlockId, isValid } = precomputed.get(txHashStr)!;
|
|
207
237
|
const preProtectedSlot = this.#indices.getProtectionSlot(txHashStr);
|
|
208
238
|
|
|
209
239
|
if (minedBlockId) {
|
|
210
240
|
// Already mined - add directly (protection already set if pre-protected)
|
|
211
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
241
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
212
242
|
accepted.push(txHash);
|
|
213
243
|
} else if (preProtectedSlot !== undefined) {
|
|
214
244
|
// Pre-protected and not mined - add as protected (bypass validation)
|
|
215
|
-
await this.#addTx(tx, { protected: preProtectedSlot }, opts);
|
|
245
|
+
await this.#addTx(tx, { protected: preProtectedSlot }, opts, meta);
|
|
216
246
|
accepted.push(txHash);
|
|
247
|
+
} else if (!isValid) {
|
|
248
|
+
// Failed pre-computed validation
|
|
249
|
+
rejected.push(txHash);
|
|
217
250
|
} else {
|
|
218
|
-
// Regular pending tx -
|
|
251
|
+
// Regular pending tx - run pre-add rules using pre-computed metadata
|
|
219
252
|
const result = await this.#tryAddRegularPendingTx(
|
|
220
253
|
tx,
|
|
254
|
+
meta,
|
|
221
255
|
opts,
|
|
222
256
|
poolAccess,
|
|
223
257
|
acceptedPending,
|
|
@@ -227,8 +261,6 @@ export class TxPoolV2Impl {
|
|
|
227
261
|
);
|
|
228
262
|
if (result.status === 'accepted') {
|
|
229
263
|
acceptedPending.add(txHashStr);
|
|
230
|
-
} else if (result.status === 'rejected') {
|
|
231
|
-
rejected.push(txHash);
|
|
232
264
|
} else {
|
|
233
265
|
ignored.push(txHash);
|
|
234
266
|
}
|
|
@@ -259,27 +291,21 @@ export class TxPoolV2Impl {
|
|
|
259
291
|
return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
|
|
260
292
|
}
|
|
261
293
|
|
|
262
|
-
/**
|
|
294
|
+
/** Adds a validated pending tx, running pre-add rules and evicting conflicts. */
|
|
263
295
|
async #tryAddRegularPendingTx(
|
|
264
296
|
tx: Tx,
|
|
297
|
+
precomputedMeta: TxMetaData,
|
|
265
298
|
opts: { source?: string },
|
|
266
299
|
poolAccess: PreAddPoolAccess,
|
|
267
300
|
acceptedPending: Set<string>,
|
|
268
301
|
ignored: TxHash[],
|
|
269
302
|
errors: Map<string, TxPoolRejectionError>,
|
|
270
303
|
preAddContext?: PreAddContext,
|
|
271
|
-
): Promise<{ status: 'accepted' | 'ignored'
|
|
272
|
-
const
|
|
273
|
-
const txHashStr = txHash.toString();
|
|
274
|
-
|
|
275
|
-
// Build metadata and validate using metadata
|
|
276
|
-
const meta = await buildTxMetaData(tx);
|
|
277
|
-
if (!(await this.#validateMeta(meta))) {
|
|
278
|
-
return { status: 'rejected' };
|
|
279
|
-
}
|
|
304
|
+
): Promise<{ status: 'accepted' | 'ignored' }> {
|
|
305
|
+
const txHashStr = tx.getTxHash().toString();
|
|
280
306
|
|
|
281
307
|
// Run pre-add rules
|
|
282
|
-
const preAddResult = await this.#evictionManager.runPreAddRules(
|
|
308
|
+
const preAddResult = await this.#evictionManager.runPreAddRules(precomputedMeta, poolAccess, preAddContext);
|
|
283
309
|
|
|
284
310
|
if (preAddResult.shouldIgnore) {
|
|
285
311
|
this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
|
|
@@ -323,7 +349,7 @@ export class TxPoolV2Impl {
|
|
|
323
349
|
}
|
|
324
350
|
|
|
325
351
|
// Add the transaction
|
|
326
|
-
await this.#addTx(tx, 'pending', opts);
|
|
352
|
+
await this.#addTx(tx, 'pending', opts, precomputedMeta);
|
|
327
353
|
return { status: 'accepted' };
|
|
328
354
|
}
|
|
329
355
|
|
|
@@ -332,6 +358,7 @@ export class TxPoolV2Impl {
|
|
|
332
358
|
|
|
333
359
|
// Check if already in pool
|
|
334
360
|
if (this.#indices.has(txHashStr)) {
|
|
361
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} already in pool`);
|
|
335
362
|
return 'ignored';
|
|
336
363
|
}
|
|
337
364
|
|
|
@@ -340,26 +367,37 @@ export class TxPoolV2Impl {
|
|
|
340
367
|
const poolAccess = this.#createPreAddPoolAccess();
|
|
341
368
|
const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
|
|
342
369
|
|
|
343
|
-
|
|
370
|
+
if (preAddResult.shouldIgnore) {
|
|
371
|
+
this.#log.verbose(`canAddPendingTx: tx ${txHashStr} ignored by pre-add rule`, {
|
|
372
|
+
reason: preAddResult.reason?.message ?? 'no reason provided',
|
|
373
|
+
});
|
|
374
|
+
return 'ignored';
|
|
375
|
+
}
|
|
376
|
+
return 'accepted';
|
|
344
377
|
}
|
|
345
378
|
|
|
346
379
|
async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
|
|
347
380
|
const slotNumber = block.globalVariables.slotNumber;
|
|
348
381
|
|
|
382
|
+
// Precompute setup-call allow-list flags outside the store transaction
|
|
383
|
+
const allowedFlags = await Promise.all(txs.map(tx => this.#checkAllowedSetupCalls(tx)));
|
|
384
|
+
|
|
349
385
|
await this.#store.transactionAsync(async () => {
|
|
350
|
-
for (
|
|
386
|
+
for (let i = 0; i < txs.length; i++) {
|
|
387
|
+
const tx = txs[i];
|
|
351
388
|
const txHash = tx.getTxHash();
|
|
352
389
|
const txHashStr = txHash.toString();
|
|
353
390
|
const isNew = !this.#indices.has(txHashStr);
|
|
354
391
|
const minedBlockId = await this.#getMinedBlockId(txHash);
|
|
355
392
|
|
|
356
393
|
if (isNew) {
|
|
394
|
+
const meta = await buildTxMetaData(tx, allowedFlags[i]);
|
|
357
395
|
// New tx - add as mined or protected (callback emitted by #addTx)
|
|
358
396
|
if (minedBlockId) {
|
|
359
|
-
await this.#addTx(tx, { mined: minedBlockId }, opts);
|
|
397
|
+
await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
|
|
360
398
|
this.#indices.setProtection(txHashStr, slotNumber);
|
|
361
399
|
} else {
|
|
362
|
-
await this.#addTx(tx, { protected: slotNumber }, opts);
|
|
400
|
+
await this.#addTx(tx, { protected: slotNumber }, opts, meta);
|
|
363
401
|
}
|
|
364
402
|
} else {
|
|
365
403
|
// Existing tx - update protection and mined status
|
|
@@ -479,6 +517,10 @@ export class TxPoolV2Impl {
|
|
|
479
517
|
await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
|
|
480
518
|
});
|
|
481
519
|
|
|
520
|
+
if (found.length > 0) {
|
|
521
|
+
this.#callbacks.onTxsMined(found.map(m => m.txHash));
|
|
522
|
+
}
|
|
523
|
+
|
|
482
524
|
this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
|
|
483
525
|
}
|
|
484
526
|
|
|
@@ -765,9 +807,10 @@ export class TxPoolV2Impl {
|
|
|
765
807
|
tx: Tx,
|
|
766
808
|
state: 'pending' | { protected: SlotNumber } | { mined: L2BlockId },
|
|
767
809
|
opts: { source?: string } = {},
|
|
810
|
+
precomputedMeta?: TxMetaData,
|
|
768
811
|
): Promise<TxMetaData> {
|
|
769
812
|
const txHashStr = tx.getTxHash().toString();
|
|
770
|
-
const meta = await buildTxMetaData(tx);
|
|
813
|
+
const meta = precomputedMeta ?? (await buildTxMetaData(tx));
|
|
771
814
|
meta.receivedAt = this.#dateProvider.now();
|
|
772
815
|
|
|
773
816
|
await this.#txsDB.set(txHashStr, tx.toBuffer());
|
|
@@ -949,7 +992,8 @@ export class TxPoolV2Impl {
|
|
|
949
992
|
|
|
950
993
|
try {
|
|
951
994
|
const tx = Tx.fromBuffer(buffer);
|
|
952
|
-
const
|
|
995
|
+
const allowedSetupCalls = await this.#checkAllowedSetupCalls(tx);
|
|
996
|
+
const meta = await buildTxMetaData(tx, allowedSetupCalls);
|
|
953
997
|
loaded.push({ tx, meta });
|
|
954
998
|
} catch (err) {
|
|
955
999
|
this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Attestation Validation
|
|
2
|
+
|
|
3
|
+
This module validates `CheckpointAttestation` gossipsub messages. Attestations are signatures from committee members endorsing a checkpoint proposal.
|
|
4
|
+
|
|
5
|
+
**Topic**: `checkpoint_attestation` | **Snappy size limit**: 5 KB
|
|
6
|
+
|
|
7
|
+
## Stage 1: AttestationValidator (Gossipsub Validation)
|
|
8
|
+
|
|
9
|
+
| # | Rule | Consequence | Severity | File |
|
|
10
|
+
|---|------|-------------|----------|------|
|
|
11
|
+
| 1 | **Slot timeliness**: `currentSlot` or `nextSlot`. Previous slot within 500ms: IGNORE. Older: REJECT. | REJECT or IGNORE | HighToleranceError | `attestation_validator.ts` |
|
|
12
|
+
| 2 | **Attester signature**: `getSender()` must recover valid address | REJECT | LowToleranceError | same |
|
|
13
|
+
| 3 | **Attester in committee**: recovered address in committee for slot | REJECT | HighToleranceError | same |
|
|
14
|
+
| 4 | **Proposer exists**: `getProposerAttesterAddressInSlot` must return defined | REJECT | HighToleranceError | same |
|
|
15
|
+
| 5 | **Proposer signature**: `getProposer()` must recover valid address | REJECT | LowToleranceError | same |
|
|
16
|
+
| 6 | **Proposer matches expected**: recovered proposer = expected for slot | REJECT | HighToleranceError | same |
|
|
17
|
+
| 7 | **NoCommitteeError**: committee unavailable | REJECT | LowToleranceError | same |
|
|
18
|
+
|
|
19
|
+
**Fisherman mode extension** (`FishermanAttestationValidator`): if a checkpoint proposal for the same archive exists in pool, the attestation's `ConsensusPayload` must `.equals()` the stored proposal's payload. On mismatch: REJECT + LowToleranceError.
|
|
20
|
+
|
|
21
|
+
## Stage 2: Pool Admission
|
|
22
|
+
|
|
23
|
+
| # | Rule | Consequence |
|
|
24
|
+
|---|------|-------------|
|
|
25
|
+
| 8 | Sender recoverable (pool-side) | Silent drop |
|
|
26
|
+
| 9 | Not a duplicate (same slot + proposalId + signer) | IGNORE |
|
|
27
|
+
| 10 | Per-signer cap: `MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER` = 2 | IGNORE |
|
|
28
|
+
|
|
29
|
+
Own attestations added via `addOwnCheckpointAttestations` bypass the per-signer cap.
|
|
30
|
+
|
|
31
|
+
## Stage 3: Equivocation Detection
|
|
32
|
+
|
|
33
|
+
When a signer's attestation count for a slot reaches exactly 2 (different proposals): `duplicateAttestationCallback` fires -> `WANT_TO_SLASH_EVENT` with `OffenseType.DUPLICATE_ATTESTATION`. Attestation still ACCEPTED and rebroadcast. Callback fires once (not again at count 3+).
|
|
34
|
+
|
|
35
|
+
## Validation at L1 Checkpoint Submission (Archiver)
|
|
36
|
+
|
|
37
|
+
| Rule | Consequence | File |
|
|
38
|
+
|------|-------------|------|
|
|
39
|
+
| Each attestation must have recoverable signature (or address-only is allowed but does not count toward quorum) | Checkpoint rejected as invalid | `archiver/src/modules/validation.ts` |
|
|
40
|
+
| Attestation at index `i` must correspond to committee member at index `i` | Checkpoint rejected as invalid | same |
|
|
41
|
+
| Valid attestation count >= floor(committee * 2/3) + 1 | Checkpoint rejected as invalid | same |
|
|
42
|
+
| No committee / escape hatch open | Accepted unconditionally | same |
|
|
43
|
+
|
|
44
|
+
Note: `skipValidateCheckpointAttestations` config flag bypasses all archiver attestation validation.
|
|
45
|
+
|
|
46
|
+
## Gossipsub Topic Scoring
|
|
47
|
+
|
|
48
|
+
P3 enabled with expected messages per slot = `targetCommitteeSize`. Conservative threshold (30% of convergence value). Max P3 penalty = -34 per topic.
|
|
49
|
+
|
|
@@ -3,19 +3,35 @@ import { NoCommitteeError } from '@aztec/ethereum/contracts';
|
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import {
|
|
5
5
|
type CheckpointAttestation,
|
|
6
|
+
type CoordinationSignatureContext,
|
|
6
7
|
type P2PValidator,
|
|
7
8
|
PeerErrorSeverity,
|
|
8
9
|
type ValidationResult,
|
|
10
|
+
hasValidSignatureContext,
|
|
9
11
|
} from '@aztec/stdlib/p2p';
|
|
10
12
|
|
|
11
|
-
import { isWithinClockTolerance } from '../clock_tolerance.js';
|
|
13
|
+
import { PipeliningWindow, isWithinClockTolerance } from '../clock_tolerance.js';
|
|
12
14
|
|
|
13
15
|
export class CheckpointAttestationValidator implements P2PValidator<CheckpointAttestation> {
|
|
14
16
|
protected epochCache: EpochCacheInterface;
|
|
15
17
|
protected logger: Logger;
|
|
18
|
+
private readonly pipeliningWindow: PipeliningWindow;
|
|
19
|
+
protected readonly signatureContext: CoordinationSignatureContext;
|
|
16
20
|
|
|
17
|
-
constructor(
|
|
21
|
+
constructor(
|
|
22
|
+
epochCache: EpochCacheInterface,
|
|
23
|
+
opts: {
|
|
24
|
+
l1PublishingTime?: number;
|
|
25
|
+
p2pPropagationTime?: number;
|
|
26
|
+
signatureContext: CoordinationSignatureContext;
|
|
27
|
+
},
|
|
28
|
+
) {
|
|
18
29
|
this.epochCache = epochCache;
|
|
30
|
+
this.pipeliningWindow = new PipeliningWindow(epochCache, {
|
|
31
|
+
l1PublishingTime: opts.l1PublishingTime,
|
|
32
|
+
p2pPropagationTime: opts.p2pPropagationTime,
|
|
33
|
+
});
|
|
34
|
+
this.signatureContext = opts.signatureContext;
|
|
19
35
|
this.logger = createLogger('p2p:checkpoint-attestation-validator');
|
|
20
36
|
}
|
|
21
37
|
|
|
@@ -23,18 +39,34 @@ export class CheckpointAttestationValidator implements P2PValidator<CheckpointAt
|
|
|
23
39
|
const slotNumber = message.payload.header.slotNumber;
|
|
24
40
|
|
|
25
41
|
try {
|
|
26
|
-
|
|
42
|
+
// Cross-chain replay check: reject attestations that carry a foreign signing domain.
|
|
43
|
+
if (!hasValidSignatureContext(message.payload, this.signatureContext)) {
|
|
44
|
+
this.logger.warn(`Rejecting checkpoint attestation with foreign signature context for slot ${slotNumber}`, {
|
|
45
|
+
chainId: message.payload.signatureContext.chainId,
|
|
46
|
+
rollupAddress: message.payload.signatureContext.rollupAddress.toString(),
|
|
47
|
+
expectedChainId: this.signatureContext.chainId,
|
|
48
|
+
expectedRollupAddress: this.signatureContext.rollupAddress.toString(),
|
|
49
|
+
});
|
|
50
|
+
return { result: 'reject', severity: PeerErrorSeverity.LowToleranceError };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Use target slots since proposals target pipeline slots (slot + 1 when pipelining).
|
|
54
|
+
const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
|
|
27
55
|
|
|
28
|
-
if (slotNumber !==
|
|
29
|
-
//
|
|
30
|
-
|
|
56
|
+
if (slotNumber !== targetSlot && slotNumber !== nextSlot) {
|
|
57
|
+
// When pipelining, accept attestations for the current slot (built in the previous slot)
|
|
58
|
+
// until the target slot reaches its L1 publish cutoff.
|
|
59
|
+
if (this.pipeliningWindow.acceptsAttestation(slotNumber)) {
|
|
60
|
+
// Fall through to remaining validation (signature, committee, etc.)
|
|
61
|
+
} else if (!isWithinClockTolerance(slotNumber, targetSlot, this.epochCache)) {
|
|
31
62
|
this.logger.warn(
|
|
32
|
-
`Checkpoint attestation slot ${slotNumber} is not current (${
|
|
63
|
+
`Checkpoint attestation slot ${slotNumber} is not current (${targetSlot}) or next (${nextSlot}) slot`,
|
|
33
64
|
);
|
|
34
65
|
return { result: 'reject', severity: PeerErrorSeverity.HighToleranceError };
|
|
66
|
+
} else {
|
|
67
|
+
this.logger.debug(`Ignoring checkpoint attestation for previous slot ${slotNumber} within clock tolerance`);
|
|
68
|
+
return { result: 'ignore' };
|
|
35
69
|
}
|
|
36
|
-
this.logger.debug(`Ignoring checkpoint attestation for previous slot ${slotNumber} within clock tolerance`);
|
|
37
|
-
return { result: 'ignore' };
|
|
38
70
|
}
|
|
39
71
|
|
|
40
72
|
// Verify the signature is valid
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type CheckpointAttestation,
|
|
4
|
+
type CoordinationSignatureContext,
|
|
5
|
+
PeerErrorSeverity,
|
|
6
|
+
type ValidationResult,
|
|
7
|
+
} from '@aztec/stdlib/p2p';
|
|
3
8
|
import { Attributes, Metrics, type TelemetryClient, createUpDownCounterWithDefault } from '@aztec/telemetry-client';
|
|
4
9
|
|
|
5
10
|
import type { AttestationPoolApi } from '../../mem_pools/attestation_pool/attestation_pool.js';
|
|
@@ -20,8 +25,13 @@ export class FishermanAttestationValidator extends CheckpointAttestationValidato
|
|
|
20
25
|
epochCache: EpochCacheInterface,
|
|
21
26
|
private attestationPool: AttestationPoolApi,
|
|
22
27
|
telemetryClient: TelemetryClient,
|
|
28
|
+
opts: {
|
|
29
|
+
l1PublishingTime?: number;
|
|
30
|
+
p2pPropagationTime?: number;
|
|
31
|
+
signatureContext: CoordinationSignatureContext;
|
|
32
|
+
},
|
|
23
33
|
) {
|
|
24
|
-
super(epochCache);
|
|
34
|
+
super(epochCache, opts);
|
|
25
35
|
this.logger = this.logger.createChild('[FISHERMAN]');
|
|
26
36
|
|
|
27
37
|
const meter = telemetryClient.getMeter('FishermanAttestationValidator');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import { DEFAULT_P2P_PROPAGATION_TIME, createPipelinedCheckpointTimingModel } from '@aztec/stdlib/timetable';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Maximum clock disparity tolerance for P2P message validation (in milliseconds).
|
|
@@ -36,10 +37,11 @@ export function isWithinClockTolerance(
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
// Check how far we are into the current slot (in milliseconds)
|
|
39
|
-
const { ts: slotStartTs, nowMs
|
|
40
|
+
const { ts: slotStartTs, nowMs } = epochCache.getEpochAndSlotNow();
|
|
41
|
+
const targetSlot = epochCache.getTargetSlot();
|
|
40
42
|
|
|
41
|
-
// Sanity check: ensure the epoch cache's
|
|
42
|
-
if (
|
|
43
|
+
// Sanity check: ensure the epoch cache's target slot matches the expected current slot
|
|
44
|
+
if (targetSlot !== currentSlot) {
|
|
43
45
|
return false;
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -49,3 +51,77 @@ export function isWithinClockTolerance(
|
|
|
49
51
|
|
|
50
52
|
return elapsedMs < MAXIMUM_GOSSIP_CLOCK_DISPARITY_MS;
|
|
51
53
|
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Checks if a straggler message for the previous target slot should be accepted.
|
|
57
|
+
*
|
|
58
|
+
* Under pipelining, proposals and attestations carry the target slot N. Most of the
|
|
59
|
+
* time the receiver is either still in the build slot N-1 (accepted via the main
|
|
60
|
+
* `slotNumber === targetSlot` match) or in the target slot N (accepted via
|
|
61
|
+
* `slotNumber === nextSlot` when pipelining is disabled, or again via `targetSlot`
|
|
62
|
+
* when the receiver itself is pipelining). Stragglers that arrive after the receiver
|
|
63
|
+
* has rolled past the target slot fall to this check: accept `messageSlot === slotNow`
|
|
64
|
+
* while we're still within the first `windowSeconds + clock-disparity` of the slot.
|
|
65
|
+
*
|
|
66
|
+
* Under the early-pipelining schedule `windowSeconds` is small (0 for proposals,
|
|
67
|
+
* `2*p2pPropagationTime` for attestations) since the proposer collects everything
|
|
68
|
+
* before the slot boundary.
|
|
69
|
+
*
|
|
70
|
+
* @param messageSlot - The slot number from the received message
|
|
71
|
+
* @param epochCache - EpochCache to get timing and pipelining state
|
|
72
|
+
* @param windowSeconds - How far into the current slot we still accept previous-target messages
|
|
73
|
+
* @returns true if pipelining is enabled, the message is for the current wallclock slot, and we're within the grace period
|
|
74
|
+
*/
|
|
75
|
+
function isWithinPipeliningWindow(
|
|
76
|
+
messageSlot: SlotNumber,
|
|
77
|
+
epochCache: EpochCacheInterface,
|
|
78
|
+
windowSeconds: number,
|
|
79
|
+
): boolean {
|
|
80
|
+
if (!epochCache.isProposerPipeliningEnabled()) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const currentSlot = epochCache.getSlotNow();
|
|
85
|
+
if (messageSlot !== currentSlot) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const { ts: slotStartTs, nowMs } = epochCache.getEpochAndSlotNow();
|
|
90
|
+
const slotStartMs = slotStartTs * 1000n;
|
|
91
|
+
const elapsedMs = Number(nowMs - slotStartMs);
|
|
92
|
+
const windowMs = windowSeconds * 1000 + MAXIMUM_GOSSIP_CLOCK_DISPARITY_MS;
|
|
93
|
+
|
|
94
|
+
return elapsedMs < windowMs;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export class PipeliningWindow {
|
|
98
|
+
private readonly proposalWindowIntoTargetSlot: number;
|
|
99
|
+
private readonly attestationWindowIntoTargetSlot: number;
|
|
100
|
+
|
|
101
|
+
constructor(
|
|
102
|
+
private readonly epochCache: EpochCacheInterface,
|
|
103
|
+
opts: {
|
|
104
|
+
p2pPropagationTime?: number;
|
|
105
|
+
l1PublishingTime?: number;
|
|
106
|
+
} = {},
|
|
107
|
+
) {
|
|
108
|
+
const l1Constants = epochCache.getL1Constants();
|
|
109
|
+
const checkpointTiming = createPipelinedCheckpointTimingModel({
|
|
110
|
+
aztecSlotDuration: l1Constants.slotDuration,
|
|
111
|
+
ethereumSlotDuration: l1Constants.ethereumSlotDuration,
|
|
112
|
+
l1PublishingTime: opts.l1PublishingTime ?? l1Constants.ethereumSlotDuration,
|
|
113
|
+
p2pPropagationTime: opts.p2pPropagationTime ?? DEFAULT_P2P_PROPAGATION_TIME,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
this.proposalWindowIntoTargetSlot = checkpointTiming.proposalWindowIntoTargetSlot;
|
|
117
|
+
this.attestationWindowIntoTargetSlot = checkpointTiming.attestationWindowIntoTargetSlot;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public acceptsProposal(messageSlot: SlotNumber): boolean {
|
|
121
|
+
return isWithinPipeliningWindow(messageSlot, this.epochCache, this.proposalWindowIntoTargetSlot);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public acceptsAttestation(messageSlot: SlotNumber): boolean {
|
|
125
|
+
return isWithinPipeliningWindow(messageSlot, this.epochCache, this.attestationWindowIntoTargetSlot);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Proposal Validation
|
|
2
|
+
|
|
3
|
+
This module validates `BlockProposal` and `CheckpointProposal` gossipsub messages. Both share the same base `ProposalValidator` (neither subclass overrides `validate()`), with checkpoint-specific logic layered on top in the gossipsub handler.
|
|
4
|
+
|
|
5
|
+
## BlockProposal
|
|
6
|
+
|
|
7
|
+
**Topic**: `block_proposal` | **Snappy size limit**: 10 MB
|
|
8
|
+
|
|
9
|
+
### Stage 1: Gossipsub Validation (ProposalValidator)
|
|
10
|
+
|
|
11
|
+
File: `proposal_validator.ts`
|
|
12
|
+
|
|
13
|
+
| # | Rule | Consequence | Severity |
|
|
14
|
+
|---|------|-------------|----------|
|
|
15
|
+
| 1 | **Slot check**: must be `currentSlot` or `nextSlot`. Previous slot within 500ms tolerance: IGNORE. | REJECT | HighToleranceError |
|
|
16
|
+
| 2 | **Signature**: `getSender()` must recover a valid address. If `signedTxs` present, its recovered sender must match. | REJECT | MidToleranceError |
|
|
17
|
+
| 3 | **Txs permitted**: if `disableTransactions`, must have 0 txHashes and 0 embedded txs | REJECT | MidToleranceError |
|
|
18
|
+
| 4 | **Max txs**: `txHashes.length <= maxTxsPerBlock` | REJECT | MidToleranceError |
|
|
19
|
+
| 5 | **Embedded txs in txHashes**: every embedded tx's hash must appear in `txHashes` | REJECT | MidToleranceError |
|
|
20
|
+
| 6 | **Proposer check**: signer must match expected proposer for slot (skipped if committee size = 0) | REJECT | MidToleranceError |
|
|
21
|
+
| 7 | **Tx hash integrity**: each embedded tx's recomputed hash must match declared hash | REJECT | LowToleranceError |
|
|
22
|
+
| 8 | **NoCommitteeError**: epoch cache cannot determine committee | REJECT | LowToleranceError |
|
|
23
|
+
|
|
24
|
+
Deserialization guards: `BlockProposal.fromBuffer` and `SignedTxs.fromBuffer` both enforce `txCount <= MAX_TXS_PER_BLOCK` (65536). Violation -> REJECT + LowToleranceError.
|
|
25
|
+
|
|
26
|
+
### Stage 2: Mempool (Attestation Pool)
|
|
27
|
+
|
|
28
|
+
| # | Rule | Consequence |
|
|
29
|
+
|---|------|-------------|
|
|
30
|
+
| 9 | **Duplicate**: same archive root already stored | IGNORE (no penalty) |
|
|
31
|
+
| 10 | **Per-position cap**: max 2 proposals per (slot, indexWithinCheckpoint) | REJECT + HighToleranceError |
|
|
32
|
+
| 11 | **Equivocation**: >1 distinct proposal for same (slot, index) | ACCEPT (rebroadcast for detection). At count=2: `duplicateProposalCallback` fires -> slash event (`OffenseType.DUPLICATE_PROPOSAL`, configured via `slashDuplicateProposalPenalty`) |
|
|
33
|
+
|
|
34
|
+
### Stage 3: Validator-Client Processing (BlockProposalHandler)
|
|
35
|
+
|
|
36
|
+
Only runs on validator nodes. Non-validator nodes use a default handler that triggers tx collection without deep validation.
|
|
37
|
+
|
|
38
|
+
| # | Rule | Failure Reason |
|
|
39
|
+
|---|------|----------------|
|
|
40
|
+
| 12 | Signature re-check | `invalid_proposal` |
|
|
41
|
+
| 13 | ProposalValidator re-run | `invalid_proposal` |
|
|
42
|
+
| 14 | Self-proposal filter | Ignored silently |
|
|
43
|
+
| 15 | Parent block exists (`lastArchive.root` matches known block or genesis) | `parent_block_not_found` |
|
|
44
|
+
| 16 | Parent block slot <= proposal slot | `parent_block_wrong_slot` |
|
|
45
|
+
| 17 | Block number not already in archiver | `block_number_already_exists` |
|
|
46
|
+
| 18 | Checkpoint number consistency (multiple sub-rules for first/non-first blocks) | `invalid_proposal` |
|
|
47
|
+
| 19 | Global variables consistency (non-first block: chainId, version, slot, timestamp, coinbase, feeRecipient, gasFees match parent) | `global_variables_mismatch` |
|
|
48
|
+
| 20 | L1-to-L2 message hash matches `proposal.inHash` | `in_hash_mismatch` |
|
|
49
|
+
| 21 | All txs referenced by `txHashes` obtainable | `txs_not_available` |
|
|
50
|
+
| 22 | **Re-execution**: processed tx count matches `txHashes.length` | `timeout` (ReExTimeoutError) |
|
|
51
|
+
| 23 | **Re-execution**: no failed txs | `failed_txs` (ReExFailedTxsError) -- **SLASHABLE** |
|
|
52
|
+
| 24 | **Re-execution**: archive root and header match proposal | `state_mismatch` (ReExStateMismatchError) -- **SLASHABLE** |
|
|
53
|
+
|
|
54
|
+
**Escape hatch**: during escape hatch periods (`isEscapeHatchOpenAtSlot`), re-execution and slashing are both disabled, and the proposal is rejected locally.
|
|
55
|
+
|
|
56
|
+
**Conditional re-execution**: rules 22-24 only run when at least one condition is true: `fishermanMode` enabled, `slashBroadcastedInvalidBlockPenalty > 0`, committee membership, `alwaysReexecuteBlockProposals`, or `blobClient.canUpload()`.
|
|
57
|
+
|
|
58
|
+
**Slashing**: only `state_mismatch` and `failed_txs` trigger on-chain slashing (`OffenseType.BROADCASTED_INVALID_BLOCK_PROPOSAL`, gated by `slashBroadcastedInvalidBlockPenalty > 0`). Unknown errors during re-execution do NOT slash.
|
|
59
|
+
|
|
60
|
+
**Embedded tx validation**: txs in `signedTxs` are validated via `createTxValidatorForBlockProposalReceivedTxs` (well-formedness only) when stored in the tx pool. Invalid embedded txs are rejected from the pool but do not cause the block proposal itself to be rejected at gossipsub level.
|
|
61
|
+
|
|
62
|
+
### Gossipsub Topic Scoring
|
|
63
|
+
|
|
64
|
+
| Parameter | Effect |
|
|
65
|
+
|-----------|--------|
|
|
66
|
+
| P4 (invalidMessageDeliveries) | weight = -20, decay over 4 slots |
|
|
67
|
+
| P3 (meshMessageDeliveries) | Enabled only when `expectedBlockProposalsPerSlot > 0` (MBPS mode) |
|
|
68
|
+
| P1/P2 | Only active when P3 is enabled |
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## CheckpointProposal
|
|
73
|
+
|
|
74
|
+
**Topic**: `checkpoint_proposal` | **Snappy size limit**: 10 MB
|
|
75
|
+
|
|
76
|
+
### Stage 1: Gossipsub Validation (ProposalValidator)
|
|
77
|
+
|
|
78
|
+
Same `ProposalValidator.validate()` as BlockProposal (shared implementation, neither subclass overrides it). See BlockProposal Stage 1 rules 1-8.
|
|
79
|
+
|
|
80
|
+
### Stage 2: Embedded Block Proposal Validation (if `lastBlock` present)
|
|
81
|
+
|
|
82
|
+
The checkpoint's embedded `lastBlock` is extracted via `getBlockProposal()` and validated through `BlockProposalValidator.validate()` plus block mempool checks.
|
|
83
|
+
|
|
84
|
+
| Rule | Consequence | File |
|
|
85
|
+
|------|-------------|------|
|
|
86
|
+
| Block proposal must pass `BlockProposalValidator.validate()` | If REJECT: entire checkpoint REJECTED | `libp2p_service.ts` |
|
|
87
|
+
| Block proposal must not exceed per-position cap (2) | Checkpoint REJECTED + HighToleranceError | same |
|
|
88
|
+
| Block equivocation detected (>1 proposals for same slot+index) | Checkpoint REJECTED (block itself is ACCEPT for re-broadcast) | same |
|
|
89
|
+
|
|
90
|
+
### Stage 3: Mempool (Attestation Pool)
|
|
91
|
+
|
|
92
|
+
| Rule | Consequence | File |
|
|
93
|
+
|------|-------------|------|
|
|
94
|
+
| Duplicate (same archive ID) | IGNORE (no penalty). Embedded block still processed if valid. | `attestation_pool.ts` |
|
|
95
|
+
| Per-slot cap: `MAX_CHECKPOINT_PROPOSALS_PER_SLOT` = 2 | REJECT + HighToleranceError. Embedded block still processed. | same |
|
|
96
|
+
|
|
97
|
+
### Stage 4: Equivocation Detection
|
|
98
|
+
|
|
99
|
+
When >1 checkpoint proposals exist for same slot (count > 1): ACCEPT (re-broadcast). At count == 2 (exactly): `duplicateProposalCallback` fires. Proposal NOT further processed. Callback fires only once per equivocation pair.
|
|
100
|
+
|
|
101
|
+
### Stage 5: Validator-Client Consensus Validation
|
|
102
|
+
|
|
103
|
+
Determines whether the validator signs an attestation.
|
|
104
|
+
|
|
105
|
+
| Rule | Consequence | File |
|
|
106
|
+
|------|-------------|------|
|
|
107
|
+
| Escape hatch open | No attestation | `validator-client/src/validator.ts` |
|
|
108
|
+
| Signature invalid (re-check) | No attestation | same |
|
|
109
|
+
| Self-proposal | No attestation (ignored) | same |
|
|
110
|
+
| `feeAssetPriceModifier` outside [-100, +100] bps | No attestation | same |
|
|
111
|
+
| Not in committee (unless fisherman mode) | No attestation | same |
|
|
112
|
+
| Checkpoint header mismatch (computed vs proposal) | No attestation | same |
|
|
113
|
+
| Archive root mismatch | No attestation | same |
|
|
114
|
+
| Epoch out hash mismatch | No attestation | same |
|
|
115
|
+
| Last block not found / not matching | No attestation | same |
|
|
116
|
+
| Already attested to this or earlier slot | No attestation (unless `attestToEquivocatedProposals`) | same |
|
|
117
|
+
|
|
118
|
+
**`skipCheckpointProposalValidation` config**: when true, the re-execution checks (header/archive/epoch hash) are all skipped. Signature, fee modifier, committee, escape hatch, and equivocation checks still apply.
|
|
119
|
+
|
|
120
|
+
### Gossipsub Topic Scoring
|
|
121
|
+
|
|
122
|
+
P3 enabled with expected rate of 1 message per slot. P4 weight = -20, max P3 penalty = -34 per topic.
|
|
123
|
+
|