@aztec/p2p 0.0.0-test.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dest/bootstrap/bootstrap.d.ts +38 -0
- package/dest/bootstrap/bootstrap.d.ts.map +1 -0
- package/dest/bootstrap/bootstrap.js +123 -0
- package/dest/client/factory.d.ts +21 -0
- package/dest/client/factory.d.ts.map +1 -0
- package/dest/client/factory.js +37 -0
- package/dest/client/index.d.ts +3 -0
- package/dest/client/index.d.ts.map +1 -0
- package/dest/client/index.js +2 -0
- package/dest/client/p2p_client.d.ts +314 -0
- package/dest/client/p2p_client.d.ts.map +1 -0
- package/dest/client/p2p_client.js +505 -0
- package/dest/config.d.ts +180 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +193 -0
- package/dest/enr/generate-enr.d.ts +9 -0
- package/dest/enr/generate-enr.d.ts.map +1 -0
- package/dest/enr/generate-enr.js +30 -0
- package/dest/enr/index.d.ts +2 -0
- package/dest/enr/index.d.ts.map +1 -0
- package/dest/enr/index.js +1 -0
- package/dest/errors/reqresp.error.d.ts +28 -0
- package/dest/errors/reqresp.error.d.ts.map +1 -0
- package/dest/errors/reqresp.error.js +30 -0
- package/dest/index.d.ts +8 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +7 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +57 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.js +6 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +3 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +195 -0
- package/dest/mem_pools/attestation_pool/index.d.ts +3 -0
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/index.js +2 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +22 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +112 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +129 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts +19 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/mocks.js +33 -0
- package/dest/mem_pools/index.d.ts +4 -0
- package/dest/mem_pools/index.d.ts.map +1 -0
- package/dest/mem_pools/index.js +1 -0
- package/dest/mem_pools/instrumentation.d.ts +30 -0
- package/dest/mem_pools/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/instrumentation.js +84 -0
- package/dest/mem_pools/interface.d.ts +11 -0
- package/dest/mem_pools/interface.d.ts.map +1 -0
- package/dest/mem_pools/interface.js +3 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +66 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +245 -0
- package/dest/mem_pools/tx_pool/index.d.ts +4 -0
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/index.js +3 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +56 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +141 -0
- package/dest/mem_pools/tx_pool/priority.d.ts +8 -0
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/priority.js +10 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +66 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool.js +3 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +7 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +169 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +8 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.js +19 -0
- package/dest/msg_validators/attestation_validator/index.d.ts +2 -0
- package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/index.js +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +8 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts +2 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/index.js +1 -0
- package/dest/msg_validators/index.d.ts +4 -0
- package/dest/msg_validators/index.d.ts.map +1 -0
- package/dest/msg_validators/index.js +3 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +7 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +31 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +11 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/block_header_validator.js +26 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +6 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/data_validator.js +107 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +12 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.js +41 -0
- package/dest/msg_validators/tx_validator/index.d.ts +7 -0
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/index.js +6 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +10 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/metadata_validator.js +44 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +25 -0
- package/dest/services/data_store.d.ts +27 -0
- package/dest/services/data_store.d.ts.map +1 -0
- package/dest/services/data_store.js +188 -0
- package/dest/services/discv5/discV5_service.d.ts +42 -0
- package/dest/services/discv5/discV5_service.d.ts.map +1 -0
- package/dest/services/discv5/discV5_service.js +214 -0
- package/dest/services/dummy_service.d.ts +85 -0
- package/dest/services/dummy_service.d.ts.map +1 -0
- package/dest/services/dummy_service.js +92 -0
- package/dest/services/encoding.d.ts +31 -0
- package/dest/services/encoding.d.ts.map +1 -0
- package/dest/services/encoding.js +66 -0
- package/dest/services/gossipsub/scoring.d.ts +7 -0
- package/dest/services/gossipsub/scoring.d.ts.map +1 -0
- package/dest/services/gossipsub/scoring.js +10 -0
- package/dest/services/index.d.ts +3 -0
- package/dest/services/index.d.ts.map +1 -0
- package/dest/services/index.js +2 -0
- package/dest/services/libp2p/libp2p_service.d.ts +186 -0
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
- package/dest/services/libp2p/libp2p_service.js +712 -0
- package/dest/services/peer-manager/metrics.d.ts +12 -0
- package/dest/services/peer-manager/metrics.d.ts.map +1 -0
- package/dest/services/peer-manager/metrics.js +33 -0
- package/dest/services/peer-manager/peer_manager.d.ts +94 -0
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_manager.js +445 -0
- package/dest/services/peer-manager/peer_scoring.d.ts +28 -0
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_scoring.js +86 -0
- package/dest/services/reqresp/config.d.ts +16 -0
- package/dest/services/reqresp/config.d.ts.map +1 -0
- package/dest/services/reqresp/config.js +20 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +45 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +88 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +61 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +181 -0
- package/dest/services/reqresp/index.d.ts +6 -0
- package/dest/services/reqresp/index.d.ts.map +1 -0
- package/dest/services/reqresp/index.js +4 -0
- package/dest/services/reqresp/interface.d.ts +116 -0
- package/dest/services/reqresp/interface.d.ts.map +1 -0
- package/dest/services/reqresp/interface.js +84 -0
- package/dest/services/reqresp/metrics.d.ts +15 -0
- package/dest/services/reqresp/metrics.d.ts.map +1 -0
- package/dest/services/reqresp/metrics.js +55 -0
- package/dest/services/reqresp/protocols/block.d.ts +4 -0
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block.js +8 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts +51 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/goodbye.js +87 -0
- package/dest/services/reqresp/protocols/index.d.ts +9 -0
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/index.js +7 -0
- package/dest/services/reqresp/protocols/ping.d.ts +9 -0
- package/dest/services/reqresp/protocols/ping.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/ping.js +7 -0
- package/dest/services/reqresp/protocols/status.d.ts +9 -0
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/status.js +7 -0
- package/dest/services/reqresp/protocols/tx.d.ts +13 -0
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts +2 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/index.js +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +102 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +184 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +3 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.js +54 -0
- package/dest/services/reqresp/reqresp.d.ts +166 -0
- package/dest/services/reqresp/reqresp.d.ts.map +1 -0
- package/dest/services/reqresp/reqresp.js +516 -0
- package/dest/services/reqresp/status.d.ts +31 -0
- package/dest/services/reqresp/status.d.ts.map +1 -0
- package/dest/services/reqresp/status.js +51 -0
- package/dest/services/service.d.ts +87 -0
- package/dest/services/service.d.ts.map +1 -0
- package/dest/services/service.js +5 -0
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts +7 -0
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts.map +1 -0
- package/dest/test-helpers/generate-peer-id-private-keys.js +13 -0
- package/dest/test-helpers/get-ports.d.ts +7 -0
- package/dest/test-helpers/get-ports.d.ts.map +1 -0
- package/dest/test-helpers/get-ports.js +8 -0
- package/dest/test-helpers/index.d.ts +6 -0
- package/dest/test-helpers/index.d.ts.map +1 -0
- package/dest/test-helpers/index.js +5 -0
- package/dest/test-helpers/make-enrs.d.ts +16 -0
- package/dest/test-helpers/make-enrs.d.ts.map +1 -0
- package/dest/test-helpers/make-enrs.js +32 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts +36 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -0
- package/dest/test-helpers/make-test-p2p-clients.js +68 -0
- package/dest/test-helpers/reqresp-nodes.d.ts +66 -0
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -0
- package/dest/test-helpers/reqresp-nodes.js +207 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -0
- package/dest/testbench/p2p_client_testbench_worker.js +132 -0
- package/dest/testbench/parse_log_file.d.ts +2 -0
- package/dest/testbench/parse_log_file.d.ts.map +1 -0
- package/dest/testbench/parse_log_file.js +131 -0
- package/dest/testbench/testbench.d.ts +2 -0
- package/dest/testbench/testbench.d.ts.map +1 -0
- package/dest/testbench/testbench.js +61 -0
- package/dest/testbench/worker_client_manager.d.ts +56 -0
- package/dest/testbench/worker_client_manager.d.ts.map +1 -0
- package/dest/testbench/worker_client_manager.js +266 -0
- package/dest/types/index.d.ts +32 -0
- package/dest/types/index.d.ts.map +1 -0
- package/dest/types/index.js +28 -0
- package/dest/util.d.ts +53 -0
- package/dest/util.d.ts.map +1 -0
- package/dest/util.js +140 -0
- package/dest/versioning.d.ts +12 -0
- package/dest/versioning.d.ts.map +1 -0
- package/dest/versioning.js +33 -0
- package/package.json +127 -0
- package/src/bootstrap/bootstrap.ts +146 -0
- package/src/client/factory.ts +89 -0
- package/src/client/index.ts +2 -0
- package/src/client/p2p_client.ts +754 -0
- package/src/config.ts +371 -0
- package/src/enr/generate-enr.ts +39 -0
- package/src/enr/index.ts +1 -0
- package/src/errors/reqresp.error.ts +35 -0
- package/src/index.ts +7 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +62 -0
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +230 -0
- package/src/mem_pools/attestation_pool/index.ts +2 -0
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +159 -0
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +161 -0
- package/src/mem_pools/attestation_pool/mocks.ts +44 -0
- package/src/mem_pools/index.ts +3 -0
- package/src/mem_pools/instrumentation.ts +126 -0
- package/src/mem_pools/interface.ts +12 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +309 -0
- package/src/mem_pools/tx_pool/index.ts +3 -0
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +174 -0
- package/src/mem_pools/tx_pool/priority.ts +13 -0
- package/src/mem_pools/tx_pool/tx_pool.ts +76 -0
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +130 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +29 -0
- package/src/msg_validators/block_proposal_validator/index.ts +1 -0
- package/src/msg_validators/index.ts +3 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +32 -0
- package/src/msg_validators/tx_validator/block_header_validator.ts +25 -0
- package/src/msg_validators/tx_validator/data_validator.ts +106 -0
- package/src/msg_validators/tx_validator/double_spend_validator.ts +38 -0
- package/src/msg_validators/tx_validator/index.ts +6 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +48 -0
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +18 -0
- package/src/services/data_store.ts +235 -0
- package/src/services/discv5/discV5_service.ts +256 -0
- package/src/services/dummy_service.ts +134 -0
- package/src/services/encoding.ts +79 -0
- package/src/services/gossipsub/scoring.ts +13 -0
- package/src/services/index.ts +2 -0
- package/src/services/libp2p/libp2p_service.ts +871 -0
- package/src/services/peer-manager/metrics.ts +41 -0
- package/src/services/peer-manager/peer_manager.ts +530 -0
- package/src/services/peer-manager/peer_scoring.ts +105 -0
- package/src/services/reqresp/config.ts +35 -0
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +94 -0
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +217 -0
- package/src/services/reqresp/index.ts +4 -0
- package/src/services/reqresp/interface.ts +185 -0
- package/src/services/reqresp/metrics.ts +57 -0
- package/src/services/reqresp/protocols/block.ts +15 -0
- package/src/services/reqresp/protocols/goodbye.ts +101 -0
- package/src/services/reqresp/protocols/index.ts +8 -0
- package/src/services/reqresp/protocols/ping.ts +8 -0
- package/src/services/reqresp/protocols/status.ts +8 -0
- package/src/services/reqresp/protocols/tx.ts +29 -0
- package/src/services/reqresp/rate-limiter/index.ts +1 -0
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +228 -0
- package/src/services/reqresp/rate-limiter/rate_limits.ts +55 -0
- package/src/services/reqresp/reqresp.ts +661 -0
- package/src/services/reqresp/status.ts +59 -0
- package/src/services/service.ts +112 -0
- package/src/test-helpers/generate-peer-id-private-keys.ts +15 -0
- package/src/test-helpers/get-ports.ts +8 -0
- package/src/test-helpers/index.ts +5 -0
- package/src/test-helpers/make-enrs.ts +44 -0
- package/src/test-helpers/make-test-p2p-clients.ts +122 -0
- package/src/test-helpers/reqresp-nodes.ts +289 -0
- package/src/testbench/README.md +20 -0
- package/src/testbench/p2p_client_testbench_worker.ts +152 -0
- package/src/testbench/parse_log_file.ts +175 -0
- package/src/testbench/testbench.ts +66 -0
- package/src/testbench/worker_client_manager.ts +318 -0
- package/src/types/index.ts +36 -0
- package/src/util.ts +196 -0
- package/src/versioning.ts +50 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { Secp256k1Signer } from '@aztec/foundation/crypto';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import type { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
4
|
+
import { TxHash } from '@aztec/stdlib/tx';
|
|
5
|
+
|
|
6
|
+
import { jest } from '@jest/globals';
|
|
7
|
+
import { type MockProxy, mock } from 'jest-mock-extended';
|
|
8
|
+
|
|
9
|
+
import type { PoolInstrumentation } from '../instrumentation.js';
|
|
10
|
+
import type { AttestationPool } from './attestation_pool.js';
|
|
11
|
+
import { mockAttestation } from './mocks.js';
|
|
12
|
+
|
|
13
|
+
const NUMBER_OF_SIGNERS_PER_TEST = 4;
|
|
14
|
+
|
|
15
|
+
export function describeAttestationPool(getAttestationPool: () => AttestationPool) {
|
|
16
|
+
let ap: AttestationPool;
|
|
17
|
+
let signers: Secp256k1Signer[];
|
|
18
|
+
|
|
19
|
+
// Check that metrics are recorded correctly
|
|
20
|
+
let metricsMock: MockProxy<PoolInstrumentation<BlockAttestation>>;
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
ap = getAttestationPool();
|
|
24
|
+
signers = Array.from({ length: NUMBER_OF_SIGNERS_PER_TEST }, () => Secp256k1Signer.random());
|
|
25
|
+
|
|
26
|
+
metricsMock = mock<PoolInstrumentation<BlockAttestation>>();
|
|
27
|
+
// Can i overwrite this like this??
|
|
28
|
+
(ap as any).metrics = metricsMock;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const createAttestationsForSlot = (slotNumber: number) => {
|
|
32
|
+
const archive = Fr.random();
|
|
33
|
+
return Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// We compare buffers as the objects can have cached values attached to them which are not serialised
|
|
37
|
+
// using array containing as the kv store does not respect insertion order
|
|
38
|
+
const compareAttestations = (a1: BlockAttestation[], a2: BlockAttestation[]) => {
|
|
39
|
+
const a1Buffer = a1.map(attestation => attestation.toBuffer());
|
|
40
|
+
const a2Buffer = a2.map(attestation => attestation.toBuffer());
|
|
41
|
+
expect(a1Buffer.length).toBe(a2Buffer.length);
|
|
42
|
+
expect(a1Buffer).toEqual(expect.arrayContaining(a2Buffer));
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
it('should add attestations to pool', async () => {
|
|
46
|
+
const slotNumber = 420;
|
|
47
|
+
const archive = Fr.random();
|
|
48
|
+
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
|
|
49
|
+
|
|
50
|
+
await ap.addAttestations(attestations);
|
|
51
|
+
|
|
52
|
+
// Check metrics have been updated.
|
|
53
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations.length);
|
|
54
|
+
|
|
55
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
|
|
56
|
+
|
|
57
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
58
|
+
|
|
59
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
60
|
+
|
|
61
|
+
// Delete by slot
|
|
62
|
+
await ap.deleteAttestationsForSlot(BigInt(slotNumber));
|
|
63
|
+
|
|
64
|
+
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledWith(attestations.length);
|
|
65
|
+
|
|
66
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
|
|
67
|
+
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('Should handle duplicate proposals in a slot', async () => {
|
|
71
|
+
const slotNumber = 420;
|
|
72
|
+
const archive = Fr.random();
|
|
73
|
+
const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
|
|
74
|
+
|
|
75
|
+
// Use the same signer for all attestations
|
|
76
|
+
const attestations: BlockAttestation[] = [];
|
|
77
|
+
const signer = signers[0];
|
|
78
|
+
for (let i = 0; i < NUMBER_OF_SIGNERS_PER_TEST; i++) {
|
|
79
|
+
attestations.push(await mockAttestation(signer, slotNumber, archive, txs));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await ap.addAttestations(attestations);
|
|
83
|
+
|
|
84
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
|
|
85
|
+
expect(retreivedAttestations.length).toBe(1);
|
|
86
|
+
expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
|
|
87
|
+
expect(retreivedAttestations[0].payload.txHashes).toEqual(txs);
|
|
88
|
+
expect((await retreivedAttestations[0].getSender()).toString()).toEqual(signer.address.toString());
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('Should store attestations by differing slot', async () => {
|
|
92
|
+
const slotNumbers = [1, 2, 3, 4];
|
|
93
|
+
const attestations = await Promise.all(signers.map((signer, i) => mockAttestation(signer, slotNumbers[i])));
|
|
94
|
+
|
|
95
|
+
await ap.addAttestations(attestations);
|
|
96
|
+
|
|
97
|
+
for (const attestation of attestations) {
|
|
98
|
+
const slot = attestation.payload.header.globalVariables.slotNumber;
|
|
99
|
+
const archive = attestation.archive.toString();
|
|
100
|
+
|
|
101
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), archive);
|
|
102
|
+
expect(retreivedAttestations.length).toBe(1);
|
|
103
|
+
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
104
|
+
expect(retreivedAttestations[0].payload.header.globalVariables.slotNumber).toEqual(slot);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('Should store attestations by differing slot and archive', async () => {
|
|
109
|
+
const slotNumbers = [1, 1, 2, 3];
|
|
110
|
+
const archives = [Fr.random(), Fr.random(), Fr.random(), Fr.random()];
|
|
111
|
+
const attestations = await Promise.all(
|
|
112
|
+
signers.map((signer, i) => mockAttestation(signer, slotNumbers[i], archives[i])),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
await ap.addAttestations(attestations);
|
|
116
|
+
|
|
117
|
+
for (const attestation of attestations) {
|
|
118
|
+
const slot = attestation.payload.header.globalVariables.slotNumber;
|
|
119
|
+
const proposalId = attestation.archive.toString();
|
|
120
|
+
|
|
121
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), proposalId);
|
|
122
|
+
expect(retreivedAttestations.length).toBe(1);
|
|
123
|
+
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
124
|
+
expect(retreivedAttestations[0].payload.header.globalVariables.slotNumber).toEqual(slot);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('Should delete attestations', async () => {
|
|
129
|
+
const slotNumber = 420;
|
|
130
|
+
const archive = Fr.random();
|
|
131
|
+
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
|
|
132
|
+
const proposalId = attestations[0].archive.toString();
|
|
133
|
+
|
|
134
|
+
await ap.addAttestations(attestations);
|
|
135
|
+
|
|
136
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations.length);
|
|
137
|
+
|
|
138
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
139
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
140
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
141
|
+
|
|
142
|
+
await ap.deleteAttestations(attestations);
|
|
143
|
+
|
|
144
|
+
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledWith(attestations.length);
|
|
145
|
+
|
|
146
|
+
const gottenAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
147
|
+
expect(gottenAfterDelete.length).toBe(0);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('Should blanket delete attestations per slot', async () => {
|
|
151
|
+
const slotNumber = 420;
|
|
152
|
+
const archive = Fr.random();
|
|
153
|
+
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
|
|
154
|
+
const proposalId = attestations[0].archive.toString();
|
|
155
|
+
|
|
156
|
+
await ap.addAttestations(attestations);
|
|
157
|
+
|
|
158
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
159
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
160
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
161
|
+
|
|
162
|
+
await ap.deleteAttestationsForSlot(BigInt(slotNumber));
|
|
163
|
+
|
|
164
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
165
|
+
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('Should blanket delete attestations per slot and proposal', async () => {
|
|
169
|
+
const slotNumber = 420;
|
|
170
|
+
const archive = Fr.random();
|
|
171
|
+
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
|
|
172
|
+
const proposalId = attestations[0].archive.toString();
|
|
173
|
+
|
|
174
|
+
// Add another set of attestations with a different proposalId, yet the same slot
|
|
175
|
+
const archive2 = Fr.random();
|
|
176
|
+
const attestations2 = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive2)));
|
|
177
|
+
const proposalId2 = attestations2[0].archive.toString();
|
|
178
|
+
|
|
179
|
+
await ap.addAttestations(attestations);
|
|
180
|
+
await ap.addAttestations(attestations2);
|
|
181
|
+
|
|
182
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations.length);
|
|
183
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations2.length);
|
|
184
|
+
|
|
185
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
186
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
187
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
188
|
+
|
|
189
|
+
await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
|
|
190
|
+
|
|
191
|
+
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledWith(attestations.length);
|
|
192
|
+
|
|
193
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
194
|
+
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
195
|
+
|
|
196
|
+
const retreivedAttestationsAfterDeleteForOtherProposal = await ap.getAttestationsForSlot(
|
|
197
|
+
BigInt(slotNumber),
|
|
198
|
+
proposalId2,
|
|
199
|
+
);
|
|
200
|
+
expect(retreivedAttestationsAfterDeleteForOtherProposal.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
201
|
+
compareAttestations(retreivedAttestationsAfterDeleteForOtherProposal, attestations2);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('Should delete attestations older than a given slot', async () => {
|
|
205
|
+
const slotNumbers = [1, 2, 3, 69, 72, 74, 88, 420];
|
|
206
|
+
const attestations = (
|
|
207
|
+
await Promise.all(slotNumbers.map(slotNumber => createAttestationsForSlot(slotNumber)))
|
|
208
|
+
).flat();
|
|
209
|
+
const proposalId = attestations[0].archive.toString();
|
|
210
|
+
|
|
211
|
+
await ap.addAttestations(attestations);
|
|
212
|
+
|
|
213
|
+
const attestationsForSlot1 = await ap.getAttestationsForSlot(BigInt(1), proposalId);
|
|
214
|
+
expect(attestationsForSlot1.length).toBe(signers.length);
|
|
215
|
+
|
|
216
|
+
const deleteAttestationsSpy = jest.spyOn(ap, 'deleteAttestationsForSlot');
|
|
217
|
+
|
|
218
|
+
await ap.deleteAttestationsOlderThan(BigInt(73));
|
|
219
|
+
|
|
220
|
+
const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlot(BigInt(1), proposalId);
|
|
221
|
+
expect(attestationsForSlot1AfterDelete.length).toBe(0);
|
|
222
|
+
|
|
223
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledTimes(5);
|
|
224
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(1));
|
|
225
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(2));
|
|
226
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(3));
|
|
227
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(69));
|
|
228
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(72));
|
|
229
|
+
});
|
|
230
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { toArray } from '@aztec/foundation/iterable';
|
|
3
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
|
|
5
|
+
import { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
6
|
+
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
7
|
+
|
|
8
|
+
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
9
|
+
import type { AttestationPool } from './attestation_pool.js';
|
|
10
|
+
|
|
11
|
+
export class KvAttestationPool implements AttestationPool {
|
|
12
|
+
private metrics: PoolInstrumentation<BlockAttestation>;
|
|
13
|
+
|
|
14
|
+
private attestations: AztecAsyncMap<string, Buffer>;
|
|
15
|
+
private proposalsForSlot: AztecAsyncMultiMap<string, string>;
|
|
16
|
+
private attestationsForProposal: AztecAsyncMultiMap<string, string>;
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
private store: AztecAsyncKVStore,
|
|
20
|
+
telemetry: TelemetryClient = getTelemetryClient(),
|
|
21
|
+
private log = createLogger('aztec:attestation_pool'),
|
|
22
|
+
) {
|
|
23
|
+
this.attestations = store.openMap('attestations');
|
|
24
|
+
this.proposalsForSlot = store.openMultiMap('proposals_for_slot');
|
|
25
|
+
this.attestationsForProposal = store.openMultiMap('attestations_for_proposal');
|
|
26
|
+
|
|
27
|
+
this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private getProposalKey(slot: number | bigint | Fr | string, proposalId: Fr | string | Buffer): string {
|
|
31
|
+
const slotStr = typeof slot === 'string' ? slot : new Fr(slot).toString();
|
|
32
|
+
const proposalIdStr =
|
|
33
|
+
typeof proposalId === 'string'
|
|
34
|
+
? proposalId
|
|
35
|
+
: Buffer.isBuffer(proposalId)
|
|
36
|
+
? Fr.fromBuffer(proposalId).toString()
|
|
37
|
+
: proposalId.toString();
|
|
38
|
+
|
|
39
|
+
return `${slotStr}-${proposalIdStr}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private getAttestationKey(slot: number | bigint | Fr | string, proposalId: Fr | string, address: string): string {
|
|
43
|
+
return `${this.getProposalKey(slot, proposalId)}-${address}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public async addAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
47
|
+
await this.store.transactionAsync(async () => {
|
|
48
|
+
for (const attestation of attestations) {
|
|
49
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
50
|
+
const proposalId = attestation.archive;
|
|
51
|
+
const address = (await attestation.getSender()).toString();
|
|
52
|
+
|
|
53
|
+
await this.attestations.set(this.getAttestationKey(slotNumber, proposalId, address), attestation.toBuffer());
|
|
54
|
+
|
|
55
|
+
await this.proposalsForSlot.set(slotNumber.toString(), proposalId.toString());
|
|
56
|
+
await this.attestationsForProposal.set(
|
|
57
|
+
this.getProposalKey(slotNumber, proposalId),
|
|
58
|
+
this.getAttestationKey(slotNumber, proposalId, address),
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
this.metrics.recordAddedObjects(attestations.length);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public async getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
|
|
69
|
+
const attestationIds = await toArray(
|
|
70
|
+
this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
|
|
71
|
+
);
|
|
72
|
+
const attestations: BlockAttestation[] = [];
|
|
73
|
+
|
|
74
|
+
// alternatively iterate this.attestaions starting from slot-proposal-EthAddress.zero
|
|
75
|
+
for (const id of attestationIds) {
|
|
76
|
+
const buf = await this.attestations.getAsync(id);
|
|
77
|
+
|
|
78
|
+
if (!buf) {
|
|
79
|
+
// this should not happen unless we lost writes
|
|
80
|
+
throw new Error('Attestation not found ' + id);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const attestation = BlockAttestation.fromBuffer(buf);
|
|
84
|
+
attestations.push(attestation);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return attestations;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public async deleteAttestationsOlderThan(oldestSlot: bigint): Promise<void> {
|
|
91
|
+
const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end: new Fr(oldestSlot).toString() }));
|
|
92
|
+
for (const oldSlot of olderThan) {
|
|
93
|
+
await this.deleteAttestationsForSlot(BigInt(oldSlot));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public async deleteAttestationsForSlot(slot: bigint): Promise<void> {
|
|
98
|
+
const slotFr = new Fr(slot);
|
|
99
|
+
let numberOfAttestations = 0;
|
|
100
|
+
await this.store.transactionAsync(async () => {
|
|
101
|
+
const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slotFr.toString()));
|
|
102
|
+
for (const proposalId of proposalIds) {
|
|
103
|
+
const attestations = await toArray(
|
|
104
|
+
this.attestationsForProposal.getValuesAsync(this.getProposalKey(slotFr, proposalId)),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
numberOfAttestations += attestations.length;
|
|
108
|
+
for (const attestation of attestations) {
|
|
109
|
+
await this.attestations.delete(attestation);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
await this.attestationsForProposal.delete(this.getProposalKey(slotFr, proposalId));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
|
|
117
|
+
this.metrics.recordRemovedObjects(numberOfAttestations);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public async deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
|
|
121
|
+
let numberOfAttestations = 0;
|
|
122
|
+
await this.store.transactionAsync(async () => {
|
|
123
|
+
const slotString = new Fr(slot).toString();
|
|
124
|
+
const attestations = await toArray(
|
|
125
|
+
this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
numberOfAttestations += attestations.length;
|
|
129
|
+
for (const attestation of attestations) {
|
|
130
|
+
await this.attestations.delete(attestation);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
await this.proposalsForSlot.deleteValue(slotString, proposalId);
|
|
134
|
+
await this.attestationsForProposal.delete(this.getProposalKey(slotString, proposalId));
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
|
|
138
|
+
this.metrics.recordRemovedObjects(numberOfAttestations);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public async deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
142
|
+
await this.store.transactionAsync(async () => {
|
|
143
|
+
for (const attestation of attestations) {
|
|
144
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
145
|
+
const proposalId = attestation.archive;
|
|
146
|
+
const address = (await attestation.getSender()).toString();
|
|
147
|
+
|
|
148
|
+
await this.attestations.delete(this.getAttestationKey(slotNumber, proposalId, address));
|
|
149
|
+
await this.attestationsForProposal.deleteValue(
|
|
150
|
+
this.getProposalKey(slotNumber, proposalId),
|
|
151
|
+
this.getAttestationKey(slotNumber, proposalId, address),
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
this.metrics.recordRemovedObjects(attestations.length);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import type { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
3
|
+
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
4
|
+
|
|
5
|
+
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
6
|
+
import type { AttestationPool } from './attestation_pool.js';
|
|
7
|
+
|
|
8
|
+
export class InMemoryAttestationPool implements AttestationPool {
|
|
9
|
+
private metrics: PoolInstrumentation<BlockAttestation>;
|
|
10
|
+
|
|
11
|
+
private attestations: Map</*slot=*/ bigint, Map</*proposalId*/ string, Map</*address=*/ string, BlockAttestation>>>;
|
|
12
|
+
|
|
13
|
+
constructor(telemetry: TelemetryClient = getTelemetryClient(), private log = createLogger('p2p:attestation_pool')) {
|
|
14
|
+
this.attestations = new Map();
|
|
15
|
+
this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
|
|
19
|
+
const slotAttestationMap = this.attestations.get(slot);
|
|
20
|
+
if (slotAttestationMap) {
|
|
21
|
+
const proposalAttestationMap = slotAttestationMap.get(proposalId);
|
|
22
|
+
if (proposalAttestationMap) {
|
|
23
|
+
return Promise.resolve(Array.from(proposalAttestationMap.values()));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return Promise.resolve([]);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public async addAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
30
|
+
for (const attestation of attestations) {
|
|
31
|
+
// Perf: order and group by slot before insertion
|
|
32
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
33
|
+
|
|
34
|
+
const proposalId = attestation.archive.toString();
|
|
35
|
+
const address = await attestation.getSender();
|
|
36
|
+
|
|
37
|
+
const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt());
|
|
38
|
+
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
39
|
+
proposalAttestationMap.set(address.toString(), attestation);
|
|
40
|
+
|
|
41
|
+
this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// TODO: set these to pending or something ????
|
|
45
|
+
this.metrics.recordAddedObjects(attestations.length);
|
|
46
|
+
return Promise.resolve();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#getNumberOfAttestationsInSlot(slot: bigint): number {
|
|
50
|
+
let total = 0;
|
|
51
|
+
const slotAttestationMap = getSlotOrDefault(this.attestations, slot);
|
|
52
|
+
|
|
53
|
+
if (slotAttestationMap) {
|
|
54
|
+
for (const proposalAttestationMap of slotAttestationMap.values() ?? []) {
|
|
55
|
+
total += proposalAttestationMap.size;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return total;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async deleteAttestationsOlderThan(oldestSlot: bigint): Promise<void> {
|
|
62
|
+
const olderThan = [];
|
|
63
|
+
|
|
64
|
+
// Entries are iterated in insertion order, so we can break as soon as we find a slot that is older than the oldestSlot.
|
|
65
|
+
// Note: this will only prune correctly if attestations are added in order of rising slot, it is important that we do not allow
|
|
66
|
+
// insertion of attestations that are old. #(https://github.com/AztecProtocol/aztec-packages/issues/10322)
|
|
67
|
+
const slots = this.attestations.keys();
|
|
68
|
+
for (const slot of slots) {
|
|
69
|
+
if (slot < oldestSlot) {
|
|
70
|
+
olderThan.push(slot);
|
|
71
|
+
} else {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for (const oldSlot of olderThan) {
|
|
77
|
+
await this.deleteAttestationsForSlot(oldSlot);
|
|
78
|
+
}
|
|
79
|
+
return Promise.resolve();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public deleteAttestationsForSlot(slot: bigint): Promise<void> {
|
|
83
|
+
// We count the number of attestations we are removing
|
|
84
|
+
const numberOfAttestations = this.#getNumberOfAttestationsInSlot(slot);
|
|
85
|
+
|
|
86
|
+
this.attestations.delete(slot);
|
|
87
|
+
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
|
|
88
|
+
|
|
89
|
+
this.metrics.recordRemovedObjects(numberOfAttestations);
|
|
90
|
+
return Promise.resolve();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
|
|
94
|
+
const slotAttestationMap = getSlotOrDefault(this.attestations, slot);
|
|
95
|
+
if (slotAttestationMap) {
|
|
96
|
+
if (slotAttestationMap.has(proposalId)) {
|
|
97
|
+
const numberOfAttestations = slotAttestationMap.get(proposalId)?.size ?? 0;
|
|
98
|
+
|
|
99
|
+
slotAttestationMap.delete(proposalId);
|
|
100
|
+
|
|
101
|
+
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
|
|
102
|
+
this.metrics.recordRemovedObjects(numberOfAttestations);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return Promise.resolve();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public async deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
109
|
+
for (const attestation of attestations) {
|
|
110
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
111
|
+
const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
|
|
112
|
+
if (slotAttestationMap) {
|
|
113
|
+
const proposalId = attestation.archive.toString();
|
|
114
|
+
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
115
|
+
if (proposalAttestationMap) {
|
|
116
|
+
const address = await attestation.getSender();
|
|
117
|
+
proposalAttestationMap.delete(address.toString());
|
|
118
|
+
this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
this.metrics.recordRemovedObjects(attestations.length);
|
|
123
|
+
return Promise.resolve();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get Slot or Default
|
|
129
|
+
*
|
|
130
|
+
* Fetch the slot mapping, if it does not exist, then create a mapping and return it
|
|
131
|
+
* @param map - The map to fetch from
|
|
132
|
+
* @param slot - The slot to fetch
|
|
133
|
+
* @returns The slot mapping
|
|
134
|
+
*/
|
|
135
|
+
function getSlotOrDefault(
|
|
136
|
+
map: Map<bigint, Map<string, Map<string, BlockAttestation>>>,
|
|
137
|
+
slot: bigint,
|
|
138
|
+
): Map<string, Map<string, BlockAttestation>> {
|
|
139
|
+
if (!map.has(slot)) {
|
|
140
|
+
map.set(slot, new Map<string, Map<string, BlockAttestation>>());
|
|
141
|
+
}
|
|
142
|
+
return map.get(slot)!;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get Proposal or Default
|
|
147
|
+
*
|
|
148
|
+
* Fetch the proposal mapping, if it does not exist, then create a mapping and return it
|
|
149
|
+
* @param map - The map to fetch from
|
|
150
|
+
* @param proposalId - The proposal id to fetch
|
|
151
|
+
* @returns The proposal mapping
|
|
152
|
+
*/
|
|
153
|
+
function getProposalOrDefault(
|
|
154
|
+
map: Map<string, Map<string, BlockAttestation>>,
|
|
155
|
+
proposalId: string,
|
|
156
|
+
): Map<string, BlockAttestation> {
|
|
157
|
+
if (!map.has(proposalId)) {
|
|
158
|
+
map.set(proposalId, new Map<string, BlockAttestation>());
|
|
159
|
+
}
|
|
160
|
+
return map.get(proposalId)!;
|
|
161
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Secp256k1Signer } from '@aztec/foundation/crypto';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import {
|
|
4
|
+
BlockAttestation,
|
|
5
|
+
ConsensusPayload,
|
|
6
|
+
SignatureDomainSeparator,
|
|
7
|
+
getHashedSignaturePayloadEthSignedMessage,
|
|
8
|
+
} from '@aztec/stdlib/p2p';
|
|
9
|
+
import { makeHeader } from '@aztec/stdlib/testing';
|
|
10
|
+
import { TxHash } from '@aztec/stdlib/tx';
|
|
11
|
+
|
|
12
|
+
import { type LocalAccount, generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
13
|
+
|
|
14
|
+
/** Generate Account
|
|
15
|
+
*
|
|
16
|
+
* Create a random signer
|
|
17
|
+
* @returns A random viem signer
|
|
18
|
+
*/
|
|
19
|
+
export const generateAccount = (): LocalAccount => {
|
|
20
|
+
const privateKey = generatePrivateKey();
|
|
21
|
+
return privateKeyToAccount(privateKey);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** Mock Attestation
|
|
25
|
+
*
|
|
26
|
+
* @param signer A viem signer to create a signature
|
|
27
|
+
* @param slot The slot number the attestation is for
|
|
28
|
+
* @returns A Block Attestation
|
|
29
|
+
*/
|
|
30
|
+
export const mockAttestation = async (
|
|
31
|
+
signer: Secp256k1Signer,
|
|
32
|
+
slot: number = 0,
|
|
33
|
+
archive: Fr = Fr.random(),
|
|
34
|
+
txs: TxHash[] = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()),
|
|
35
|
+
): Promise<BlockAttestation> => {
|
|
36
|
+
// Use arbitrary numbers for all other than slot
|
|
37
|
+
const header = makeHeader(1, 2, slot);
|
|
38
|
+
const payload = new ConsensusPayload(header, archive, txs);
|
|
39
|
+
|
|
40
|
+
const hash = await getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
|
|
41
|
+
const signature = signer.sign(hash);
|
|
42
|
+
|
|
43
|
+
return new BlockAttestation(payload, signature);
|
|
44
|
+
};
|