@aztec/p2p 0.0.1-commit.b655e406 → 0.0.1-commit.d3ec352c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bootstrap/bootstrap.d.ts +1 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/client/factory.d.ts +1 -1
- package/dest/client/index.d.ts +1 -1
- package/dest/client/interface.d.ts +4 -2
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +8 -26
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +22 -16
- package/dest/config.d.ts +60 -54
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +11 -1
- package/dest/enr/generate-enr.d.ts +1 -1
- package/dest/enr/index.d.ts +1 -1
- package/dest/errors/attestation-pool.error.d.ts +7 -0
- package/dest/errors/attestation-pool.error.d.ts.map +1 -0
- package/dest/errors/attestation-pool.error.js +12 -0
- package/dest/errors/reqresp.error.d.ts +1 -1
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/index.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +28 -6
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +33 -32
- package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +13 -6
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +40 -17
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +11 -6
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +30 -8
- package/dest/mem_pools/attestation_pool/mocks.d.ts +224 -3
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +1 -1
- package/dest/mem_pools/index.d.ts +1 -1
- package/dest/mem_pools/instrumentation.d.ts +3 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +11 -2
- package/dest/mem_pools/interface.d.ts +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +4 -38
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/index.d.ts +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +4 -3
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +1 -0
- package/dest/mem_pools/tx_pool/priority.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +4 -3
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +5 -4
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +11 -11
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +67 -0
- package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
- package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/index.js +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -9
- package/dest/msg_validators/block_proposal_validator/index.d.ts +1 -1
- package/dest/msg_validators/index.d.ts +1 -1
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
- package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
- package/dest/msg_validators/tx_validator/archive_cache.d.ts +1 -1
- package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/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/double_spend_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.d.ts +3 -2
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.d.ts +1 -1
- 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/phases_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +3 -1
- package/dest/msg_validators/tx_validator/test_utils.d.ts +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/services/data_store.d.ts +1 -1
- package/dest/services/data_store.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.d.ts +1 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/dummy_service.d.ts +1 -1
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/gossipsub/scoring.d.ts +1 -1
- package/dest/services/index.d.ts +1 -1
- 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 +9 -2
- package/dest/services/libp2p/libp2p_service.d.ts +11 -67
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +227 -57
- package/dest/services/peer-manager/interface.d.ts +1 -1
- 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 +11 -0
- package/dest/services/peer-manager/peer_manager.d.ts +1 -32
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +2 -0
- 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 +40 -2
- package/dest/services/reqresp/config.d.ts +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +1 -1
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -4
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/index.d.ts +1 -1
- package/dest/services/reqresp/interface.d.ts +1 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/metrics.d.ts +1 -1
- package/dest/services/reqresp/metrics.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/auth.d.ts +1 -1
- package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.d.ts +1 -1
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.js +2 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +3 -5
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
- package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.d.ts +1 -1
- package/dest/services/reqresp/protocols/ping.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts +6 -5
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +4 -3
- package/dest/services/reqresp/protocols/tx.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts +1 -41
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/status.d.ts +2 -2
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/service.d.ts +1 -1
- package/dest/services/tx_collection/config.d.ts +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -9
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/index.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.d.ts +4 -5
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +2 -1
- package/dest/services/tx_collection/tx_collection.d.ts +9 -9
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +1 -1
- package/dest/services/tx_collection/tx_collection_sink.d.ts +3 -3
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.d.ts +1 -1
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_provider.d.ts +5 -4
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts +1 -1
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
- package/dest/test-helpers/get-ports.d.ts +1 -1
- package/dest/test-helpers/get-ports.d.ts.map +1 -1
- package/dest/test-helpers/index.d.ts +1 -1
- package/dest/test-helpers/make-enrs.d.ts +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts +2 -2
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +4 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-tx-helpers.d.ts +2 -2
- package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +11 -8
- package/dest/testbench/parse_log_file.d.ts +1 -1
- package/dest/testbench/testbench.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/types/index.d.ts +1 -1
- package/dest/util.d.ts +2 -1
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +11 -2
- package/dest/versioning.d.ts +1 -1
- package/package.json +19 -18
- package/src/client/interface.ts +4 -1
- package/src/client/p2p_client.ts +37 -29
- package/src/config.ts +18 -1
- package/src/errors/attestation-pool.error.ts +13 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +29 -5
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +45 -32
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +65 -23
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +50 -16
- package/src/mem_pools/attestation_pool/mocks.ts +1 -1
- package/src/mem_pools/instrumentation.ts +13 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +7 -6
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +8 -6
- package/src/mem_pools/tx_pool/tx_pool.ts +3 -2
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +5 -4
- package/src/msg_validators/attestation_validator/attestation_validator.ts +13 -15
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +91 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +25 -9
- package/src/msg_validators/tx_validator/factory.ts +2 -1
- package/src/msg_validators/tx_validator/phases_validator.ts +3 -1
- package/src/msg_validators/tx_validator/timestamp_validator.ts +2 -1
- package/src/services/libp2p/instrumentation.ts +10 -1
- package/src/services/libp2p/libp2p_service.ts +255 -66
- package/src/services/peer-manager/metrics.ts +10 -0
- package/src/services/peer-manager/peer_manager.ts +2 -0
- package/src/services/peer-manager/peer_scoring.ts +46 -3
- package/src/services/reqresp/protocols/block.ts +2 -1
- package/src/services/reqresp/protocols/status.ts +9 -8
- package/src/services/tx_collection/fast_tx_collection.ts +3 -2
- package/src/services/tx_collection/slow_tx_collection.ts +5 -4
- package/src/services/tx_collection/tx_collection.ts +9 -8
- package/src/services/tx_provider.ts +4 -3
- package/src/testbench/p2p_client_testbench_worker.ts +8 -5
- package/src/util.ts +12 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import { Secp256k1Signer } from '@aztec/foundation/crypto';
|
|
2
3
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
4
|
import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
@@ -42,7 +43,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
42
43
|
|
|
43
44
|
const mockBlockProposal = (signer: Secp256k1Signer, slotNumber: number, archive: Fr = Fr.random()): BlockProposal => {
|
|
44
45
|
const header = makeL2BlockHeader(1, 2, slotNumber);
|
|
45
|
-
const payload = new ConsensusPayload(header.toCheckpointHeader(), archive
|
|
46
|
+
const payload = new ConsensusPayload(header.toCheckpointHeader(), archive);
|
|
46
47
|
|
|
47
48
|
const hash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
|
|
48
49
|
const signature = signer.sign(hash);
|
|
@@ -68,7 +69,10 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
68
69
|
|
|
69
70
|
await ap.addAttestations(attestations);
|
|
70
71
|
|
|
71
|
-
const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
72
|
+
const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
73
|
+
SlotNumber(slotNumber),
|
|
74
|
+
archive.toString(),
|
|
75
|
+
);
|
|
72
76
|
expect(retrievedAttestations.length).toBe(attestations.length);
|
|
73
77
|
compareAttestations(retrievedAttestations, attestations);
|
|
74
78
|
|
|
@@ -77,7 +81,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
77
81
|
expect(await ap.hasAttestation(attestation)).toBe(true);
|
|
78
82
|
}
|
|
79
83
|
|
|
80
|
-
const retrievedAttestationsForSlot = await ap.getAttestationsForSlot(
|
|
84
|
+
const retrievedAttestationsForSlot = await ap.getAttestationsForSlot(SlotNumber(slotNumber));
|
|
81
85
|
expect(retrievedAttestationsForSlot.length).toBe(attestations.length);
|
|
82
86
|
compareAttestations(retrievedAttestationsForSlot, attestations);
|
|
83
87
|
|
|
@@ -85,21 +89,21 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
85
89
|
const newAttestation = mockAttestation(signers[NUMBER_OF_SIGNERS_PER_TEST - 1], slotNumber, archive);
|
|
86
90
|
await ap.addAttestations([newAttestation]);
|
|
87
91
|
const retrievedAttestationsAfterAdd = await ap.getAttestationsForSlotAndProposal(
|
|
88
|
-
|
|
92
|
+
SlotNumber(slotNumber),
|
|
89
93
|
archive.toString(),
|
|
90
94
|
);
|
|
91
95
|
expect(retrievedAttestationsAfterAdd.length).toBe(attestations.length + 1);
|
|
92
96
|
compareAttestations(retrievedAttestationsAfterAdd, [...attestations, newAttestation]);
|
|
93
97
|
expect(await ap.hasAttestation(newAttestation)).toBe(true);
|
|
94
|
-
const retrievedAttestationsForSlotAfterAdd = await ap.getAttestationsForSlot(
|
|
98
|
+
const retrievedAttestationsForSlotAfterAdd = await ap.getAttestationsForSlot(SlotNumber(slotNumber));
|
|
95
99
|
expect(retrievedAttestationsForSlotAfterAdd.length).toBe(attestations.length + 1);
|
|
96
100
|
compareAttestations(retrievedAttestationsForSlotAfterAdd, [...attestations, newAttestation]);
|
|
97
101
|
|
|
98
102
|
// Delete by slot
|
|
99
|
-
await ap.deleteAttestationsForSlot(
|
|
103
|
+
await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
|
|
100
104
|
|
|
101
105
|
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
|
|
102
|
-
|
|
106
|
+
SlotNumber(slotNumber),
|
|
103
107
|
archive.toString(),
|
|
104
108
|
);
|
|
105
109
|
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
@@ -124,14 +128,17 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
124
128
|
// Add them to store and check we end up with only one
|
|
125
129
|
await ap.addAttestations(attestations);
|
|
126
130
|
|
|
127
|
-
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
131
|
+
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
132
|
+
SlotNumber(slotNumber),
|
|
133
|
+
archive.toString(),
|
|
134
|
+
);
|
|
128
135
|
expect(retreivedAttestations.length).toBe(1);
|
|
129
136
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
|
|
130
137
|
expect(retreivedAttestations[0].getSender()?.toString()).toEqual(signer.address.toString());
|
|
131
138
|
|
|
132
139
|
// Try adding them on another operation and check they are still not duplicated
|
|
133
140
|
await ap.addAttestations([attestations[0]]);
|
|
134
|
-
expect(await ap.getAttestationsForSlotAndProposal(
|
|
141
|
+
expect(await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), archive.toString())).toHaveLength(1);
|
|
135
142
|
});
|
|
136
143
|
|
|
137
144
|
it('should store attestations by differing slot', async () => {
|
|
@@ -144,7 +151,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
144
151
|
const slot = attestation.payload.header.slotNumber;
|
|
145
152
|
const archive = attestation.archive.toString();
|
|
146
153
|
|
|
147
|
-
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot
|
|
154
|
+
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot, archive);
|
|
148
155
|
expect(retreivedAttestations.length).toBe(1);
|
|
149
156
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
150
157
|
expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
|
|
@@ -162,7 +169,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
162
169
|
const slot = attestation.payload.header.slotNumber;
|
|
163
170
|
const proposalId = attestation.archive.toString();
|
|
164
171
|
|
|
165
|
-
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot
|
|
172
|
+
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot, proposalId);
|
|
166
173
|
expect(retreivedAttestations.length).toBe(1);
|
|
167
174
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
168
175
|
expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
|
|
@@ -177,7 +184,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
177
184
|
|
|
178
185
|
await ap.addAttestations(attestations);
|
|
179
186
|
|
|
180
|
-
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
187
|
+
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
|
|
181
188
|
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
182
189
|
compareAttestations(retreivedAttestations, attestations);
|
|
183
190
|
|
|
@@ -188,7 +195,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
188
195
|
|
|
189
196
|
await ap.deleteAttestations(attestations);
|
|
190
197
|
|
|
191
|
-
const gottenAfterDelete = await ap.getAttestationsForSlotAndProposal(
|
|
198
|
+
const gottenAfterDelete = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
|
|
192
199
|
expect(gottenAfterDelete.length).toBe(0);
|
|
193
200
|
|
|
194
201
|
// Check hasAttestation after deletion
|
|
@@ -205,13 +212,16 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
205
212
|
|
|
206
213
|
await ap.addAttestations(attestations);
|
|
207
214
|
|
|
208
|
-
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
215
|
+
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
|
|
209
216
|
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
210
217
|
compareAttestations(retreivedAttestations, attestations);
|
|
211
218
|
|
|
212
|
-
await ap.deleteAttestationsForSlot(
|
|
219
|
+
await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
|
|
213
220
|
|
|
214
|
-
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
|
|
221
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
|
|
222
|
+
SlotNumber(slotNumber),
|
|
223
|
+
proposalId,
|
|
224
|
+
);
|
|
215
225
|
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
216
226
|
});
|
|
217
227
|
|
|
@@ -229,17 +239,20 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
229
239
|
await ap.addAttestations(attestations);
|
|
230
240
|
await ap.addAttestations(attestations2);
|
|
231
241
|
|
|
232
|
-
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
242
|
+
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
|
|
233
243
|
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
234
244
|
compareAttestations(retreivedAttestations, attestations);
|
|
235
245
|
|
|
236
|
-
await ap.deleteAttestationsForSlotAndProposal(
|
|
246
|
+
await ap.deleteAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
|
|
237
247
|
|
|
238
|
-
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
|
|
248
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
|
|
249
|
+
SlotNumber(slotNumber),
|
|
250
|
+
proposalId,
|
|
251
|
+
);
|
|
239
252
|
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
240
253
|
|
|
241
254
|
const retreivedAttestationsAfterDeleteForOtherProposal = await ap.getAttestationsForSlotAndProposal(
|
|
242
|
-
|
|
255
|
+
SlotNumber(slotNumber),
|
|
243
256
|
proposalId2,
|
|
244
257
|
);
|
|
245
258
|
expect(retreivedAttestationsAfterDeleteForOtherProposal.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
@@ -255,22 +268,22 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
255
268
|
|
|
256
269
|
await ap.addAttestations(attestations);
|
|
257
270
|
|
|
258
|
-
const attestationsForSlot1 = await ap.getAttestationsForSlotAndProposal(
|
|
271
|
+
const attestationsForSlot1 = await ap.getAttestationsForSlotAndProposal(SlotNumber(1), proposalId);
|
|
259
272
|
expect(attestationsForSlot1.length).toBe(signers.length);
|
|
260
273
|
|
|
261
274
|
const deleteAttestationsSpy = jest.spyOn(ap, 'deleteAttestationsForSlot');
|
|
262
275
|
|
|
263
|
-
await ap.deleteAttestationsOlderThan(
|
|
276
|
+
await ap.deleteAttestationsOlderThan(SlotNumber(73));
|
|
264
277
|
|
|
265
|
-
const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlotAndProposal(
|
|
278
|
+
const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlotAndProposal(SlotNumber(1), proposalId);
|
|
266
279
|
expect(attestationsForSlot1AfterDelete.length).toBe(0);
|
|
267
280
|
|
|
268
281
|
expect(deleteAttestationsSpy).toHaveBeenCalledTimes(5);
|
|
269
|
-
expect(deleteAttestationsSpy).toHaveBeenCalledWith(
|
|
270
|
-
expect(deleteAttestationsSpy).toHaveBeenCalledWith(
|
|
271
|
-
expect(deleteAttestationsSpy).toHaveBeenCalledWith(
|
|
272
|
-
expect(deleteAttestationsSpy).toHaveBeenCalledWith(
|
|
273
|
-
expect(deleteAttestationsSpy).toHaveBeenCalledWith(
|
|
282
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(1));
|
|
283
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(2));
|
|
284
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(3));
|
|
285
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(69));
|
|
286
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(72));
|
|
274
287
|
});
|
|
275
288
|
|
|
276
289
|
describe('BlockProposal in attestation pool', () => {
|
|
@@ -334,7 +347,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
334
347
|
const retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
335
348
|
expect(retrievedProposal).toBeDefined();
|
|
336
349
|
expect(retrievedProposal!.toBuffer()).toEqual(proposal2.toBuffer());
|
|
337
|
-
expect(retrievedProposal!.slotNumber
|
|
350
|
+
expect(retrievedProposal!.slotNumber).toBe(SlotNumber(200));
|
|
338
351
|
});
|
|
339
352
|
|
|
340
353
|
it('should delete block proposal when deleting attestations for slot and proposal', async () => {
|
|
@@ -354,7 +367,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
354
367
|
expect(await ap.hasBlockProposal(proposalId)).toBe(true);
|
|
355
368
|
|
|
356
369
|
// Delete attestations for slot and proposal
|
|
357
|
-
await ap.deleteAttestationsForSlotAndProposal(
|
|
370
|
+
await ap.deleteAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
|
|
358
371
|
|
|
359
372
|
// Proposal should be deleted
|
|
360
373
|
retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
@@ -377,7 +390,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
377
390
|
expect(await ap.hasBlockProposal(proposal)).toBe(true);
|
|
378
391
|
|
|
379
392
|
// Delete attestations for slot
|
|
380
|
-
await ap.deleteAttestationsForSlot(
|
|
393
|
+
await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
|
|
381
394
|
|
|
382
395
|
// Proposal should be deleted
|
|
383
396
|
retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
@@ -400,7 +413,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
400
413
|
|
|
401
414
|
// Retrieve both proposal and attestations
|
|
402
415
|
const retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
403
|
-
const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(
|
|
416
|
+
const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
|
|
404
417
|
|
|
405
418
|
expect(retrievedProposal).toBeDefined();
|
|
406
419
|
expect(retrievedProposal).toEqual(proposal);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
4
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -5,9 +6,13 @@ import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@azte
|
|
|
5
6
|
import { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
6
7
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
7
8
|
|
|
9
|
+
import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
|
|
8
10
|
import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
|
|
9
11
|
import type { AttestationPool } from './attestation_pool.js';
|
|
10
12
|
|
|
13
|
+
export const MAX_PROPOSALS_PER_SLOT = 5;
|
|
14
|
+
export const ATTESTATION_CAP_BUFFER = 10;
|
|
15
|
+
|
|
11
16
|
export class KvAttestationPool implements AttestationPool {
|
|
12
17
|
private metrics: PoolInstrumentation<BlockAttestation>;
|
|
13
18
|
|
|
@@ -16,7 +21,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
16
21
|
/* proposal.payload.archive */ string,
|
|
17
22
|
/* buffer representation of proposal */ Buffer
|
|
18
23
|
>;
|
|
19
|
-
private proposalsForSlot: AztecAsyncMultiMap<
|
|
24
|
+
private proposalsForSlot: AztecAsyncMultiMap<number, string>;
|
|
20
25
|
private attestationsForProposal: AztecAsyncMultiMap<string, string>;
|
|
21
26
|
|
|
22
27
|
constructor(
|
|
@@ -70,7 +75,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
70
75
|
|
|
71
76
|
// Skip attestations with invalid signatures
|
|
72
77
|
if (!sender) {
|
|
73
|
-
this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber
|
|
78
|
+
this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber}`, {
|
|
74
79
|
signature: attestation.signature.toString(),
|
|
75
80
|
slotNumber,
|
|
76
81
|
proposalId,
|
|
@@ -82,13 +87,13 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
82
87
|
|
|
83
88
|
await this.attestations.set(this.getAttestationKey(slotNumber, proposalId, address), attestation.toBuffer());
|
|
84
89
|
|
|
85
|
-
await this.proposalsForSlot.set(slotNumber
|
|
90
|
+
await this.proposalsForSlot.set(slotNumber, proposalId.toString());
|
|
86
91
|
await this.attestationsForProposal.set(
|
|
87
92
|
this.getProposalKey(slotNumber, proposalId),
|
|
88
93
|
this.getAttestationKey(slotNumber, proposalId, address),
|
|
89
94
|
);
|
|
90
95
|
|
|
91
|
-
this.log.verbose(`Added attestation for slot ${slotNumber
|
|
96
|
+
this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`, {
|
|
92
97
|
signature: attestation.signature.toString(),
|
|
93
98
|
slotNumber,
|
|
94
99
|
address,
|
|
@@ -98,9 +103,8 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
98
103
|
});
|
|
99
104
|
}
|
|
100
105
|
|
|
101
|
-
public async getAttestationsForSlot(slot:
|
|
102
|
-
const
|
|
103
|
-
const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slotFr.toString()));
|
|
106
|
+
public async getAttestationsForSlot(slot: SlotNumber): Promise<BlockAttestation[]> {
|
|
107
|
+
const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
|
|
104
108
|
const attestations: BlockAttestation[] = [];
|
|
105
109
|
|
|
106
110
|
for (const proposalId of proposalIds) {
|
|
@@ -110,7 +114,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
110
114
|
return attestations;
|
|
111
115
|
}
|
|
112
116
|
|
|
113
|
-
public async getAttestationsForSlotAndProposal(slot:
|
|
117
|
+
public async getAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<BlockAttestation[]> {
|
|
114
118
|
const attestationIds = await toArray(
|
|
115
119
|
this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
|
|
116
120
|
);
|
|
@@ -132,21 +136,20 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
132
136
|
return attestations;
|
|
133
137
|
}
|
|
134
138
|
|
|
135
|
-
public async deleteAttestationsOlderThan(oldestSlot:
|
|
136
|
-
const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end:
|
|
139
|
+
public async deleteAttestationsOlderThan(oldestSlot: SlotNumber): Promise<void> {
|
|
140
|
+
const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end: oldestSlot }));
|
|
137
141
|
for (const oldSlot of olderThan) {
|
|
138
|
-
await this.deleteAttestationsForSlot(
|
|
142
|
+
await this.deleteAttestationsForSlot(SlotNumber(oldSlot));
|
|
139
143
|
}
|
|
140
144
|
}
|
|
141
145
|
|
|
142
|
-
public async deleteAttestationsForSlot(slot:
|
|
143
|
-
const slotFr = new Fr(slot);
|
|
146
|
+
public async deleteAttestationsForSlot(slot: SlotNumber): Promise<void> {
|
|
144
147
|
let numberOfAttestations = 0;
|
|
145
148
|
await this.store.transactionAsync(async () => {
|
|
146
|
-
const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(
|
|
149
|
+
const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
|
|
147
150
|
for (const proposalId of proposalIds) {
|
|
148
151
|
const attestations = await toArray(
|
|
149
|
-
this.attestationsForProposal.getValuesAsync(this.getProposalKey(
|
|
152
|
+
this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
|
|
150
153
|
);
|
|
151
154
|
|
|
152
155
|
numberOfAttestations += attestations.length;
|
|
@@ -155,17 +158,19 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
await this.proposals.delete(proposalId);
|
|
158
|
-
await this.attestationsForProposal.delete(this.getProposalKey(
|
|
161
|
+
await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
|
|
159
162
|
}
|
|
160
163
|
|
|
164
|
+
// Delete from proposalsForSlot
|
|
165
|
+
await this.proposalsForSlot.delete(slot);
|
|
166
|
+
|
|
161
167
|
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
|
|
162
168
|
});
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
public async deleteAttestationsForSlotAndProposal(slot:
|
|
171
|
+
public async deleteAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<void> {
|
|
166
172
|
let numberOfAttestations = 0;
|
|
167
173
|
await this.store.transactionAsync(async () => {
|
|
168
|
-
const slotString = new Fr(slot).toString();
|
|
169
174
|
const attestations = await toArray(
|
|
170
175
|
this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
|
|
171
176
|
);
|
|
@@ -176,8 +181,8 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
176
181
|
}
|
|
177
182
|
|
|
178
183
|
await this.proposals.delete(proposalId);
|
|
179
|
-
await this.proposalsForSlot.deleteValue(
|
|
180
|
-
await this.attestationsForProposal.delete(this.getProposalKey(
|
|
184
|
+
await this.proposalsForSlot.deleteValue(slot, proposalId);
|
|
185
|
+
await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
|
|
181
186
|
|
|
182
187
|
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
|
|
183
188
|
});
|
|
@@ -192,7 +197,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
192
197
|
|
|
193
198
|
// Skip attestations with invalid signatures
|
|
194
199
|
if (!sender) {
|
|
195
|
-
this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber
|
|
200
|
+
this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber}`);
|
|
196
201
|
continue;
|
|
197
202
|
}
|
|
198
203
|
|
|
@@ -249,8 +254,45 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
249
254
|
|
|
250
255
|
public async addBlockProposal(blockProposal: BlockProposal): Promise<void> {
|
|
251
256
|
await this.store.transactionAsync(async () => {
|
|
252
|
-
|
|
253
|
-
|
|
257
|
+
const slotKey = blockProposal.slotNumber;
|
|
258
|
+
const proposalId = blockProposal.archive.toString();
|
|
259
|
+
|
|
260
|
+
if (!(await this.canAddProposal(blockProposal))) {
|
|
261
|
+
throw new ProposalSlotCapExceededError(
|
|
262
|
+
`Maximum proposals per slot reached: slot=${slotKey} cap=${MAX_PROPOSALS_PER_SLOT} proposal=${proposalId}`,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
await this.proposalsForSlot.set(slotKey, proposalId);
|
|
267
|
+
// Always update the stored proposal buffer so re-adds overwrite with latest data
|
|
268
|
+
await this.proposals.set(proposalId, blockProposal.toBuffer());
|
|
254
269
|
});
|
|
255
270
|
}
|
|
271
|
+
|
|
272
|
+
public async hasReachedProposalCap(slot: SlotNumber): Promise<boolean> {
|
|
273
|
+
const uniqueProposalCount = await this.proposalsForSlot.getValueCountAsync(slot);
|
|
274
|
+
return uniqueProposalCount >= MAX_PROPOSALS_PER_SLOT;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public async hasReachedAttestationCap(slot: SlotNumber, proposalId: string, committeeSize: number): Promise<boolean> {
|
|
278
|
+
const limit = committeeSize + ATTESTATION_CAP_BUFFER;
|
|
279
|
+
return (await this.attestationsForProposal.getValueCountAsync(this.getProposalKey(slot, proposalId))) >= limit;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
public async canAddProposal(block: BlockProposal): Promise<boolean> {
|
|
283
|
+
return (
|
|
284
|
+
(await this.proposals.hasAsync(block.archive.toString())) || !(await this.hasReachedProposalCap(block.slotNumber))
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
public async canAddAttestation(attestation: BlockAttestation, committeeSize: number): Promise<boolean> {
|
|
289
|
+
return (
|
|
290
|
+
(await this.hasAttestation(attestation)) ||
|
|
291
|
+
!(await this.hasReachedAttestationCap(
|
|
292
|
+
attestation.payload.header.slotNumber,
|
|
293
|
+
attestation.archive.toString(),
|
|
294
|
+
committeeSize,
|
|
295
|
+
))
|
|
296
|
+
);
|
|
297
|
+
}
|
|
256
298
|
}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
+
import type { SlotNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
3
|
import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
3
4
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
4
5
|
|
|
5
6
|
import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
|
|
6
7
|
import type { AttestationPool } from './attestation_pool.js';
|
|
8
|
+
import { ATTESTATION_CAP_BUFFER, MAX_PROPOSALS_PER_SLOT } from './kv_attestation_pool.js';
|
|
7
9
|
|
|
8
10
|
export class InMemoryAttestationPool implements AttestationPool {
|
|
9
11
|
private metrics: PoolInstrumentation<BlockAttestation>;
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
14
|
+
private attestations: Map<
|
|
15
|
+
/*slot=*/ SlotNumber,
|
|
16
|
+
Map</*proposalId*/ string, Map</*address=*/ string, BlockAttestation>>
|
|
17
|
+
>;
|
|
12
18
|
private proposals: Map<string, BlockProposal>;
|
|
13
19
|
|
|
14
20
|
constructor(
|
|
@@ -30,7 +36,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
30
36
|
return Promise.resolve(this.attestations.size === 0);
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
public getAttestationsForSlot(slot:
|
|
39
|
+
public getAttestationsForSlot(slot: SlotNumber): Promise<BlockAttestation[]> {
|
|
34
40
|
return Promise.resolve(
|
|
35
41
|
Array.from(this.attestations.get(slot)?.values() ?? []).flatMap(proposalAttestationMap =>
|
|
36
42
|
Array.from(proposalAttestationMap.values()),
|
|
@@ -38,7 +44,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
38
44
|
);
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
public getAttestationsForSlotAndProposal(slot:
|
|
47
|
+
public getAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<BlockAttestation[]> {
|
|
42
48
|
const slotAttestationMap = this.attestations.get(slot);
|
|
43
49
|
if (slotAttestationMap) {
|
|
44
50
|
const proposalAttestationMap = slotAttestationMap.get(proposalId);
|
|
@@ -59,7 +65,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
59
65
|
|
|
60
66
|
// Skip attestations with invalid signatures
|
|
61
67
|
if (!sender) {
|
|
62
|
-
this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber
|
|
68
|
+
this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber}`, {
|
|
63
69
|
signature: attestation.signature.toString(),
|
|
64
70
|
slotNumber,
|
|
65
71
|
proposalId,
|
|
@@ -67,11 +73,11 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
67
73
|
continue;
|
|
68
74
|
}
|
|
69
75
|
|
|
70
|
-
const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber
|
|
76
|
+
const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber);
|
|
71
77
|
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
72
78
|
proposalAttestationMap.set(sender.toString(), attestation);
|
|
73
79
|
|
|
74
|
-
this.log.verbose(`Added attestation for slot ${slotNumber
|
|
80
|
+
this.log.verbose(`Added attestation for slot ${slotNumber} from ${sender}`, {
|
|
75
81
|
signature: attestation.signature.toString(),
|
|
76
82
|
slotNumber,
|
|
77
83
|
address: sender,
|
|
@@ -82,7 +88,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
82
88
|
return Promise.resolve();
|
|
83
89
|
}
|
|
84
90
|
|
|
85
|
-
#getNumberOfAttestationsInSlot(slot:
|
|
91
|
+
#getNumberOfAttestationsInSlot(slot: SlotNumber): number {
|
|
86
92
|
let total = 0;
|
|
87
93
|
const slotAttestationMap = getSlotOrDefault(this.attestations, slot);
|
|
88
94
|
|
|
@@ -94,7 +100,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
94
100
|
return total;
|
|
95
101
|
}
|
|
96
102
|
|
|
97
|
-
public async deleteAttestationsOlderThan(oldestSlot:
|
|
103
|
+
public async deleteAttestationsOlderThan(oldestSlot: SlotNumber): Promise<void> {
|
|
98
104
|
const olderThan = [];
|
|
99
105
|
|
|
100
106
|
// Entries are iterated in insertion order, so we can break as soon as we find a slot that is older than the oldestSlot.
|
|
@@ -115,7 +121,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
115
121
|
return Promise.resolve();
|
|
116
122
|
}
|
|
117
123
|
|
|
118
|
-
public deleteAttestationsForSlot(slot:
|
|
124
|
+
public deleteAttestationsForSlot(slot: SlotNumber): Promise<void> {
|
|
119
125
|
// We count the number of attestations we are removing
|
|
120
126
|
const numberOfAttestations = this.#getNumberOfAttestationsInSlot(slot);
|
|
121
127
|
const proposalIdsToDelete = this.attestations.get(slot)?.keys();
|
|
@@ -133,7 +139,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
133
139
|
return Promise.resolve();
|
|
134
140
|
}
|
|
135
141
|
|
|
136
|
-
public deleteAttestationsForSlotAndProposal(slot:
|
|
142
|
+
public deleteAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<void> {
|
|
137
143
|
const slotAttestationMap = getSlotOrDefault(this.attestations, slot);
|
|
138
144
|
if (slotAttestationMap) {
|
|
139
145
|
if (slotAttestationMap.has(proposalId)) {
|
|
@@ -152,7 +158,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
152
158
|
public deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
153
159
|
for (const attestation of attestations) {
|
|
154
160
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
155
|
-
const slotAttestationMap = this.attestations.get(slotNumber
|
|
161
|
+
const slotAttestationMap = this.attestations.get(slotNumber);
|
|
156
162
|
if (slotAttestationMap) {
|
|
157
163
|
const proposalId = attestation.archive.toString();
|
|
158
164
|
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
@@ -161,7 +167,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
161
167
|
|
|
162
168
|
// Skip attestations with invalid signatures
|
|
163
169
|
if (!sender) {
|
|
164
|
-
this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber
|
|
170
|
+
this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber}`);
|
|
165
171
|
continue;
|
|
166
172
|
}
|
|
167
173
|
|
|
@@ -183,7 +189,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
183
189
|
return Promise.resolve(false);
|
|
184
190
|
}
|
|
185
191
|
|
|
186
|
-
const slotAttestationMap = this.attestations.get(slotNumber
|
|
192
|
+
const slotAttestationMap = this.attestations.get(slotNumber);
|
|
187
193
|
if (!slotAttestationMap) {
|
|
188
194
|
return Promise.resolve(false);
|
|
189
195
|
}
|
|
@@ -199,7 +205,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
199
205
|
public addBlockProposal(blockProposal: BlockProposal): Promise<void> {
|
|
200
206
|
// We initialize slot-proposal mapping if it does not exist
|
|
201
207
|
// This is important to ensure we can delete this proposal if there were not attestations for it
|
|
202
|
-
const slotProposalMapping = getSlotOrDefault(this.attestations, blockProposal.slotNumber
|
|
208
|
+
const slotProposalMapping = getSlotOrDefault(this.attestations, blockProposal.slotNumber);
|
|
203
209
|
slotProposalMapping.set(blockProposal.payload.archive.toString(), new Map<string, BlockAttestation>());
|
|
204
210
|
|
|
205
211
|
this.proposals.set(blockProposal.payload.archive.toString(), blockProposal);
|
|
@@ -214,6 +220,33 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
214
220
|
const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.payload.archive.toString();
|
|
215
221
|
return Promise.resolve(this.proposals.has(id));
|
|
216
222
|
}
|
|
223
|
+
|
|
224
|
+
public hasReachedProposalCap(slot: SlotNumber): Promise<boolean> {
|
|
225
|
+
const slotAttestationMap = this.attestations.get(slot);
|
|
226
|
+
const proposalCount = slotAttestationMap?.size ?? 0;
|
|
227
|
+
return Promise.resolve(proposalCount >= MAX_PROPOSALS_PER_SLOT);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
public hasReachedAttestationCap(slot: SlotNumber, proposalId: string, committeeSize: number): Promise<boolean> {
|
|
231
|
+
const limit = committeeSize + ATTESTATION_CAP_BUFFER;
|
|
232
|
+
const count = this.attestations.get(slot)?.get(proposalId)?.size ?? 0;
|
|
233
|
+
return Promise.resolve(limit <= 0 || count >= limit);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
public async canAddProposal(block: BlockProposal): Promise<boolean> {
|
|
237
|
+
return this.proposals.has(block.archive.toString()) || !(await this.hasReachedProposalCap(block.slotNumber));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public async canAddAttestation(attestation: BlockAttestation, committeeSize: number): Promise<boolean> {
|
|
241
|
+
const sender = attestation.getSender();
|
|
242
|
+
const slot = attestation.payload.header.slotNumber;
|
|
243
|
+
const pid = attestation.archive.toString();
|
|
244
|
+
return (
|
|
245
|
+
!!sender &&
|
|
246
|
+
((this.attestations.get(slot)?.get(pid)?.has(sender.toString()) ?? false) ||
|
|
247
|
+
!(await this.hasReachedAttestationCap(slot, pid, committeeSize)))
|
|
248
|
+
);
|
|
249
|
+
}
|
|
217
250
|
}
|
|
218
251
|
|
|
219
252
|
/**
|
|
@@ -225,8 +258,9 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
225
258
|
* @returns The slot mapping
|
|
226
259
|
*/
|
|
227
260
|
function getSlotOrDefault(
|
|
228
|
-
|
|
229
|
-
|
|
261
|
+
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
262
|
+
map: Map<SlotNumber, Map<string, Map<string, BlockAttestation>>>,
|
|
263
|
+
slot: SlotNumber,
|
|
230
264
|
): Map<string, Map<string, BlockAttestation>> {
|
|
231
265
|
if (!map.has(slot)) {
|
|
232
266
|
map.set(slot, new Map<string, Map<string, BlockAttestation>>());
|
|
@@ -33,7 +33,7 @@ export const mockAttestation = (
|
|
|
33
33
|
): BlockAttestation => {
|
|
34
34
|
// Use arbitrary numbers for all other than slot
|
|
35
35
|
const header = makeL2BlockHeader(1, 2, slot);
|
|
36
|
-
const payload = new ConsensusPayload(header.toCheckpointHeader(), archive
|
|
36
|
+
const payload = new ConsensusPayload(header.toCheckpointHeader(), archive);
|
|
37
37
|
|
|
38
38
|
const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
|
|
39
39
|
const attestationSignature = signer.sign(attestationHash);
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type MetricsType,
|
|
11
11
|
type ObservableGauge,
|
|
12
12
|
type TelemetryClient,
|
|
13
|
+
type UpDownCounter,
|
|
13
14
|
} from '@aztec/telemetry-client';
|
|
14
15
|
|
|
15
16
|
export enum PoolName {
|
|
@@ -20,6 +21,7 @@ export enum PoolName {
|
|
|
20
21
|
type MetricsLabels = {
|
|
21
22
|
objectInMempool: MetricsType;
|
|
22
23
|
objectSize: MetricsType;
|
|
24
|
+
itemsAdded: MetricsType;
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
/**
|
|
@@ -32,11 +34,13 @@ function getMetricsLabels(name: PoolName): MetricsLabels {
|
|
|
32
34
|
return {
|
|
33
35
|
objectInMempool: Metrics.MEMPOOL_TX_COUNT,
|
|
34
36
|
objectSize: Metrics.MEMPOOL_TX_SIZE,
|
|
37
|
+
itemsAdded: Metrics.MEMPOOL_TX_ADDED_COUNT,
|
|
35
38
|
};
|
|
36
39
|
} else if (name === PoolName.ATTESTATION_POOL) {
|
|
37
40
|
return {
|
|
38
41
|
objectInMempool: Metrics.MEMPOOL_ATTESTATIONS_COUNT,
|
|
39
42
|
objectSize: Metrics.MEMPOOL_ATTESTATIONS_SIZE,
|
|
43
|
+
itemsAdded: Metrics.MEMPOOL_ATTESTATIONS_ADDED_COUNT,
|
|
40
44
|
};
|
|
41
45
|
}
|
|
42
46
|
|
|
@@ -53,6 +57,7 @@ export type PoolStatsCallback = () => Promise<{
|
|
|
53
57
|
export class PoolInstrumentation<PoolObject extends Gossipable> {
|
|
54
58
|
/** The number of txs in the mempool */
|
|
55
59
|
private objectsInMempool: ObservableGauge;
|
|
60
|
+
private addObjectCounter: UpDownCounter;
|
|
56
61
|
/** Tracks tx size */
|
|
57
62
|
private objectSize: Histogram;
|
|
58
63
|
|
|
@@ -89,6 +94,10 @@ export class PoolInstrumentation<PoolObject extends Gossipable> {
|
|
|
89
94
|
dbStats,
|
|
90
95
|
);
|
|
91
96
|
|
|
97
|
+
this.addObjectCounter = this.meter.createUpDownCounter(metricsLabels.itemsAdded, {
|
|
98
|
+
description: 'The number of transactions added to the mempool',
|
|
99
|
+
});
|
|
100
|
+
|
|
92
101
|
this.meter.addBatchObservableCallback(this.observeStats, [this.objectsInMempool]);
|
|
93
102
|
}
|
|
94
103
|
|
|
@@ -96,6 +105,10 @@ export class PoolInstrumentation<PoolObject extends Gossipable> {
|
|
|
96
105
|
this.objectSize.record(poolObject.getSize());
|
|
97
106
|
}
|
|
98
107
|
|
|
108
|
+
public incrementAddedObjects(count: number) {
|
|
109
|
+
this.addObjectCounter.add(count);
|
|
110
|
+
}
|
|
111
|
+
|
|
99
112
|
private observeStats = async (observer: BatchObservableResult) => {
|
|
100
113
|
const { itemCount } = await this.poolStats();
|
|
101
114
|
if (typeof itemCount === 'number') {
|