@aztec/p2p 1.2.1 → 2.0.0-nightly.20250813
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/client/factory.d.ts +5 -1
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +29 -12
- package/dest/client/interface.d.ts +8 -13
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +18 -22
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +86 -83
- package/dest/config.d.ts +30 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +34 -1
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +13 -1
- 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.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +117 -10
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +4 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +22 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +4 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +21 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +2 -10
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +8 -3
- 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 +64 -37
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +8 -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 +18 -10
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +11 -2
- 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.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +73 -44
- package/dest/msg_validators/attestation_validator/attestation_validator.js +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +2 -2
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +35 -59
- package/dest/msg_validators/tx_validator/double_spend_validator.js +2 -2
- package/dest/msg_validators/tx_validator/gas_validator.js +4 -4
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +21 -21
- package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +3 -3
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +4 -1
- package/dest/services/dummy_service.d.ts +13 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +26 -3
- package/dest/services/index.d.ts +3 -1
- package/dest/services/index.d.ts.map +1 -1
- package/dest/services/index.js +3 -1
- package/dest/services/libp2p/libp2p_service.d.ts +13 -20
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +123 -46
- package/dest/services/peer-manager/interface.d.ts +8 -1
- package/dest/services/peer-manager/interface.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts +70 -3
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +369 -39
- package/dest/services/reqresp/config.d.ts +3 -3
- package/dest/services/reqresp/config.d.ts.map +1 -1
- package/dest/services/reqresp/config.js +3 -3
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +3 -4
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +35 -52
- package/dest/services/reqresp/index.d.ts +2 -1
- package/dest/services/reqresp/index.d.ts.map +1 -1
- package/dest/services/reqresp/index.js +2 -1
- package/dest/services/reqresp/interface.d.ts +61 -10
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +41 -6
- package/dest/services/reqresp/protocols/auth.d.ts +43 -0
- package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/auth.js +71 -0
- package/dest/services/reqresp/protocols/block.d.ts +5 -0
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block.js +28 -5
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +39 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +49 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +75 -0
- package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
- package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
- package/dest/services/reqresp/protocols/goodbye.js +3 -5
- package/dest/services/reqresp/protocols/index.d.ts +2 -0
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/index.js +2 -0
- package/dest/services/reqresp/protocols/status.d.ts +2 -0
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +7 -0
- package/dest/services/reqresp/protocols/tx.d.ts +12 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +34 -6
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
- package/dest/services/reqresp/rate-limiter/rate_limits.js +20 -0
- package/dest/services/reqresp/reqresp.d.ts +37 -39
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +220 -220
- package/dest/services/reqresp/status.d.ts +8 -3
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/reqresp/status.js +6 -2
- package/dest/services/service.d.ts +10 -10
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +25 -0
- package/dest/services/tx_collection/config.d.ts.map +1 -0
- package/dest/services/tx_collection/config.js +58 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +56 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/fast_tx_collection.js +295 -0
- package/dest/services/tx_collection/index.d.ts +3 -0
- package/dest/services/tx_collection/index.d.ts.map +1 -0
- package/dest/services/tx_collection/index.js +2 -0
- package/dest/services/tx_collection/instrumentation.d.ts +10 -0
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
- package/dest/services/tx_collection/instrumentation.js +34 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +54 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/slow_tx_collection.js +176 -0
- package/dest/services/tx_collection/tx_collection.d.ts +109 -0
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_collection.js +127 -0
- package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_collection_sink.js +81 -0
- package/dest/services/tx_collection/tx_source.d.ts +18 -0
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/tx_source.js +31 -0
- package/dest/services/tx_provider.d.ts +49 -0
- package/dest/services/tx_provider.d.ts.map +1 -0
- package/dest/services/tx_provider.js +206 -0
- package/dest/services/{tx_collect_instrumentation.d.ts → tx_provider_instrumentation.d.ts} +2 -2
- package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
- package/dest/services/{tx_collect_instrumentation.js → tx_provider_instrumentation.js} +5 -5
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +4 -3
- package/dest/test-helpers/mock-pubsub.d.ts +2 -1
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +2 -1
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +8 -4
- package/dest/testbench/p2p_client_testbench_worker.js +11 -5
- package/dest/util.d.ts +1 -1
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -15
- package/src/client/factory.ts +87 -12
- package/src/client/interface.ts +19 -15
- package/src/client/p2p_client.ts +108 -92
- package/src/config.ts +52 -1
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +15 -1
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +155 -4
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +28 -1
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +28 -2
- package/src/mem_pools/attestation_pool/mocks.ts +1 -3
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +59 -41
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +19 -9
- package/src/mem_pools/tx_pool/tx_pool.ts +7 -2
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +63 -40
- package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
- package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
- package/src/msg_validators/tx_validator/data_validator.ts +36 -27
- package/src/msg_validators/tx_validator/double_spend_validator.ts +2 -2
- package/src/msg_validators/tx_validator/gas_validator.ts +4 -4
- package/src/msg_validators/tx_validator/metadata_validator.ts +22 -28
- package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -2
- package/src/services/discv5/discV5_service.ts +4 -1
- package/src/services/dummy_service.ts +44 -4
- package/src/services/index.ts +3 -1
- package/src/services/libp2p/libp2p_service.ts +147 -55
- package/src/services/peer-manager/interface.ts +10 -1
- package/src/services/peer-manager/peer_manager.ts +441 -41
- package/src/services/reqresp/config.ts +3 -3
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +38 -63
- package/src/services/reqresp/index.ts +2 -0
- package/src/services/reqresp/interface.ts +63 -17
- package/src/services/reqresp/protocols/auth.ts +83 -0
- package/src/services/reqresp/protocols/block.ts +24 -3
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -0
- package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
- package/src/services/reqresp/protocols/goodbye.ts +3 -3
- package/src/services/reqresp/protocols/index.ts +2 -0
- package/src/services/reqresp/protocols/status.ts +20 -0
- package/src/services/reqresp/protocols/tx.ts +35 -6
- package/src/services/reqresp/rate-limiter/rate_limits.ts +20 -0
- package/src/services/reqresp/reqresp.ts +294 -264
- package/src/services/reqresp/status.ts +9 -3
- package/src/services/service.ts +23 -14
- package/src/services/tx_collection/config.ts +84 -0
- package/src/services/tx_collection/fast_tx_collection.ts +338 -0
- package/src/services/tx_collection/index.ts +2 -0
- package/src/services/tx_collection/instrumentation.ts +43 -0
- package/src/services/tx_collection/slow_tx_collection.ts +232 -0
- package/src/services/tx_collection/tx_collection.ts +214 -0
- package/src/services/tx_collection/tx_collection_sink.ts +98 -0
- package/src/services/tx_collection/tx_source.ts +37 -0
- package/src/services/tx_provider.ts +215 -0
- package/src/services/{tx_collect_instrumentation.ts → tx_provider_instrumentation.ts} +5 -5
- package/src/test-helpers/make-test-p2p-clients.ts +4 -2
- package/src/test-helpers/mock-pubsub.ts +1 -0
- package/src/test-helpers/reqresp-nodes.ts +7 -1
- package/src/testbench/p2p_client_testbench_worker.ts +9 -2
- package/src/util.ts +1 -1
- package/dest/services/tx_collect_instrumentation.d.ts.map +0 -1
- package/dest/services/tx_collector.d.ts +0 -23
- package/dest/services/tx_collector.d.ts.map +0 -1
- package/dest/services/tx_collector.js +0 -95
- package/src/services/tx_collector.ts +0 -134
package/src/config.ts
CHANGED
|
@@ -16,11 +16,12 @@ import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
|
16
16
|
import { type AllowedElement, type ChainConfig, chainConfigMappings } from '@aztec/stdlib/config';
|
|
17
17
|
|
|
18
18
|
import { type P2PReqRespConfig, p2pReqRespConfigMappings } from './services/reqresp/config.js';
|
|
19
|
+
import { type TxCollectionConfig, txCollectionConfigMappings } from './services/tx_collection/config.js';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* P2P client configuration values.
|
|
22
23
|
*/
|
|
23
|
-
export interface P2PConfig extends P2PReqRespConfig, ChainConfig {
|
|
24
|
+
export interface P2PConfig extends P2PReqRespConfig, ChainConfig, TxCollectionConfig {
|
|
24
25
|
/** A flag dictating whether the P2P subsystem should be enabled. */
|
|
25
26
|
p2pEnabled: boolean;
|
|
26
27
|
|
|
@@ -123,6 +124,9 @@ export interface P2PConfig extends P2PReqRespConfig, ChainConfig {
|
|
|
123
124
|
/** A list of private peers. */
|
|
124
125
|
privatePeers: string[];
|
|
125
126
|
|
|
127
|
+
/** A list of preferred peers. */
|
|
128
|
+
preferredPeers: string[];
|
|
129
|
+
|
|
126
130
|
/** The maximum possible size of the P2P DB in KB. Overwrites the general dataStoreMapSizeKB. */
|
|
127
131
|
p2pStoreMapSizeKb?: number;
|
|
128
132
|
|
|
@@ -140,6 +144,20 @@ export interface P2PConfig extends P2PReqRespConfig, ChainConfig {
|
|
|
140
144
|
|
|
141
145
|
/** True to disable the status handshake on peer connected. */
|
|
142
146
|
p2pDisableStatusHandshake?: boolean;
|
|
147
|
+
|
|
148
|
+
/** True to only permit validators to connect */
|
|
149
|
+
p2pAllowOnlyValidators?: boolean;
|
|
150
|
+
|
|
151
|
+
/** True to disable participating in discovery */
|
|
152
|
+
p2pDiscoveryDisabled?: boolean;
|
|
153
|
+
/** Number of auth attempts to allow before peer is banned. Number is inclusive*/
|
|
154
|
+
p2pMaxFailedAuthAttemptsAllowed: number;
|
|
155
|
+
|
|
156
|
+
/** True to simulate discarding transactions. - For testing purposes only*/
|
|
157
|
+
dropTransactions: boolean;
|
|
158
|
+
|
|
159
|
+
/** The probability that a transaction is discarded. - For testing purposes only */
|
|
160
|
+
dropTransactionsProbability: number;
|
|
143
161
|
}
|
|
144
162
|
|
|
145
163
|
export const DEFAULT_P2P_PORT = 40400;
|
|
@@ -150,6 +168,11 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
150
168
|
description: 'A flag dictating whether the P2P subsystem should be enabled.',
|
|
151
169
|
...booleanConfigHelper(),
|
|
152
170
|
},
|
|
171
|
+
p2pDiscoveryDisabled: {
|
|
172
|
+
env: 'P2P_DISCOVERY_DISABLED',
|
|
173
|
+
description: 'A flag dictating whether the P2P discovery system should be disabled.',
|
|
174
|
+
...booleanConfigHelper(false),
|
|
175
|
+
},
|
|
153
176
|
blockCheckIntervalMS: {
|
|
154
177
|
env: 'P2P_BLOCK_CHECK_INTERVAL_MS',
|
|
155
178
|
description: 'The frequency in which to check for new L2 blocks.',
|
|
@@ -321,6 +344,13 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
321
344
|
'A list of private peer ENRs that will always be persisted and not be used for discovery. Separated by commas.',
|
|
322
345
|
defaultValue: [],
|
|
323
346
|
},
|
|
347
|
+
preferredPeers: {
|
|
348
|
+
env: 'P2P_PREFERRED_PEERS',
|
|
349
|
+
parseEnv: (val: string) => val.split(','),
|
|
350
|
+
description:
|
|
351
|
+
'A list of preferred peer ENRs that will always be persisted and not be used for discovery. Separated by commas.',
|
|
352
|
+
defaultValue: [],
|
|
353
|
+
},
|
|
324
354
|
p2pStoreMapSizeKb: {
|
|
325
355
|
env: 'P2P_STORE_MAP_SIZE_KB',
|
|
326
356
|
parseEnv: (val: string | undefined) => (val ? +val : undefined),
|
|
@@ -353,8 +383,29 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
353
383
|
description: 'True to disable the status handshake on peer connected.',
|
|
354
384
|
...booleanConfigHelper(false),
|
|
355
385
|
},
|
|
386
|
+
p2pAllowOnlyValidators: {
|
|
387
|
+
env: 'P2P_ALLOW_ONLY_VALIDATORS',
|
|
388
|
+
description: 'True to only permit validators to connect.',
|
|
389
|
+
...booleanConfigHelper(false),
|
|
390
|
+
},
|
|
391
|
+
p2pMaxFailedAuthAttemptsAllowed: {
|
|
392
|
+
env: 'P2P_MAX_AUTH_FAILED_ATTEMPTS_ALLOWED',
|
|
393
|
+
description: 'Number of auth attempts to allow before peer is banned. Number is inclusive',
|
|
394
|
+
...numberConfigHelper(3),
|
|
395
|
+
},
|
|
396
|
+
dropTransactions: {
|
|
397
|
+
env: 'P2P_DROP_TX',
|
|
398
|
+
description: 'True to simulate discarding transactions. - For testing purposes only',
|
|
399
|
+
...booleanConfigHelper(false),
|
|
400
|
+
},
|
|
401
|
+
dropTransactionsProbability: {
|
|
402
|
+
env: 'P2P_DROP_TX_CHANCE',
|
|
403
|
+
description: 'The probability that a transaction is discarded. - For testing purposes only',
|
|
404
|
+
...floatConfigHelper(0),
|
|
405
|
+
},
|
|
356
406
|
...p2pReqRespConfigMappings,
|
|
357
407
|
...chainConfigMappings,
|
|
408
|
+
...txCollectionConfigMappings,
|
|
358
409
|
};
|
|
359
410
|
|
|
360
411
|
/**
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
1
|
+
import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* An Attestation Pool contains attestations collected by a validator
|
|
@@ -7,6 +7,20 @@ import type { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
|
7
7
|
* from the validator to produce a block, or to serve to other peers.
|
|
8
8
|
*/
|
|
9
9
|
export interface AttestationPool {
|
|
10
|
+
/**
|
|
11
|
+
* Adds new block proposal to the pool
|
|
12
|
+
*/
|
|
13
|
+
addBlockProposal(blockProposal: BlockProposal): Promise<void>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get block proposal by it's ID
|
|
17
|
+
*
|
|
18
|
+
* @param id - The ID of the block proposal to retrieve. The ID is proposal.payload.archive
|
|
19
|
+
*
|
|
20
|
+
* @return The block proposal if it exists, otherwise undefined.
|
|
21
|
+
*/
|
|
22
|
+
getBlockProposal(id: string): Promise<BlockProposal | undefined>;
|
|
23
|
+
|
|
10
24
|
/**
|
|
11
25
|
* AddAttestations
|
|
12
26
|
*
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { Secp256k1Signer } from '@aztec/foundation/crypto';
|
|
2
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
-
import type { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
3
|
+
import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
4
|
+
import {
|
|
5
|
+
BlockProposal as BlockProposalClass,
|
|
6
|
+
ConsensusPayload,
|
|
7
|
+
SignatureDomainSeparator,
|
|
8
|
+
getHashedSignaturePayloadEthSignedMessage,
|
|
9
|
+
} from '@aztec/stdlib/p2p';
|
|
10
|
+
import { makeHeader } from '@aztec/stdlib/testing';
|
|
4
11
|
import { TxHash } from '@aztec/stdlib/tx';
|
|
5
12
|
|
|
6
13
|
import { jest } from '@jest/globals';
|
|
@@ -33,6 +40,19 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
33
40
|
return signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
34
41
|
};
|
|
35
42
|
|
|
43
|
+
const mockBlockProposal = (signer: Secp256k1Signer, slotNumber: number, archive: Fr = Fr.random()): BlockProposal => {
|
|
44
|
+
const blockNumber = 1;
|
|
45
|
+
const header = makeHeader(1, 2, slotNumber);
|
|
46
|
+
const payload = new ConsensusPayload(header.toPropose(), archive, header.state);
|
|
47
|
+
|
|
48
|
+
const hash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
|
|
49
|
+
const signature = signer.sign(hash);
|
|
50
|
+
|
|
51
|
+
const txHashes = [TxHash.random(), TxHash.random()]; // Mock tx hashes
|
|
52
|
+
|
|
53
|
+
return new BlockProposalClass(blockNumber, payload, signature, txHashes);
|
|
54
|
+
};
|
|
55
|
+
|
|
36
56
|
// We compare buffers as the objects can have cached values attached to them which are not serialised
|
|
37
57
|
// using array containing as the kv store does not respect insertion order
|
|
38
58
|
const compareAttestations = (a1: BlockAttestation[], a2: BlockAttestation[]) => {
|
|
@@ -83,13 +103,12 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
83
103
|
it('should handle duplicate proposals in a slot', async () => {
|
|
84
104
|
const slotNumber = 420;
|
|
85
105
|
const archive = Fr.random();
|
|
86
|
-
const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
|
|
87
106
|
|
|
88
107
|
// Use the same signer for all attestations
|
|
89
108
|
const attestations: BlockAttestation[] = [];
|
|
90
109
|
const signer = signers[0];
|
|
91
110
|
for (let i = 0; i < NUMBER_OF_SIGNERS_PER_TEST; i++) {
|
|
92
|
-
attestations.push(mockAttestation(signer, slotNumber, archive
|
|
111
|
+
attestations.push(mockAttestation(signer, slotNumber, archive));
|
|
93
112
|
}
|
|
94
113
|
|
|
95
114
|
// Add them to store and check we end up with only one
|
|
@@ -98,7 +117,6 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
98
117
|
const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), archive.toString());
|
|
99
118
|
expect(retreivedAttestations.length).toBe(1);
|
|
100
119
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
|
|
101
|
-
expect(retreivedAttestations[0].payload.txHashes).toEqual(txs);
|
|
102
120
|
expect(retreivedAttestations[0].getSender().toString()).toEqual(signer.address.toString());
|
|
103
121
|
|
|
104
122
|
// Try adding them on another operation and check they are still not duplicated
|
|
@@ -234,4 +252,137 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
234
252
|
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(69));
|
|
235
253
|
expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(72));
|
|
236
254
|
});
|
|
255
|
+
|
|
256
|
+
describe('BlockProposal in attestation pool', () => {
|
|
257
|
+
it('should add and retrieve block proposal', async () => {
|
|
258
|
+
const slotNumber = 420;
|
|
259
|
+
const archive = Fr.random();
|
|
260
|
+
const proposal = mockBlockProposal(signers[0], slotNumber, archive);
|
|
261
|
+
const proposalId = proposal.archive.toString();
|
|
262
|
+
|
|
263
|
+
await ap.addBlockProposal(proposal);
|
|
264
|
+
|
|
265
|
+
const retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
266
|
+
|
|
267
|
+
// This are cached values, so we need to call them to ensure they are not undefined
|
|
268
|
+
retrievedProposal!.payload.getSize();
|
|
269
|
+
retrievedProposal!.signature.getSize();
|
|
270
|
+
|
|
271
|
+
expect(retrievedProposal).toBeDefined();
|
|
272
|
+
expect(retrievedProposal!).toEqual(proposal);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('should return undefined for non-existent block proposal', async () => {
|
|
276
|
+
const nonExistentId = Fr.random().toString();
|
|
277
|
+
const retrievedProposal = await ap.getBlockProposal(nonExistentId);
|
|
278
|
+
expect(retrievedProposal).toBeUndefined();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('should update block proposal if added twice with same id', async () => {
|
|
282
|
+
const slotNumber = 420;
|
|
283
|
+
const archive = Fr.random();
|
|
284
|
+
const proposal1 = mockBlockProposal(signers[0], slotNumber, archive);
|
|
285
|
+
const proposalId = proposal1.archive.toString();
|
|
286
|
+
|
|
287
|
+
await ap.addBlockProposal(proposal1);
|
|
288
|
+
|
|
289
|
+
// Create a new proposal with same archive but different signer
|
|
290
|
+
const proposal2 = mockBlockProposal(signers[1], slotNumber, archive);
|
|
291
|
+
|
|
292
|
+
await ap.addBlockProposal(proposal2);
|
|
293
|
+
|
|
294
|
+
const retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
295
|
+
expect(retrievedProposal).toBeDefined();
|
|
296
|
+
// Should have the second proposal
|
|
297
|
+
expect(retrievedProposal!.toBuffer()).toEqual(proposal2.toBuffer());
|
|
298
|
+
expect(retrievedProposal!.getSender().toString()).toBe(signers[1].address.toString());
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should handle block proposals with different slots and same archive', async () => {
|
|
302
|
+
const archive = Fr.random();
|
|
303
|
+
const proposal1 = mockBlockProposal(signers[0], 100, archive);
|
|
304
|
+
const proposal2 = mockBlockProposal(signers[1], 200, archive);
|
|
305
|
+
const proposalId = archive.toString();
|
|
306
|
+
|
|
307
|
+
await ap.addBlockProposal(proposal1);
|
|
308
|
+
await ap.addBlockProposal(proposal2);
|
|
309
|
+
|
|
310
|
+
// Should get the latest one added
|
|
311
|
+
const retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
312
|
+
expect(retrievedProposal).toBeDefined();
|
|
313
|
+
expect(retrievedProposal!.toBuffer()).toEqual(proposal2.toBuffer());
|
|
314
|
+
expect(retrievedProposal!.slotNumber.toBigInt()).toBe(BigInt(200));
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should delete block proposal when deleting attestations for slot and proposal', async () => {
|
|
318
|
+
const slotNumber = 420;
|
|
319
|
+
const archive = Fr.random();
|
|
320
|
+
const proposal = mockBlockProposal(signers[0], slotNumber, archive);
|
|
321
|
+
const proposalId = proposal.archive.toString();
|
|
322
|
+
|
|
323
|
+
// Add proposal and some attestations
|
|
324
|
+
await ap.addBlockProposal(proposal);
|
|
325
|
+
const attestations = signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
326
|
+
await ap.addAttestations(attestations);
|
|
327
|
+
|
|
328
|
+
// Verify proposal exists
|
|
329
|
+
let retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
330
|
+
expect(retrievedProposal).toBeDefined();
|
|
331
|
+
|
|
332
|
+
// Delete attestations for slot and proposal
|
|
333
|
+
await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
|
|
334
|
+
|
|
335
|
+
// Proposal should be deleted
|
|
336
|
+
retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
337
|
+
expect(retrievedProposal).toBeUndefined();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should delete block proposal when deleting attestations for slot', async () => {
|
|
341
|
+
const slotNumber = 420;
|
|
342
|
+
const archive = Fr.random();
|
|
343
|
+
const proposal = mockBlockProposal(signers[0], slotNumber, archive);
|
|
344
|
+
const proposalId = proposal.archive.toString();
|
|
345
|
+
|
|
346
|
+
// Add proposal
|
|
347
|
+
await ap.addBlockProposal(proposal);
|
|
348
|
+
|
|
349
|
+
// Verify proposal exists
|
|
350
|
+
let retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
351
|
+
expect(retrievedProposal).toBeDefined();
|
|
352
|
+
|
|
353
|
+
// Delete attestations for slot
|
|
354
|
+
await ap.deleteAttestationsForSlot(BigInt(slotNumber));
|
|
355
|
+
|
|
356
|
+
// Proposal should be deleted
|
|
357
|
+
retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
358
|
+
expect(retrievedProposal).toBeUndefined();
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('should be able to fetch both block proposal and attestations', async () => {
|
|
362
|
+
const slotNumber = 420;
|
|
363
|
+
const archive = Fr.random();
|
|
364
|
+
const proposal = mockBlockProposal(signers[0], slotNumber, archive);
|
|
365
|
+
const proposalId = proposal.archive.toString();
|
|
366
|
+
|
|
367
|
+
// Add proposal first
|
|
368
|
+
await ap.addBlockProposal(proposal);
|
|
369
|
+
|
|
370
|
+
// Add attestations for the same proposal
|
|
371
|
+
const attestations = signers.slice(1).map(signer => mockAttestation(signer, slotNumber, archive));
|
|
372
|
+
await ap.addAttestations(attestations);
|
|
373
|
+
|
|
374
|
+
// Retrieve both proposal and attestations
|
|
375
|
+
const retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
376
|
+
const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
|
|
377
|
+
|
|
378
|
+
expect(retrievedProposal).toBeDefined();
|
|
379
|
+
// This are cached values, so we need to call them to ensure they are not undefined
|
|
380
|
+
retrievedProposal!.payload.getSize();
|
|
381
|
+
retrievedProposal!.signature.getSize();
|
|
382
|
+
|
|
383
|
+
expect(retrievedProposal).toEqual(proposal);
|
|
384
|
+
|
|
385
|
+
compareAttestations(retrievedAttestations, attestations);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
237
388
|
}
|
|
@@ -2,7 +2,7 @@ import { Fr } from '@aztec/foundation/fields';
|
|
|
2
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
|
|
5
|
-
import { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
5
|
+
import { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
6
6
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
7
7
|
|
|
8
8
|
import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
|
|
@@ -12,6 +12,10 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
12
12
|
private metrics: PoolInstrumentation<BlockAttestation>;
|
|
13
13
|
|
|
14
14
|
private attestations: AztecAsyncMap<string, Buffer>;
|
|
15
|
+
private proposals: AztecAsyncMap<
|
|
16
|
+
/* proposal.payload.archive */ string,
|
|
17
|
+
/* buffer representation of proposal */ Buffer
|
|
18
|
+
>;
|
|
15
19
|
private proposalsForSlot: AztecAsyncMultiMap<string, string>;
|
|
16
20
|
private attestationsForProposal: AztecAsyncMultiMap<string, string>;
|
|
17
21
|
|
|
@@ -21,6 +25,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
21
25
|
private log = createLogger('aztec:attestation_pool'),
|
|
22
26
|
) {
|
|
23
27
|
this.attestations = store.openMap('attestations');
|
|
28
|
+
this.proposals = store.openMap('proposals');
|
|
24
29
|
this.proposalsForSlot = store.openMultiMap('proposals_for_slot');
|
|
25
30
|
this.attestationsForProposal = store.openMultiMap('attestations_for_proposal');
|
|
26
31
|
|
|
@@ -137,6 +142,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
137
142
|
await this.attestations.delete(attestation);
|
|
138
143
|
}
|
|
139
144
|
|
|
145
|
+
await this.proposals.delete(proposalId);
|
|
140
146
|
await this.attestationsForProposal.delete(this.getProposalKey(slotFr, proposalId));
|
|
141
147
|
}
|
|
142
148
|
|
|
@@ -157,6 +163,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
157
163
|
await this.attestations.delete(attestation);
|
|
158
164
|
}
|
|
159
165
|
|
|
166
|
+
await this.proposals.delete(proposalId);
|
|
160
167
|
await this.proposalsForSlot.deleteValue(slotString, proposalId);
|
|
161
168
|
await this.attestationsForProposal.delete(this.getProposalKey(slotString, proposalId));
|
|
162
169
|
|
|
@@ -185,4 +192,24 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
185
192
|
}
|
|
186
193
|
});
|
|
187
194
|
}
|
|
195
|
+
|
|
196
|
+
public async getBlockProposal(id: string): Promise<BlockProposal | undefined> {
|
|
197
|
+
const buffer = await this.proposals.getAsync(id);
|
|
198
|
+
try {
|
|
199
|
+
if (buffer && buffer.length > 0) {
|
|
200
|
+
return BlockProposal.fromBuffer(buffer);
|
|
201
|
+
}
|
|
202
|
+
} catch {
|
|
203
|
+
return Promise.resolve(undefined);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return Promise.resolve(undefined);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public async addBlockProposal(blockProposal: BlockProposal): Promise<void> {
|
|
210
|
+
await this.store.transactionAsync(async () => {
|
|
211
|
+
await this.proposalsForSlot.set(blockProposal.slotNumber.toString(), blockProposal.archive.toString());
|
|
212
|
+
await this.proposals.set(blockProposal.payload.archive.toString(), blockProposal.toBuffer());
|
|
213
|
+
});
|
|
214
|
+
}
|
|
188
215
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
-
import type { BlockAttestation } from '@aztec/stdlib/p2p';
|
|
2
|
+
import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
|
|
3
3
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
4
4
|
|
|
5
5
|
import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
|
|
@@ -9,12 +9,14 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
9
9
|
private metrics: PoolInstrumentation<BlockAttestation>;
|
|
10
10
|
|
|
11
11
|
private attestations: Map</*slot=*/ bigint, Map</*proposalId*/ string, Map</*address=*/ string, BlockAttestation>>>;
|
|
12
|
+
private proposals: Map<string, BlockProposal>;
|
|
12
13
|
|
|
13
14
|
constructor(
|
|
14
15
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
15
16
|
private log = createLogger('p2p:attestation_pool'),
|
|
16
17
|
) {
|
|
17
18
|
this.attestations = new Map();
|
|
19
|
+
this.proposals = new Map();
|
|
18
20
|
this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL, this.poolStats);
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -106,9 +108,17 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
106
108
|
public deleteAttestationsForSlot(slot: bigint): Promise<void> {
|
|
107
109
|
// We count the number of attestations we are removing
|
|
108
110
|
const numberOfAttestations = this.#getNumberOfAttestationsInSlot(slot);
|
|
111
|
+
const proposalIdsToDelete = this.attestations.get(slot)?.keys();
|
|
112
|
+
let proposalIdsToDeleteCount = 0;
|
|
113
|
+
proposalIdsToDelete?.forEach(proposalId => {
|
|
114
|
+
this.proposals.delete(proposalId);
|
|
115
|
+
proposalIdsToDeleteCount++;
|
|
116
|
+
});
|
|
109
117
|
|
|
110
118
|
this.attestations.delete(slot);
|
|
111
|
-
this.log.verbose(
|
|
119
|
+
this.log.verbose(
|
|
120
|
+
`Removed ${numberOfAttestations} attestations and ${proposalIdsToDeleteCount} proposals for slot ${slot}`,
|
|
121
|
+
);
|
|
112
122
|
|
|
113
123
|
return Promise.resolve();
|
|
114
124
|
}
|
|
@@ -124,6 +134,8 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
124
134
|
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
|
|
125
135
|
}
|
|
126
136
|
}
|
|
137
|
+
|
|
138
|
+
this.proposals.delete(proposalId);
|
|
127
139
|
return Promise.resolve();
|
|
128
140
|
}
|
|
129
141
|
|
|
@@ -143,6 +155,20 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
143
155
|
}
|
|
144
156
|
return Promise.resolve();
|
|
145
157
|
}
|
|
158
|
+
|
|
159
|
+
public addBlockProposal(blockProposal: BlockProposal): Promise<void> {
|
|
160
|
+
// We initialize slot-proposal mapping if it does not exist
|
|
161
|
+
// This is important to ensure we can delete this proposal if there were not attestations for it
|
|
162
|
+
const slotProposalMapping = getSlotOrDefault(this.attestations, blockProposal.slotNumber.toBigInt());
|
|
163
|
+
slotProposalMapping.set(blockProposal.payload.archive.toString(), new Map<string, BlockAttestation>());
|
|
164
|
+
|
|
165
|
+
this.proposals.set(blockProposal.payload.archive.toString(), blockProposal);
|
|
166
|
+
return Promise.resolve();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public getBlockProposal(id: string): Promise<BlockProposal | undefined> {
|
|
170
|
+
return Promise.resolve(this.proposals.get(id));
|
|
171
|
+
}
|
|
146
172
|
}
|
|
147
173
|
|
|
148
174
|
/**
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
getHashedSignaturePayloadEthSignedMessage,
|
|
8
8
|
} from '@aztec/stdlib/p2p';
|
|
9
9
|
import { makeHeader } from '@aztec/stdlib/testing';
|
|
10
|
-
import { TxHash } from '@aztec/stdlib/tx';
|
|
11
10
|
|
|
12
11
|
import { type LocalAccount, generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
13
12
|
|
|
@@ -31,11 +30,10 @@ export const mockAttestation = (
|
|
|
31
30
|
signer: Secp256k1Signer,
|
|
32
31
|
slot: number = 0,
|
|
33
32
|
archive: Fr = Fr.random(),
|
|
34
|
-
txs: TxHash[] = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()),
|
|
35
33
|
): BlockAttestation => {
|
|
36
34
|
// Use arbitrary numbers for all other than slot
|
|
37
35
|
const header = makeHeader(1, 2, slot);
|
|
38
|
-
const payload = new ConsensusPayload(header.toPropose(), archive, header.state
|
|
36
|
+
const payload = new ConsensusPayload(header.toPropose(), archive, header.state);
|
|
39
37
|
|
|
40
38
|
const hash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
|
|
41
39
|
const signature = signer.sign(hash);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
4
5
|
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap, AztecAsyncSingleton } from '@aztec/kv-store';
|
|
5
6
|
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
6
7
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
@@ -12,17 +13,18 @@ import { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
|
|
|
12
13
|
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
13
14
|
|
|
14
15
|
import assert from 'assert';
|
|
16
|
+
import EventEmitter from 'node:events';
|
|
15
17
|
|
|
16
18
|
import { ArchiveCache } from '../../msg_validators/tx_validator/archive_cache.js';
|
|
17
19
|
import { GasTxValidator } from '../../msg_validators/tx_validator/gas_validator.js';
|
|
18
20
|
import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
|
|
19
21
|
import { getPendingTxPriority } from './priority.js';
|
|
20
|
-
import type { TxPool, TxPoolOptions } from './tx_pool.js';
|
|
22
|
+
import type { TxPool, TxPoolEvents, TxPoolOptions } from './tx_pool.js';
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
25
|
* KV implementation of the Transaction Pool.
|
|
24
26
|
*/
|
|
25
|
-
export class AztecKVTxPool implements TxPool {
|
|
27
|
+
export class AztecKVTxPool extends (EventEmitter as new () => TypedEventEmitter<TxPoolEvents>) implements TxPool {
|
|
26
28
|
#store: AztecAsyncKVStore;
|
|
27
29
|
|
|
28
30
|
/** Our tx pool, stored as a Map, with K: tx hash and V: the transaction. */
|
|
@@ -90,6 +92,8 @@ export class AztecKVTxPool implements TxPool {
|
|
|
90
92
|
config: TxPoolOptions = {},
|
|
91
93
|
log = createLogger('p2p:tx_pool'),
|
|
92
94
|
) {
|
|
95
|
+
super();
|
|
96
|
+
|
|
93
97
|
this.#log = log;
|
|
94
98
|
this.updateConfig(config);
|
|
95
99
|
|
|
@@ -276,11 +280,9 @@ export class AztecKVTxPool implements TxPool {
|
|
|
276
280
|
* @param txs - An array of txs to be added to the pool.
|
|
277
281
|
* @returns Empty promise.
|
|
278
282
|
*/
|
|
279
|
-
public async addTxs(txs: Tx[]): Promise<number> {
|
|
280
|
-
|
|
281
|
-
const hashesAndStats =
|
|
282
|
-
txs.map(async tx => ({ txHash: await tx.getTxHash(), txStats: await tx.getStats() })),
|
|
283
|
-
);
|
|
283
|
+
public async addTxs(txs: Tx[], opts: { source?: string } = {}): Promise<number> {
|
|
284
|
+
const addedTxs: Tx[] = [];
|
|
285
|
+
const hashesAndStats = txs.map(tx => ({ txHash: tx.getTxHash(), txStats: tx.getStats() }));
|
|
284
286
|
await this.#store.transactionAsync(async () => {
|
|
285
287
|
let pendingTxSize = (await this.#pendingTxSize.getAsync()) ?? 0;
|
|
286
288
|
await Promise.all(
|
|
@@ -298,9 +300,9 @@ export class AztecKVTxPool implements TxPool {
|
|
|
298
300
|
} satisfies TxAddedToPoolStats);
|
|
299
301
|
|
|
300
302
|
await this.#txs.set(key, tx.toBuffer());
|
|
303
|
+
addedTxs.push(tx as Tx);
|
|
301
304
|
|
|
302
305
|
if (!(await this.#minedTxHashToBlock.hasAsync(key))) {
|
|
303
|
-
addedCount++;
|
|
304
306
|
pendingTxSize += tx.getSize();
|
|
305
307
|
await this.addPendingTxIndices(tx, key);
|
|
306
308
|
this.#metrics.recordSize(tx);
|
|
@@ -312,7 +314,10 @@ export class AztecKVTxPool implements TxPool {
|
|
|
312
314
|
await this.evictLowPriorityTxs(hashesAndStats.map(({ txHash }) => txHash));
|
|
313
315
|
});
|
|
314
316
|
|
|
315
|
-
|
|
317
|
+
if (addedTxs.length > 0) {
|
|
318
|
+
this.emit('txs-added', { ...opts, txs: addedTxs });
|
|
319
|
+
}
|
|
320
|
+
return addedTxs.length;
|
|
316
321
|
}
|
|
317
322
|
|
|
318
323
|
/**
|
|
@@ -321,6 +326,9 @@ export class AztecKVTxPool implements TxPool {
|
|
|
321
326
|
* @returns Empty promise.
|
|
322
327
|
*/
|
|
323
328
|
public deleteTxs(txHashes: TxHash[], eviction = false): Promise<void> {
|
|
329
|
+
if (txHashes.length === 0) {
|
|
330
|
+
return Promise.resolve();
|
|
331
|
+
}
|
|
324
332
|
const deletedTxs: Tx[] = [];
|
|
325
333
|
const poolDbTx = this.#store.transactionAsync(async () => {
|
|
326
334
|
let pendingTxSize = (await this.#pendingTxSize.getAsync()) ?? 0;
|
|
@@ -346,7 +354,7 @@ export class AztecKVTxPool implements TxPool {
|
|
|
346
354
|
|
|
347
355
|
await this.#pendingTxSize.set(pendingTxSize);
|
|
348
356
|
});
|
|
349
|
-
|
|
357
|
+
this.#log.debug(`Deleted ${txHashes.length} txs from pool`, { txHashes });
|
|
350
358
|
return this.#archivedTxLimit ? poolDbTx.then(() => this.archiveTxs(deletedTxs)) : poolDbTx;
|
|
351
359
|
}
|
|
352
360
|
|
|
@@ -451,36 +459,46 @@ export class AztecKVTxPool implements TxPool {
|
|
|
451
459
|
* @returns Empty promise.
|
|
452
460
|
*/
|
|
453
461
|
private async archiveTxs(txs: Tx[]): Promise<void> {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
462
|
+
if (txs.length === 0) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
try {
|
|
466
|
+
const txHashes = await Promise.all(txs.map(tx => tx.getTxHash()));
|
|
467
|
+
await this.#archive.transactionAsync(async () => {
|
|
468
|
+
// calculate the head and tail indices of the archived txs by insertion order.
|
|
469
|
+
let headIdx =
|
|
470
|
+
((await this.#archivedTxIndices.entriesAsync({ limit: 1, reverse: true }).next()).value?.[0] ?? -1) + 1;
|
|
471
|
+
let tailIdx = (await this.#archivedTxIndices.entriesAsync({ limit: 1 }).next()).value?.[0] ?? 0;
|
|
472
|
+
|
|
473
|
+
for (let i = 0; i < txs.length; i++) {
|
|
474
|
+
const tx = txs[i];
|
|
475
|
+
while (headIdx - tailIdx >= this.#archivedTxLimit) {
|
|
476
|
+
const txHash = await this.#archivedTxIndices.getAsync(tailIdx);
|
|
477
|
+
if (txHash) {
|
|
478
|
+
await this.#archivedTxs.delete(txHash);
|
|
479
|
+
await this.#archivedTxIndices.delete(tailIdx);
|
|
480
|
+
}
|
|
481
|
+
tailIdx++;
|
|
468
482
|
}
|
|
469
|
-
tailIdx++;
|
|
470
|
-
}
|
|
471
483
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
+
const archivedTx: Tx = new Tx(
|
|
485
|
+
tx.txHash,
|
|
486
|
+
tx.data,
|
|
487
|
+
ClientIvcProof.empty(),
|
|
488
|
+
tx.contractClassLogFields,
|
|
489
|
+
tx.publicFunctionCalldata,
|
|
490
|
+
);
|
|
491
|
+
const txHash = txHashes[i].toString();
|
|
492
|
+
await this.#archivedTxs.set(txHash, archivedTx.toBuffer());
|
|
493
|
+
await this.#archivedTxIndices.set(headIdx, txHash);
|
|
494
|
+
headIdx++;
|
|
495
|
+
}
|
|
496
|
+
this.#log.debug(`Archived ${txs.length} txs`, { txHashes });
|
|
497
|
+
this.#log.debug(`Total archived txs: ${headIdx - tailIdx}`);
|
|
498
|
+
});
|
|
499
|
+
} catch (error) {
|
|
500
|
+
this.#log.error(`Error archiving txs`, { error });
|
|
501
|
+
}
|
|
484
502
|
}
|
|
485
503
|
|
|
486
504
|
/**
|
|
@@ -591,10 +609,10 @@ export class AztecKVTxPool implements TxPool {
|
|
|
591
609
|
}
|
|
592
610
|
|
|
593
611
|
// Evict pending txs with an expiration timestamp less than or equal to the mined block timestamp
|
|
594
|
-
const includeByTimestamp = tx.data.
|
|
595
|
-
if (includeByTimestamp
|
|
612
|
+
const includeByTimestamp = tx.data.includeByTimestamp;
|
|
613
|
+
if (includeByTimestamp <= timestamp) {
|
|
596
614
|
this.#log.verbose(
|
|
597
|
-
`Evicting tx ${txHash} from pool due to the tx being expired (includeByTimestamp: ${includeByTimestamp
|
|
615
|
+
`Evicting tx ${txHash} from pool due to the tx being expired (includeByTimestamp: ${includeByTimestamp}, mined block timestamp: ${timestamp})`,
|
|
598
616
|
);
|
|
599
617
|
txsToEvict.push(TxHash.fromString(txHash));
|
|
600
618
|
continue;
|