@aztec/p2p 0.66.0 → 0.67.1-devnet
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 +4 -1
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +21 -9
- package/dest/client/index.d.ts +5 -4
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +18 -12
- package/dest/client/p2p_client.d.ts +13 -20
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +32 -15
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +2 -2
- package/dest/errors/reqresp.error.d.ts +12 -1
- package/dest/errors/reqresp.error.d.ts.map +1 -1
- package/dest/errors/reqresp.error.js +15 -2
- package/dest/index.d.ts +1 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -2
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +9 -0
- 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 +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 +171 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +29 -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 +114 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +3 -3
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +2 -20
- package/dest/mem_pools/interface.d.ts +4 -3
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +4 -4
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +4 -4
- package/dest/mocks/index.d.ts +6 -6
- package/dest/mocks/index.d.ts.map +1 -1
- package/dest/mocks/index.js +9 -9
- package/dest/services/data_store.d.ts.map +1 -0
- package/dest/services/data_store.js +188 -0
- package/dest/{service → services/discv5}/discV5_service.d.ts +4 -2
- package/dest/services/discv5/discV5_service.d.ts.map +1 -0
- package/dest/services/discv5/discV5_service.js +144 -0
- package/dest/{service → services}/dummy_service.d.ts +3 -1
- package/dest/services/dummy_service.d.ts.map +1 -0
- package/dest/{service → services}/dummy_service.js +5 -1
- package/dest/{service → services}/encoding.d.ts +5 -0
- package/dest/services/encoding.d.ts.map +1 -0
- package/dest/services/encoding.js +65 -0
- package/dest/services/index.d.ts +3 -0
- package/dest/services/index.d.ts.map +1 -0
- package/dest/services/index.js +3 -0
- package/dest/{service → services/libp2p}/libp2p_service.d.ts +50 -11
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
- package/dest/services/libp2p/libp2p_service.js +573 -0
- package/dest/{service → services/peer-scoring}/peer_scoring.d.ts +5 -2
- package/dest/services/peer-scoring/peer_scoring.d.ts.map +1 -0
- package/dest/services/peer-scoring/peer_scoring.js +72 -0
- package/dest/{service → services}/peer_manager.d.ts +8 -3
- package/dest/services/peer_manager.d.ts.map +1 -0
- package/dest/services/peer_manager.js +230 -0
- package/dest/services/reqresp/config.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/config.js +1 -1
- package/dest/services/reqresp/handlers.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/handlers.js +1 -1
- package/dest/services/reqresp/index.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/index.js +1 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/interface.js +1 -1
- package/dest/services/reqresp/rate_limiter/index.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/rate_limiter/index.js +1 -1
- package/dest/services/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/rate_limiter/rate_limiter.js +2 -2
- package/dest/services/reqresp/rate_limiter/rate_limits.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/rate_limiter/rate_limits.js +1 -1
- package/dest/{service → services}/reqresp/reqresp.d.ts +16 -0
- package/dest/services/reqresp/reqresp.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/reqresp.js +69 -20
- package/dest/{service → services}/service.d.ts +2 -1
- package/dest/services/service.d.ts.map +1 -0
- package/dest/{service → services}/service.js +1 -1
- package/dest/tx_validator/aggregate_tx_validator.d.ts +1 -1
- package/dest/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/tx_validator/aggregate_tx_validator.js +5 -3
- package/dest/tx_validator/data_validator.js +3 -3
- package/dest/tx_validator/double_spend_validator.d.ts +3 -2
- package/dest/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/tx_validator/double_spend_validator.js +8 -8
- package/dest/tx_validator/metadata_validator.js +3 -3
- package/dest/tx_validator/tx_proof_validator.js +3 -3
- package/package.json +12 -8
- package/src/bootstrap/bootstrap.ts +24 -10
- package/src/client/index.ts +44 -19
- package/src/client/p2p_client.ts +58 -36
- package/src/config.ts +1 -1
- package/src/errors/reqresp.error.ts +15 -1
- package/src/index.ts +1 -1
- package/src/mem_pools/attestation_pool/attestation_pool.ts +10 -0
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +237 -0
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +153 -0
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +2 -2
- package/src/mem_pools/instrumentation.ts +1 -21
- package/src/mem_pools/interface.ts +5 -3
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +3 -3
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +3 -3
- package/src/mocks/index.ts +14 -11
- package/src/{service → services/discv5}/discV5_service.ts +20 -15
- package/src/{service → services}/dummy_service.ts +6 -1
- package/src/{service → services}/encoding.ts +21 -3
- package/src/services/index.ts +2 -0
- package/src/{service → services/libp2p}/libp2p_service.ts +208 -96
- package/src/{service → services/peer-scoring}/peer_scoring.ts +9 -2
- package/src/{service → services}/peer_manager.ts +73 -24
- package/src/{service → services}/reqresp/rate_limiter/rate_limiter.ts +1 -1
- package/src/{service → services}/reqresp/reqresp.ts +87 -21
- package/src/{service → services}/service.ts +3 -1
- package/src/tx_validator/aggregate_tx_validator.ts +5 -3
- package/src/tx_validator/data_validator.ts +2 -2
- package/src/tx_validator/double_spend_validator.ts +8 -10
- package/src/tx_validator/metadata_validator.ts +2 -2
- package/src/tx_validator/tx_proof_validator.ts +2 -2
- package/dest/service/data_store.d.ts.map +0 -1
- package/dest/service/data_store.js +0 -188
- package/dest/service/discV5_service.d.ts.map +0 -1
- package/dest/service/discV5_service.js +0 -141
- package/dest/service/dummy_service.d.ts.map +0 -1
- package/dest/service/encoding.d.ts.map +0 -1
- package/dest/service/encoding.js +0 -49
- package/dest/service/index.d.ts +0 -3
- package/dest/service/index.d.ts.map +0 -1
- package/dest/service/index.js +0 -3
- package/dest/service/libp2p_service.d.ts.map +0 -1
- package/dest/service/libp2p_service.js +0 -496
- package/dest/service/peer_manager.d.ts.map +0 -1
- package/dest/service/peer_manager.js +0 -176
- package/dest/service/peer_scoring.d.ts.map +0 -1
- package/dest/service/peer_scoring.js +0 -67
- package/dest/service/reqresp/config.d.ts.map +0 -1
- package/dest/service/reqresp/handlers.d.ts.map +0 -1
- package/dest/service/reqresp/index.d.ts.map +0 -1
- package/dest/service/reqresp/interface.d.ts.map +0 -1
- package/dest/service/reqresp/rate_limiter/index.d.ts.map +0 -1
- package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts.map +0 -1
- package/dest/service/reqresp/rate_limiter/rate_limits.d.ts.map +0 -1
- package/dest/service/reqresp/reqresp.d.ts.map +0 -1
- package/dest/service/service.d.ts.map +0 -1
- package/src/service/index.ts +0 -2
- /package/dest/{service → services}/data_store.d.ts +0 -0
- /package/dest/{service → services}/reqresp/config.d.ts +0 -0
- /package/dest/{service → services}/reqresp/handlers.d.ts +0 -0
- /package/dest/{service → services}/reqresp/index.d.ts +0 -0
- /package/dest/{service → services}/reqresp/interface.d.ts +0 -0
- /package/dest/{service → services}/reqresp/rate_limiter/index.d.ts +0 -0
- /package/dest/{service → services}/reqresp/rate_limiter/rate_limiter.d.ts +0 -0
- /package/dest/{service → services}/reqresp/rate_limiter/rate_limits.d.ts +0 -0
- /package/src/{service → services}/data_store.ts +0 -0
- /package/src/{service → services}/reqresp/config.ts +0 -0
- /package/src/{service → services}/reqresp/handlers.ts +0 -0
- /package/src/{service → services}/reqresp/index.ts +0 -0
- /package/src/{service → services}/reqresp/interface.ts +0 -0
- /package/src/{service → services}/reqresp/rate_limiter/index.ts +0 -0
- /package/src/{service → services}/reqresp/rate_limiter/rate_limits.ts +0 -0
package/src/client/index.ts
CHANGED
|
@@ -1,51 +1,66 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
type ClientProtocolCircuitVerifier,
|
|
3
|
+
type L2BlockSource,
|
|
4
|
+
P2PClientType,
|
|
5
|
+
type WorldStateSynchronizer,
|
|
6
|
+
} from '@aztec/circuit-types';
|
|
7
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
8
|
import { type AztecKVStore } from '@aztec/kv-store';
|
|
4
9
|
import { type DataStoreConfig } from '@aztec/kv-store/config';
|
|
5
|
-
import { createStore } from '@aztec/kv-store/
|
|
10
|
+
import { createStore } from '@aztec/kv-store/lmdb';
|
|
6
11
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
7
12
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
8
13
|
|
|
9
14
|
import { P2PClient } from '../client/p2p_client.js';
|
|
10
15
|
import { type P2PConfig } from '../config.js';
|
|
11
16
|
import { type AttestationPool } from '../mem_pools/attestation_pool/attestation_pool.js';
|
|
12
|
-
import {
|
|
17
|
+
import { KvAttestationPool } from '../mem_pools/attestation_pool/kv_attestation_pool.js';
|
|
13
18
|
import { type EpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
14
19
|
import { MemoryEpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js';
|
|
15
20
|
import { type MemPools } from '../mem_pools/interface.js';
|
|
16
21
|
import { AztecKVTxPool, type TxPool } from '../mem_pools/tx_pool/index.js';
|
|
17
|
-
import { DiscV5Service } from '../
|
|
18
|
-
import { DummyP2PService } from '../
|
|
19
|
-
import { LibP2PService } from '../
|
|
22
|
+
import { DiscV5Service } from '../services/discv5/discV5_service.js';
|
|
23
|
+
import { DummyP2PService } from '../services/dummy_service.js';
|
|
24
|
+
import { LibP2PService } from '../services/index.js';
|
|
20
25
|
import { configureP2PClientAddresses, createLibP2PPeerIdFromPrivateKey, getPeerIdPrivateKey } from '../util.js';
|
|
21
26
|
|
|
22
27
|
export * from './p2p_client.js';
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
type P2PClientDeps<T extends P2PClientType> = {
|
|
30
|
+
txPool?: TxPool;
|
|
31
|
+
store?: AztecKVStore;
|
|
32
|
+
attestationPool?: T extends P2PClientType.Full ? AttestationPool : undefined;
|
|
33
|
+
epochProofQuotePool?: EpochProofQuotePool;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const createP2PClient = async <T extends P2PClientType>(
|
|
37
|
+
clientType: T,
|
|
25
38
|
_config: P2PConfig & DataStoreConfig,
|
|
26
39
|
l2BlockSource: L2BlockSource,
|
|
27
40
|
proofVerifier: ClientProtocolCircuitVerifier,
|
|
28
41
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
29
42
|
telemetry: TelemetryClient = new NoopTelemetryClient(),
|
|
30
|
-
deps: {
|
|
31
|
-
txPool?: TxPool;
|
|
32
|
-
store?: AztecKVStore;
|
|
33
|
-
attestationPool?: AttestationPool;
|
|
34
|
-
epochProofQuotePool?: EpochProofQuotePool;
|
|
35
|
-
} = {},
|
|
43
|
+
deps: P2PClientDeps<T> = {},
|
|
36
44
|
) => {
|
|
37
45
|
let config = { ..._config };
|
|
38
|
-
const
|
|
46
|
+
const logger = createLogger('p2p');
|
|
47
|
+
const store = deps.store ?? (await createStore('p2p', config, createLogger('p2p:lmdb')));
|
|
39
48
|
|
|
40
|
-
const mempools: MemPools = {
|
|
49
|
+
const mempools: MemPools<T> = {
|
|
41
50
|
txPool: deps.txPool ?? new AztecKVTxPool(store, telemetry),
|
|
42
|
-
attestationPool: deps.attestationPool ?? new InMemoryAttestationPool(telemetry),
|
|
43
51
|
epochProofQuotePool: deps.epochProofQuotePool ?? new MemoryEpochProofQuotePool(telemetry),
|
|
52
|
+
attestationPool:
|
|
53
|
+
clientType === P2PClientType.Full
|
|
54
|
+
? ((deps.attestationPool ?? new KvAttestationPool(store, telemetry)) as T extends P2PClientType.Full
|
|
55
|
+
? AttestationPool
|
|
56
|
+
: undefined)
|
|
57
|
+
: undefined,
|
|
44
58
|
};
|
|
45
59
|
|
|
46
60
|
let p2pService;
|
|
47
61
|
|
|
48
62
|
if (_config.p2pEnabled) {
|
|
63
|
+
logger.verbose('P2P is enabled. Using LibP2P service.');
|
|
49
64
|
config = await configureP2PClientAddresses(_config);
|
|
50
65
|
|
|
51
66
|
// Create peer discovery service
|
|
@@ -53,7 +68,8 @@ export const createP2PClient = async (
|
|
|
53
68
|
const peerId = await createLibP2PPeerIdFromPrivateKey(peerIdPrivateKey);
|
|
54
69
|
const discoveryService = new DiscV5Service(peerId, config, telemetry);
|
|
55
70
|
|
|
56
|
-
p2pService = await LibP2PService.new(
|
|
71
|
+
p2pService = await LibP2PService.new<T>(
|
|
72
|
+
clientType,
|
|
57
73
|
config,
|
|
58
74
|
discoveryService,
|
|
59
75
|
peerId,
|
|
@@ -65,7 +81,16 @@ export const createP2PClient = async (
|
|
|
65
81
|
telemetry,
|
|
66
82
|
);
|
|
67
83
|
} else {
|
|
84
|
+
logger.verbose('P2P is disabled. Using dummy P2P service');
|
|
68
85
|
p2pService = new DummyP2PService();
|
|
69
86
|
}
|
|
70
|
-
return new P2PClient(
|
|
87
|
+
return new P2PClient(
|
|
88
|
+
clientType,
|
|
89
|
+
store,
|
|
90
|
+
l2BlockSource,
|
|
91
|
+
mempools,
|
|
92
|
+
p2pService,
|
|
93
|
+
config.keepProvenTxsInPoolFor,
|
|
94
|
+
telemetry,
|
|
95
|
+
);
|
|
71
96
|
};
|
package/src/client/p2p_client.ts
CHANGED
|
@@ -5,16 +5,24 @@ import {
|
|
|
5
5
|
type L2Block,
|
|
6
6
|
type L2BlockId,
|
|
7
7
|
type L2BlockSource,
|
|
8
|
-
L2BlockStream,
|
|
9
8
|
type L2BlockStreamEvent,
|
|
10
9
|
type L2Tips,
|
|
10
|
+
type P2PApi,
|
|
11
|
+
type P2PClientType,
|
|
12
|
+
type PeerInfo,
|
|
11
13
|
type Tx,
|
|
12
14
|
type TxHash,
|
|
13
15
|
} from '@aztec/circuit-types';
|
|
14
16
|
import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
|
|
15
|
-
import {
|
|
17
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
16
18
|
import { type AztecKVStore, type AztecMap, type AztecSingleton } from '@aztec/kv-store';
|
|
17
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
Attributes,
|
|
21
|
+
type TelemetryClient,
|
|
22
|
+
TraceableL2BlockStream,
|
|
23
|
+
WithTracer,
|
|
24
|
+
trackSpan,
|
|
25
|
+
} from '@aztec/telemetry-client';
|
|
18
26
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
19
27
|
|
|
20
28
|
import { type ENR } from '@chainsafe/enr';
|
|
@@ -24,8 +32,8 @@ import { type AttestationPool } from '../mem_pools/attestation_pool/attestation_
|
|
|
24
32
|
import { type EpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
25
33
|
import { type MemPools } from '../mem_pools/interface.js';
|
|
26
34
|
import { type TxPool } from '../mem_pools/tx_pool/index.js';
|
|
27
|
-
import { TX_REQ_PROTOCOL } from '../
|
|
28
|
-
import type { P2PService } from '../
|
|
35
|
+
import { TX_REQ_PROTOCOL } from '../services/reqresp/interface.js';
|
|
36
|
+
import type { P2PService } from '../services/service.js';
|
|
29
37
|
|
|
30
38
|
/**
|
|
31
39
|
* Enum defining the possible states of the p2p client.
|
|
@@ -54,7 +62,7 @@ export interface P2PSyncState {
|
|
|
54
62
|
/**
|
|
55
63
|
* Interface of a P2P client.
|
|
56
64
|
**/
|
|
57
|
-
export
|
|
65
|
+
export type P2P<T extends P2PClientType = P2PClientType.Full> = P2PApi<T> & {
|
|
58
66
|
/**
|
|
59
67
|
* Broadcasts a block proposal to other peers.
|
|
60
68
|
*
|
|
@@ -62,15 +70,6 @@ export interface P2P {
|
|
|
62
70
|
*/
|
|
63
71
|
broadcastProposal(proposal: BlockProposal): void;
|
|
64
72
|
|
|
65
|
-
/**
|
|
66
|
-
* Queries the Attestation pool for attestations for the given slot
|
|
67
|
-
*
|
|
68
|
-
* @param slot - the slot to query
|
|
69
|
-
* @param proposalId - the proposal id to query
|
|
70
|
-
* @returns BlockAttestations
|
|
71
|
-
*/
|
|
72
|
-
getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]>;
|
|
73
|
-
|
|
74
73
|
/**
|
|
75
74
|
* Queries the EpochProofQuote pool for quotes for the given epoch
|
|
76
75
|
*
|
|
@@ -122,12 +121,6 @@ export interface P2P {
|
|
|
122
121
|
**/
|
|
123
122
|
deleteTxs(txHashes: TxHash[]): Promise<void>;
|
|
124
123
|
|
|
125
|
-
/**
|
|
126
|
-
* Returns all transactions in the transaction pool.
|
|
127
|
-
* @returns An array of Txs.
|
|
128
|
-
*/
|
|
129
|
-
getTxs(filter: 'all' | 'pending' | 'mined'): Tx[];
|
|
130
|
-
|
|
131
124
|
/**
|
|
132
125
|
* Returns a transaction in the transaction pool by its hash.
|
|
133
126
|
* @param txHash - Hash of tx to return.
|
|
@@ -173,15 +166,21 @@ export interface P2P {
|
|
|
173
166
|
getStatus(): Promise<P2PSyncState>;
|
|
174
167
|
|
|
175
168
|
/**
|
|
176
|
-
* Returns the ENR
|
|
169
|
+
* Returns the ENR of this node, if any.
|
|
177
170
|
*/
|
|
178
171
|
getEnr(): ENR | undefined;
|
|
179
|
-
|
|
172
|
+
|
|
173
|
+
/** Identifies a p2p client. */
|
|
174
|
+
isP2PClient(): true;
|
|
175
|
+
};
|
|
180
176
|
|
|
181
177
|
/**
|
|
182
178
|
* The P2P client implementation.
|
|
183
179
|
*/
|
|
184
|
-
export class P2PClient extends
|
|
180
|
+
export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
181
|
+
extends WithTracer
|
|
182
|
+
implements P2P, P2P<P2PClientType.Prover>
|
|
183
|
+
{
|
|
185
184
|
/** Property that indicates whether the client is running. */
|
|
186
185
|
private stopping = false;
|
|
187
186
|
|
|
@@ -199,7 +198,7 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
199
198
|
private synchedProvenBlockNumber: AztecSingleton<number>;
|
|
200
199
|
|
|
201
200
|
private txPool: TxPool;
|
|
202
|
-
private attestationPool: AttestationPool;
|
|
201
|
+
private attestationPool: T extends P2PClientType.Full ? AttestationPool : undefined;
|
|
203
202
|
private epochProofQuotePool: EpochProofQuotePool;
|
|
204
203
|
|
|
205
204
|
/** How many slots to keep attestations for. */
|
|
@@ -217,13 +216,14 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
217
216
|
* @param log - A logger.
|
|
218
217
|
*/
|
|
219
218
|
constructor(
|
|
219
|
+
clientType: T,
|
|
220
220
|
store: AztecKVStore,
|
|
221
221
|
private l2BlockSource: L2BlockSource,
|
|
222
|
-
mempools: MemPools
|
|
222
|
+
mempools: MemPools<T>,
|
|
223
223
|
private p2pService: P2PService,
|
|
224
224
|
private keepProvenTxsFor: number,
|
|
225
225
|
telemetry: TelemetryClient = new NoopTelemetryClient(),
|
|
226
|
-
private log =
|
|
226
|
+
private log = createLogger('p2p'),
|
|
227
227
|
) {
|
|
228
228
|
super(telemetry, 'P2PClient');
|
|
229
229
|
|
|
@@ -231,7 +231,9 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
231
231
|
|
|
232
232
|
this.keepAttestationsInPoolFor = keepAttestationsInPoolFor;
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
const tracer = telemetry.getTracer('P2PL2BlockStream');
|
|
235
|
+
const logger = createLogger('p2p:l2-block-stream');
|
|
236
|
+
this.blockStream = new TraceableL2BlockStream(l2BlockSource, this, this, tracer, 'P2PL2BlockStream', logger, {
|
|
235
237
|
batchSize: blockRequestBatchSize,
|
|
236
238
|
pollIntervalMS: blockCheckIntervalMS,
|
|
237
239
|
});
|
|
@@ -241,8 +243,16 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
241
243
|
this.synchedProvenBlockNumber = store.openSingleton('p2p_pool_last_proven_l2_block');
|
|
242
244
|
|
|
243
245
|
this.txPool = mempools.txPool;
|
|
244
|
-
this.attestationPool = mempools.attestationPool;
|
|
245
246
|
this.epochProofQuotePool = mempools.epochProofQuotePool;
|
|
247
|
+
this.attestationPool = mempools.attestationPool!;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public isP2PClient(): true {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
public getPeers(includePending?: boolean): Promise<PeerInfo[]> {
|
|
255
|
+
return Promise.resolve(this.p2pService.getPeers(includePending));
|
|
246
256
|
}
|
|
247
257
|
|
|
248
258
|
public getL2BlockHash(number: number): Promise<string | undefined> {
|
|
@@ -361,7 +371,7 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
361
371
|
this.setCurrentState(P2PClientState.RUNNING);
|
|
362
372
|
this.syncPromise = Promise.resolve();
|
|
363
373
|
await this.p2pService.start();
|
|
364
|
-
this.log.
|
|
374
|
+
this.log.debug(`Block ${syncedLatestBlock} (proven ${syncedProvenBlock}) already beyond current block`);
|
|
365
375
|
}
|
|
366
376
|
|
|
367
377
|
// publish any txs in TxPool after its doing initial sync
|
|
@@ -401,7 +411,7 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
401
411
|
}
|
|
402
412
|
|
|
403
413
|
public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
|
|
404
|
-
return Promise.resolve(this.attestationPool
|
|
414
|
+
return Promise.resolve(this.attestationPool?.getAttestationsForSlot(slot, proposalId) ?? []);
|
|
405
415
|
}
|
|
406
416
|
|
|
407
417
|
// REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
@@ -436,14 +446,20 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
436
446
|
public async requestTxByHash(txHash: TxHash): Promise<Tx | undefined> {
|
|
437
447
|
const tx = await this.p2pService.sendRequest(TX_REQ_PROTOCOL, txHash);
|
|
438
448
|
|
|
439
|
-
this.log.debug(`Requested ${txHash.toString()} from peer | success = ${!!tx}`);
|
|
440
449
|
if (tx) {
|
|
450
|
+
this.log.debug(`Received tx ${txHash.toString()} from peer`);
|
|
441
451
|
await this.txPool.addTxs([tx]);
|
|
452
|
+
} else {
|
|
453
|
+
this.log.debug(`Failed to receive tx ${txHash.toString()} from peer`);
|
|
442
454
|
}
|
|
443
455
|
|
|
444
456
|
return tx;
|
|
445
457
|
}
|
|
446
458
|
|
|
459
|
+
public getPendingTxs(): Promise<Tx[]> {
|
|
460
|
+
return Promise.resolve(this.getTxs('pending'));
|
|
461
|
+
}
|
|
462
|
+
|
|
447
463
|
/**
|
|
448
464
|
* Returns all transactions in the transaction pool.
|
|
449
465
|
* @returns An array of Txs.
|
|
@@ -514,6 +530,10 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
514
530
|
return this.p2pService.getEnr();
|
|
515
531
|
}
|
|
516
532
|
|
|
533
|
+
public getEncodedEnr(): Promise<string | undefined> {
|
|
534
|
+
return Promise.resolve(this.p2pService.getEnr()?.encodeTxt());
|
|
535
|
+
}
|
|
536
|
+
|
|
517
537
|
/**
|
|
518
538
|
* Deletes the 'txs' from the pool.
|
|
519
539
|
* NOT used if we use sendTx as reconcileTxPool will handle this.
|
|
@@ -636,16 +656,17 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
636
656
|
// We delete attestations older than the last block slot minus the number of slots we want to keep in the pool.
|
|
637
657
|
const lastBlockSlotMinusKeepAttestationsInPoolFor = lastBlockSlot - BigInt(this.keepAttestationsInPoolFor);
|
|
638
658
|
if (lastBlockSlotMinusKeepAttestationsInPoolFor >= BigInt(INITIAL_L2_BLOCK_NUM)) {
|
|
639
|
-
await this.attestationPool
|
|
659
|
+
await this.attestationPool?.deleteAttestationsOlderThan(lastBlockSlotMinusKeepAttestationsInPoolFor);
|
|
640
660
|
}
|
|
641
661
|
|
|
642
|
-
await this.synchedProvenBlockNumber.set(lastBlockNum);
|
|
643
|
-
this.log.debug(`Synched to proven block ${lastBlockNum}`);
|
|
644
662
|
const provenEpochNumber = await this.l2BlockSource.getProvenL2EpochNumber();
|
|
645
663
|
if (provenEpochNumber !== undefined) {
|
|
646
664
|
this.epochProofQuotePool.deleteQuotesToEpoch(BigInt(provenEpochNumber));
|
|
647
665
|
}
|
|
648
666
|
|
|
667
|
+
await this.synchedProvenBlockNumber.set(lastBlockNum);
|
|
668
|
+
this.log.debug(`Synched to proven block ${lastBlockNum}`);
|
|
669
|
+
|
|
649
670
|
await this.startServiceIfSynched();
|
|
650
671
|
}
|
|
651
672
|
|
|
@@ -709,8 +730,9 @@ export class P2PClient extends WithTracer implements P2P {
|
|
|
709
730
|
* @param newState - New state value.
|
|
710
731
|
*/
|
|
711
732
|
private setCurrentState(newState: P2PClientState) {
|
|
733
|
+
const oldState = this.currentState;
|
|
712
734
|
this.currentState = newState;
|
|
713
|
-
this.log.debug(`Moved
|
|
735
|
+
this.log.debug(`Moved from state ${P2PClientState[oldState]} to ${P2PClientState[this.currentState]}`);
|
|
714
736
|
}
|
|
715
737
|
|
|
716
738
|
private async publishStoredTxs() {
|
package/src/config.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '@aztec/foundation/config';
|
|
9
9
|
import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
|
|
10
10
|
|
|
11
|
-
import { type P2PReqRespConfig, p2pReqRespConfigMappings } from './
|
|
11
|
+
import { type P2PReqRespConfig, p2pReqRespConfigMappings } from './services/reqresp/config.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* P2P client configuration values.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* This error will be thrown when a request to a specific peer times out.
|
|
4
4
|
* @category Errors
|
|
5
5
|
*/
|
|
6
|
-
export class
|
|
6
|
+
export class IndividualReqRespTimeoutError extends Error {
|
|
7
7
|
constructor() {
|
|
8
8
|
super(`Request to peer timed out`);
|
|
9
9
|
}
|
|
@@ -19,3 +19,17 @@ export class CollectiveReqRespTimeoutError extends Error {
|
|
|
19
19
|
super(`Request to all peers timed out`);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
/** Invalid response error
|
|
24
|
+
*
|
|
25
|
+
* This error will be thrown when a response is received that is not valid.
|
|
26
|
+
*
|
|
27
|
+
* This error does not need to be punished as message validators will handle punishing invalid
|
|
28
|
+
* requests
|
|
29
|
+
* @category Errors
|
|
30
|
+
*/
|
|
31
|
+
export class InvalidResponseError extends Error {
|
|
32
|
+
constructor() {
|
|
33
|
+
super(`Invalid response received`);
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,6 @@ export * from './bootstrap/bootstrap.js';
|
|
|
3
3
|
export * from './client/index.js';
|
|
4
4
|
export * from './config.js';
|
|
5
5
|
export * from './mem_pools/epoch_proof_quote_pool/index.js';
|
|
6
|
-
export * from './
|
|
6
|
+
export * from './services/index.js';
|
|
7
7
|
export * from './mem_pools/tx_pool/index.js';
|
|
8
8
|
export * from './tx_validator/index.js';
|
|
@@ -39,6 +39,16 @@ export interface AttestationPool {
|
|
|
39
39
|
*/
|
|
40
40
|
deleteAttestationsForSlot(slot: bigint): Promise<void>;
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Delete Attestations for slot and proposal
|
|
44
|
+
*
|
|
45
|
+
* Removes all attestations associated with a slot and proposal
|
|
46
|
+
*
|
|
47
|
+
* @param slot - The slot to delete.
|
|
48
|
+
* @param proposalId - The proposal to delete.
|
|
49
|
+
*/
|
|
50
|
+
deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void>;
|
|
51
|
+
|
|
42
52
|
/**
|
|
43
53
|
* Get Attestations for slot
|
|
44
54
|
*
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { type BlockAttestation, TxHash } from '@aztec/circuit-types';
|
|
2
|
+
import { Secp256k1Signer } from '@aztec/foundation/crypto';
|
|
3
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
4
|
+
|
|
5
|
+
import { jest } from '@jest/globals';
|
|
6
|
+
import { type MockProxy, mock } from 'jest-mock-extended';
|
|
7
|
+
|
|
8
|
+
import { type PoolInstrumentation } from '../instrumentation.js';
|
|
9
|
+
import { type AttestationPool } from './attestation_pool.js';
|
|
10
|
+
import { mockAttestation } from './mocks.js';
|
|
11
|
+
|
|
12
|
+
const NUMBER_OF_SIGNERS_PER_TEST = 4;
|
|
13
|
+
|
|
14
|
+
export function describeAttestationPool(getAttestationPool: () => AttestationPool) {
|
|
15
|
+
let ap: AttestationPool;
|
|
16
|
+
let signers: Secp256k1Signer[];
|
|
17
|
+
|
|
18
|
+
// Check that metrics are recorded correctly
|
|
19
|
+
let metricsMock: MockProxy<PoolInstrumentation<BlockAttestation>>;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
ap = getAttestationPool();
|
|
23
|
+
signers = Array.from({ length: NUMBER_OF_SIGNERS_PER_TEST }, () => Secp256k1Signer.random());
|
|
24
|
+
|
|
25
|
+
metricsMock = mock<PoolInstrumentation<BlockAttestation>>();
|
|
26
|
+
// Can i overwrite this like this??
|
|
27
|
+
(ap as any).metrics = metricsMock;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const createAttestationsForSlot = (slotNumber: number) => {
|
|
31
|
+
const archive = Fr.random();
|
|
32
|
+
return signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// We compare buffers as the objects can have cached values attached to them which are not serialised
|
|
36
|
+
// using array containing as the kv store does not respect insertion order
|
|
37
|
+
const compareAttestations = (a1: BlockAttestation[], a2: BlockAttestation[]) => {
|
|
38
|
+
const a1Buffer = a1.map(attestation => attestation.toBuffer());
|
|
39
|
+
const a2Buffer = a2.map(attestation => attestation.toBuffer());
|
|
40
|
+
expect(a1Buffer.length).toBe(a2Buffer.length);
|
|
41
|
+
expect(a1Buffer).toEqual(expect.arrayContaining(a2Buffer));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
it('should add attestations to pool', async () => {
|
|
45
|
+
const slotNumber = 420;
|
|
46
|
+
const archive = Fr.random();
|
|
47
|
+
const attestations = signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
48
|
+
|
|
49
|
+
await ap.addAttestations(attestations);
|
|
50
|
+
|
|
51
|
+
// Check metrics have been updated.
|
|
52
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations.length);
|
|
53
|
+
|
|
54
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
|
|
55
|
+
|
|
56
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
57
|
+
|
|
58
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
59
|
+
|
|
60
|
+
// Delete by slot
|
|
61
|
+
await ap.deleteAttestationsForSlot(BigInt(slotNumber));
|
|
62
|
+
|
|
63
|
+
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledWith(attestations.length);
|
|
64
|
+
|
|
65
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
|
|
66
|
+
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('Should handle duplicate proposals in a slot', async () => {
|
|
70
|
+
const slotNumber = 420;
|
|
71
|
+
const archive = Fr.random();
|
|
72
|
+
const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
|
|
73
|
+
|
|
74
|
+
// Use the same signer for all attestations
|
|
75
|
+
const attestations: BlockAttestation[] = [];
|
|
76
|
+
const signer = signers[0];
|
|
77
|
+
for (let i = 0; i < NUMBER_OF_SIGNERS_PER_TEST; i++) {
|
|
78
|
+
attestations.push(mockAttestation(signer, slotNumber, archive, txs));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await ap.addAttestations(attestations);
|
|
82
|
+
|
|
83
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), archive.toString());
|
|
84
|
+
expect(retreivedAttestations.length).toBe(1);
|
|
85
|
+
expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
|
|
86
|
+
expect(retreivedAttestations[0].payload.txHashes).toEqual(txs);
|
|
87
|
+
expect(retreivedAttestations[0].getSender().toString()).toEqual(signer.address.toString());
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('Should store attestations by differing slot', async () => {
|
|
91
|
+
const slotNumbers = [1, 2, 3, 4];
|
|
92
|
+
const attestations = signers.map((signer, i) => mockAttestation(signer, slotNumbers[i]));
|
|
93
|
+
|
|
94
|
+
await ap.addAttestations(attestations);
|
|
95
|
+
|
|
96
|
+
for (const attestation of attestations) {
|
|
97
|
+
const slot = attestation.payload.header.globalVariables.slotNumber;
|
|
98
|
+
const archive = attestation.archive.toString();
|
|
99
|
+
|
|
100
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), archive);
|
|
101
|
+
expect(retreivedAttestations.length).toBe(1);
|
|
102
|
+
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
103
|
+
expect(retreivedAttestations[0].payload.header.globalVariables.slotNumber).toEqual(slot);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('Should store attestations by differing slot and archive', async () => {
|
|
108
|
+
const slotNumbers = [1, 1, 2, 3];
|
|
109
|
+
const archives = [Fr.random(), Fr.random(), Fr.random(), Fr.random()];
|
|
110
|
+
const attestations = signers.map((signer, i) => mockAttestation(signer, slotNumbers[i], archives[i]));
|
|
111
|
+
|
|
112
|
+
await ap.addAttestations(attestations);
|
|
113
|
+
|
|
114
|
+
for (const attestation of attestations) {
|
|
115
|
+
const slot = attestation.payload.header.globalVariables.slotNumber;
|
|
116
|
+
const proposalId = attestation.archive.toString();
|
|
117
|
+
|
|
118
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), proposalId);
|
|
119
|
+
expect(retreivedAttestations.length).toBe(1);
|
|
120
|
+
expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
|
|
121
|
+
expect(retreivedAttestations[0].payload.header.globalVariables.slotNumber).toEqual(slot);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('Should delete attestations', async () => {
|
|
126
|
+
const slotNumber = 420;
|
|
127
|
+
const archive = Fr.random();
|
|
128
|
+
const attestations = signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
129
|
+
const proposalId = attestations[0].archive.toString();
|
|
130
|
+
|
|
131
|
+
await ap.addAttestations(attestations);
|
|
132
|
+
|
|
133
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations.length);
|
|
134
|
+
|
|
135
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
136
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
137
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
138
|
+
|
|
139
|
+
await ap.deleteAttestations(attestations);
|
|
140
|
+
|
|
141
|
+
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledWith(attestations.length);
|
|
142
|
+
|
|
143
|
+
const gottenAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
144
|
+
expect(gottenAfterDelete.length).toBe(0);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('Should blanket delete attestations per slot', async () => {
|
|
148
|
+
const slotNumber = 420;
|
|
149
|
+
const archive = Fr.random();
|
|
150
|
+
const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive)));
|
|
151
|
+
const proposalId = attestations[0].archive.toString();
|
|
152
|
+
|
|
153
|
+
await ap.addAttestations(attestations);
|
|
154
|
+
|
|
155
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
156
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
157
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
158
|
+
|
|
159
|
+
await ap.deleteAttestationsForSlot(BigInt(slotNumber));
|
|
160
|
+
|
|
161
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
162
|
+
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('Should blanket delete attestations per slot and proposal', async () => {
|
|
166
|
+
const slotNumber = 420;
|
|
167
|
+
const archive = Fr.random();
|
|
168
|
+
const attestations = signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
169
|
+
const proposalId = attestations[0].archive.toString();
|
|
170
|
+
|
|
171
|
+
// Add another set of attestations with a different proposalId, yet the same slot
|
|
172
|
+
const archive2 = Fr.random();
|
|
173
|
+
const attestations2 = signers.map(signer => mockAttestation(signer, slotNumber, archive2));
|
|
174
|
+
const proposalId2 = attestations2[0].archive.toString();
|
|
175
|
+
|
|
176
|
+
await ap.addAttestations(attestations);
|
|
177
|
+
await ap.addAttestations(attestations2);
|
|
178
|
+
|
|
179
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations.length);
|
|
180
|
+
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(attestations2.length);
|
|
181
|
+
|
|
182
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
183
|
+
expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
184
|
+
compareAttestations(retreivedAttestations, attestations);
|
|
185
|
+
|
|
186
|
+
await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
|
|
187
|
+
|
|
188
|
+
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledWith(attestations.length);
|
|
189
|
+
|
|
190
|
+
const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
191
|
+
expect(retreivedAttestationsAfterDelete.length).toBe(0);
|
|
192
|
+
|
|
193
|
+
const retreivedAttestationsAfterDeleteForOtherProposal = await ap.getAttestationsForSlot(
|
|
194
|
+
BigInt(slotNumber),
|
|
195
|
+
proposalId2,
|
|
196
|
+
);
|
|
197
|
+
expect(retreivedAttestationsAfterDeleteForOtherProposal.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
|
|
198
|
+
compareAttestations(retreivedAttestationsAfterDeleteForOtherProposal, attestations2);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('Should blanket delete attestations per slot and proposal (does not perform db ops if there are no attestations)', async () => {
|
|
202
|
+
const slotNumber = 420;
|
|
203
|
+
const proposalId = 'proposalId';
|
|
204
|
+
|
|
205
|
+
const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId);
|
|
206
|
+
expect(retreivedAttestations.length).toBe(0);
|
|
207
|
+
|
|
208
|
+
await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
|
|
209
|
+
|
|
210
|
+
expect(metricsMock.recordRemovedObjects).toHaveBeenCalledTimes(0);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('Should delete attestations older than a given slot', async () => {
|
|
214
|
+
const slotNumbers = [1, 2, 3, 69, 72, 74, 88, 420];
|
|
215
|
+
const attestations = slotNumbers.map(slotNumber => createAttestationsForSlot(slotNumber)).flat();
|
|
216
|
+
const proposalId = attestations[0].archive.toString();
|
|
217
|
+
|
|
218
|
+
await ap.addAttestations(attestations);
|
|
219
|
+
|
|
220
|
+
const attestationsForSlot1 = await ap.getAttestationsForSlot(BigInt(1), proposalId);
|
|
221
|
+
expect(attestationsForSlot1.length).toBe(signers.length);
|
|
222
|
+
|
|
223
|
+
const deleteAttestationsSpy = jest.spyOn(ap, 'deleteAttestationsForSlot');
|
|
224
|
+
|
|
225
|
+
await ap.deleteAttestationsOlderThan(BigInt(73));
|
|
226
|
+
|
|
227
|
+
const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlot(BigInt(1), proposalId);
|
|
228
|
+
expect(attestationsForSlot1AfterDelete.length).toBe(0);
|
|
229
|
+
|
|
230
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledTimes(5);
|
|
231
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(1));
|
|
232
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(2));
|
|
233
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(3));
|
|
234
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(69));
|
|
235
|
+
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(72));
|
|
236
|
+
});
|
|
237
|
+
}
|