@aztec/p2p 0.67.1 → 0.68.1
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 +5 -3
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +17 -15
- package/dest/client/factory.d.ts +19 -0
- package/dest/client/factory.d.ts.map +1 -0
- package/dest/client/factory.js +40 -0
- package/dest/client/index.d.ts +1 -15
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +2 -37
- package/dest/client/p2p_client.d.ts +6 -6
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +12 -11
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +3 -3
- 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 +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +3 -3
- 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/interface.d.ts +4 -3
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mocks/index.d.ts +7 -6
- package/dest/mocks/index.d.ts.map +1 -1
- package/dest/mocks/index.js +8 -8
- 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 +2 -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 +2 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts +8 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts.map +1 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.js +16 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts +2 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.js +2 -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 +4 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/aggregate_tx_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +34 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/data_validator.js +1 -1
- package/dest/{tx_validator → msg_validators/tx_validator}/double_spend_validator.d.ts +3 -2
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.js +56 -0
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/index.js +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -0
- package/dest/{tx_validator → msg_validators/tx_validator}/metadata_validator.js +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +29 -0
- 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 +3 -9
- package/dest/services/discv5/discV5_service.d.ts.map +1 -0
- package/dest/services/discv5/discV5_service.js +139 -0
- package/dest/services/dummy_service.d.ts.map +1 -0
- package/dest/{service → services}/dummy_service.js +1 -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/services/libp2p/libp2p_service.d.ts +222 -0
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
- package/dest/services/libp2p/libp2p_service.js +697 -0
- package/dest/services/peer-scoring/peer_scoring.d.ts +25 -0
- package/dest/services/peer-scoring/peer_scoring.d.ts.map +1 -0
- package/dest/services/peer-scoring/peer_scoring.js +75 -0
- package/dest/services/peer_manager.d.ts +60 -0
- package/dest/services/peer_manager.d.ts.map +1 -0
- package/dest/services/peer_manager.js +358 -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/{service → services}/reqresp/rate_limiter/rate_limiter.d.ts +0 -5
- package/dest/services/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -0
- package/dest/{service → services}/reqresp/rate_limiter/rate_limiter.js +7 -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/services/reqresp/reqresp.js +279 -0
- package/dest/services/service.d.ts.map +1 -0
- package/dest/{service → services}/service.js +1 -1
- package/dest/services/types.d.ts +38 -0
- package/dest/services/types.d.ts.map +1 -0
- package/dest/services/types.js +43 -0
- package/package.json +14 -11
- package/src/bootstrap/bootstrap.ts +25 -20
- package/src/client/factory.ts +97 -0
- package/src/client/index.ts +1 -73
- package/src/client/p2p_client.ts +28 -15
- package/src/config.ts +2 -2
- package/src/errors/reqresp.error.ts +15 -1
- package/src/index.ts +2 -2
- 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/interface.ts +5 -3
- package/src/mocks/index.ts +16 -10
- 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/epoch_proof_quote_validator/epoch_proof_quote_validator.ts +22 -0
- package/src/msg_validators/epoch_proof_quote_validator/index.ts +1 -0
- package/src/msg_validators/index.ts +3 -0
- package/src/{tx_validator → msg_validators/tx_validator}/aggregate_tx_validator.ts +5 -3
- package/src/{tx_validator → msg_validators/tx_validator}/double_spend_validator.ts +6 -8
- package/src/{service → services/discv5}/discV5_service.ts +19 -23
- package/src/{service → services}/encoding.ts +21 -3
- package/src/services/index.ts +2 -0
- package/src/{service → services/libp2p}/libp2p_service.ts +350 -90
- package/src/{service → services/peer-scoring}/peer_scoring.ts +27 -23
- package/src/services/peer_manager.ts +422 -0
- package/src/{service → services}/reqresp/rate_limiter/rate_limiter.ts +2 -1
- package/src/{service → services}/reqresp/reqresp.ts +86 -20
- package/src/services/types.ts +44 -0
- 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 -144
- 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 +0 -136
- package/dest/service/libp2p_service.d.ts.map +0 -1
- package/dest/service/libp2p_service.js +0 -500
- package/dest/service/peer_manager.d.ts +0 -33
- package/dest/service/peer_manager.d.ts.map +0 -1
- package/dest/service/peer_manager.js +0 -214
- package/dest/service/peer_scoring.d.ts +0 -35
- package/dest/service/peer_scoring.d.ts.map +0 -1
- package/dest/service/peer_scoring.js +0 -72
- 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/reqresp/reqresp.js +0 -230
- package/dest/service/service.d.ts.map +0 -1
- package/dest/tx_validator/aggregate_tx_validator.d.ts.map +0 -1
- package/dest/tx_validator/aggregate_tx_validator.js +0 -32
- package/dest/tx_validator/data_validator.d.ts.map +0 -1
- package/dest/tx_validator/double_spend_validator.d.ts.map +0 -1
- package/dest/tx_validator/double_spend_validator.js +0 -56
- package/dest/tx_validator/index.d.ts.map +0 -1
- package/dest/tx_validator/metadata_validator.d.ts.map +0 -1
- package/dest/tx_validator/tx_proof_validator.d.ts.map +0 -1
- package/dest/tx_validator/tx_proof_validator.js +0 -29
- package/src/service/index.ts +0 -2
- package/src/service/peer_manager.ts +0 -266
- /package/dest/{tx_validator → msg_validators/tx_validator}/data_validator.d.ts +0 -0
- /package/dest/{tx_validator → msg_validators/tx_validator}/index.d.ts +0 -0
- /package/dest/{tx_validator → msg_validators/tx_validator}/metadata_validator.d.ts +0 -0
- /package/dest/{tx_validator → msg_validators/tx_validator}/tx_proof_validator.d.ts +0 -0
- /package/dest/{service → services}/data_store.d.ts +0 -0
- /package/dest/{service → services}/dummy_service.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_limits.d.ts +0 -0
- /package/dest/{service → services}/service.d.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/data_validator.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/index.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/metadata_validator.ts +0 -0
- /package/src/{tx_validator → msg_validators/tx_validator}/tx_proof_validator.ts +0 -0
- /package/src/{service → services}/data_store.ts +0 -0
- /package/src/{service → services}/dummy_service.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/{service → services}/service.ts +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { BlockAttestation } from '@aztec/circuit-types';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import { type AztecKVStore, type AztecMapWithSize, type AztecMultiMap } from '@aztec/kv-store';
|
|
5
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
6
|
+
|
|
7
|
+
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
8
|
+
import { type AttestationPool } from './attestation_pool.js';
|
|
9
|
+
|
|
10
|
+
export class KvAttestationPool implements AttestationPool {
|
|
11
|
+
private metrics: PoolInstrumentation<BlockAttestation>;
|
|
12
|
+
|
|
13
|
+
// Index of all proposal ids in a slot
|
|
14
|
+
private attestations: AztecMultiMap<string, string>;
|
|
15
|
+
|
|
16
|
+
constructor(
|
|
17
|
+
private store: AztecKVStore,
|
|
18
|
+
telemetry: TelemetryClient,
|
|
19
|
+
private log = createLogger('aztec:attestation_pool'),
|
|
20
|
+
) {
|
|
21
|
+
this.attestations = store.openMultiMap('attestations');
|
|
22
|
+
this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private getProposalMapKey(slot: string, proposalId: string): string {
|
|
26
|
+
return `proposal-${slot}-${proposalId}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the proposal map for a given slot and proposalId
|
|
31
|
+
*
|
|
32
|
+
* Essentially a nested mapping of address -> attestation
|
|
33
|
+
*
|
|
34
|
+
* @param slot - The slot to get the proposal map for
|
|
35
|
+
* @param proposalId - The proposalId to get the map for
|
|
36
|
+
* @returns The proposal map
|
|
37
|
+
*/
|
|
38
|
+
private getProposalMap(slot: string, proposalId: string): AztecMapWithSize<string, Buffer> {
|
|
39
|
+
const mapKey = this.getProposalMapKey(slot, proposalId);
|
|
40
|
+
return this.store.openMapWithSize(mapKey);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public async addAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
44
|
+
for (const attestation of attestations) {
|
|
45
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber.toString();
|
|
46
|
+
const proposalId = attestation.archive.toString();
|
|
47
|
+
const address = attestation.getSender().toString();
|
|
48
|
+
|
|
49
|
+
// Index the proposalId in the slot map
|
|
50
|
+
await this.attestations.set(slotNumber, proposalId);
|
|
51
|
+
|
|
52
|
+
// Store the actual attestation in the proposal map
|
|
53
|
+
const proposalMap = this.getProposalMap(slotNumber, proposalId);
|
|
54
|
+
await proposalMap.set(address, attestation.toBuffer());
|
|
55
|
+
|
|
56
|
+
this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this.metrics.recordAddedObjects(attestations.length);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
|
|
63
|
+
const slotNumber = new Fr(slot).toString();
|
|
64
|
+
const proposalMap = this.getProposalMap(slotNumber, proposalId);
|
|
65
|
+
const attestations = proposalMap.values();
|
|
66
|
+
const attestationsArray = Array.from(attestations).map(attestation => BlockAttestation.fromBuffer(attestation));
|
|
67
|
+
return Promise.resolve(attestationsArray);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public async deleteAttestationsOlderThan(oldestSlot: bigint): Promise<void> {
|
|
71
|
+
const olderThan = [];
|
|
72
|
+
|
|
73
|
+
const slots = this.attestations.keys();
|
|
74
|
+
for (const slot of slots) {
|
|
75
|
+
if (BigInt(slot) < oldestSlot) {
|
|
76
|
+
olderThan.push(slot);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await Promise.all(olderThan.map(oldSlot => this.deleteAttestationsForSlot(BigInt(oldSlot))));
|
|
81
|
+
return Promise.resolve();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public async deleteAttestationsForSlot(slot: bigint): Promise<void> {
|
|
85
|
+
const deletionPromises = [];
|
|
86
|
+
|
|
87
|
+
const slotString = new Fr(slot).toString();
|
|
88
|
+
let numberOfAttestations = 0;
|
|
89
|
+
const proposalIds = this.attestations.getValues(slotString);
|
|
90
|
+
|
|
91
|
+
if (proposalIds) {
|
|
92
|
+
for (const proposalId of proposalIds) {
|
|
93
|
+
const proposalMap = this.getProposalMap(slotString, proposalId);
|
|
94
|
+
numberOfAttestations += proposalMap.size();
|
|
95
|
+
deletionPromises.push(proposalMap.clear());
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
await Promise.all(deletionPromises);
|
|
100
|
+
|
|
101
|
+
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
|
|
102
|
+
this.metrics.recordRemovedObjects(numberOfAttestations);
|
|
103
|
+
return Promise.resolve();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public async deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
|
|
107
|
+
const deletionPromises = [];
|
|
108
|
+
|
|
109
|
+
const slotString = new Fr(slot).toString();
|
|
110
|
+
const exists = this.attestations.get(slotString);
|
|
111
|
+
|
|
112
|
+
if (exists) {
|
|
113
|
+
// Remove the proposalId from the slot index
|
|
114
|
+
deletionPromises.push(this.attestations.deleteValue(slotString, proposalId));
|
|
115
|
+
|
|
116
|
+
// Delete all attestations for the proposalId
|
|
117
|
+
const proposalMap = this.getProposalMap(slotString, proposalId);
|
|
118
|
+
const numberOfAttestations = proposalMap.size();
|
|
119
|
+
deletionPromises.push(proposalMap.clear());
|
|
120
|
+
|
|
121
|
+
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
|
|
122
|
+
this.metrics.recordRemovedObjects(numberOfAttestations);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await Promise.all(deletionPromises);
|
|
126
|
+
return Promise.resolve();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public async deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
130
|
+
const deletionPromises = [];
|
|
131
|
+
|
|
132
|
+
for (const attestation of attestations) {
|
|
133
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber.toString();
|
|
134
|
+
const proposalId = attestation.archive.toString();
|
|
135
|
+
const proposalMap = this.getProposalMap(slotNumber, proposalId);
|
|
136
|
+
|
|
137
|
+
if (proposalMap) {
|
|
138
|
+
const address = attestation.getSender().toString();
|
|
139
|
+
deletionPromises.push(proposalMap.delete(address));
|
|
140
|
+
this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (proposalMap.size() === 0) {
|
|
144
|
+
deletionPromises.push(this.attestations.deleteValue(slotNumber, proposalId));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
await Promise.all(deletionPromises);
|
|
149
|
+
|
|
150
|
+
this.metrics.recordRemovedObjects(attestations.length);
|
|
151
|
+
return Promise.resolve();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type P2PClientType } from '@aztec/circuit-types';
|
|
2
|
+
|
|
1
3
|
import { type AttestationPool } from './attestation_pool/attestation_pool.js';
|
|
2
4
|
import { type EpochProofQuotePool } from './epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
3
5
|
import { type TxPool } from './tx_pool/tx_pool.js';
|
|
@@ -5,8 +7,8 @@ import { type TxPool } from './tx_pool/tx_pool.js';
|
|
|
5
7
|
/**
|
|
6
8
|
* A interface the combines all mempools
|
|
7
9
|
*/
|
|
8
|
-
export
|
|
10
|
+
export type MemPools<T extends P2PClientType = P2PClientType.Full> = {
|
|
9
11
|
txPool: TxPool;
|
|
10
|
-
attestationPool:
|
|
12
|
+
attestationPool?: T extends P2PClientType.Full ? AttestationPool : undefined;
|
|
11
13
|
epochProofQuotePool: EpochProofQuotePool;
|
|
12
|
-
}
|
|
14
|
+
};
|
package/src/mocks/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type ClientProtocolCircuitVerifier,
|
|
3
3
|
type L2BlockSource,
|
|
4
|
+
type P2PClientType,
|
|
4
5
|
type Tx,
|
|
5
6
|
type WorldStateSynchronizer,
|
|
6
7
|
} from '@aztec/circuit-types';
|
|
8
|
+
import { type EpochCache } from '@aztec/epoch-cache';
|
|
7
9
|
import { type DataStoreConfig } from '@aztec/kv-store/config';
|
|
8
10
|
import { openTmpStore } from '@aztec/kv-store/lmdb';
|
|
9
11
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
@@ -23,11 +25,11 @@ import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p';
|
|
|
23
25
|
import { BootstrapNode } from '../bootstrap/bootstrap.js';
|
|
24
26
|
import { type BootnodeConfig, type P2PConfig } from '../config.js';
|
|
25
27
|
import { type MemPools } from '../mem_pools/interface.js';
|
|
26
|
-
import { DiscV5Service } from '../
|
|
27
|
-
import { LibP2PService } from '../
|
|
28
|
-
import { type PeerManager } from '../
|
|
29
|
-
import { type P2PReqRespConfig } from '../
|
|
30
|
-
import { pingHandler, statusHandler } from '../
|
|
28
|
+
import { DiscV5Service } from '../services/discv5/discV5_service.js';
|
|
29
|
+
import { LibP2PService } from '../services/libp2p/libp2p_service.js';
|
|
30
|
+
import { type PeerManager } from '../services/peer_manager.js';
|
|
31
|
+
import { type P2PReqRespConfig } from '../services/reqresp/config.js';
|
|
32
|
+
import { pingHandler, statusHandler } from '../services/reqresp/handlers.js';
|
|
31
33
|
import {
|
|
32
34
|
PING_PROTOCOL,
|
|
33
35
|
type ReqRespSubProtocolHandlers,
|
|
@@ -35,8 +37,8 @@ import {
|
|
|
35
37
|
STATUS_PROTOCOL,
|
|
36
38
|
TX_REQ_PROTOCOL,
|
|
37
39
|
noopValidator,
|
|
38
|
-
} from '../
|
|
39
|
-
import { ReqResp } from '../
|
|
40
|
+
} from '../services/reqresp/interface.js';
|
|
41
|
+
import { ReqResp } from '../services/reqresp/reqresp.js';
|
|
40
42
|
import { type PubSubLibp2p } from '../util.js';
|
|
41
43
|
|
|
42
44
|
/**
|
|
@@ -95,11 +97,13 @@ export async function createLibp2pNode(
|
|
|
95
97
|
*
|
|
96
98
|
*
|
|
97
99
|
*/
|
|
98
|
-
export async function createTestLibP2PService(
|
|
100
|
+
export async function createTestLibP2PService<T extends P2PClientType>(
|
|
101
|
+
clientType: T,
|
|
99
102
|
boostrapAddrs: string[] = [],
|
|
100
103
|
l2BlockSource: L2BlockSource,
|
|
101
104
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
102
|
-
|
|
105
|
+
epochCache: EpochCache,
|
|
106
|
+
mempools: MemPools<T>,
|
|
103
107
|
telemetry: TelemetryClient,
|
|
104
108
|
port: number = 0,
|
|
105
109
|
peerId?: PeerId,
|
|
@@ -123,12 +127,14 @@ export async function createTestLibP2PService(
|
|
|
123
127
|
// No bootstrap nodes provided as the libp2p service will register them in the constructor
|
|
124
128
|
const p2pNode = await createLibp2pNode([], peerId, port, /*enable gossip */ true, /**start */ false);
|
|
125
129
|
|
|
126
|
-
return new LibP2PService(
|
|
130
|
+
return new LibP2PService<T>(
|
|
131
|
+
clientType,
|
|
127
132
|
config,
|
|
128
133
|
p2pNode as PubSubLibp2p,
|
|
129
134
|
discoveryService,
|
|
130
135
|
mempools,
|
|
131
136
|
l2BlockSource,
|
|
137
|
+
epochCache,
|
|
132
138
|
proofVerifier,
|
|
133
139
|
worldStateSynchronizer,
|
|
134
140
|
telemetry,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type BlockAttestation, type P2PValidator, PeerErrorSeverity } from '@aztec/circuit-types';
|
|
2
|
+
import { type EpochCache } from '@aztec/epoch-cache';
|
|
3
|
+
|
|
4
|
+
export class AttestationValidator implements P2PValidator<BlockAttestation> {
|
|
5
|
+
private epochCache: EpochCache;
|
|
6
|
+
|
|
7
|
+
constructor(epochCache: EpochCache) {
|
|
8
|
+
this.epochCache = epochCache;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async validate(message: BlockAttestation): Promise<PeerErrorSeverity | undefined> {
|
|
12
|
+
const { currentSlot, nextSlot } = await this.epochCache.getProposerInCurrentOrNextSlot();
|
|
13
|
+
|
|
14
|
+
const slotNumberBigInt = message.payload.header.globalVariables.slotNumber.toBigInt();
|
|
15
|
+
if (slotNumberBigInt !== currentSlot && slotNumberBigInt !== nextSlot) {
|
|
16
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const attester = message.getSender();
|
|
20
|
+
if (!(await this.epochCache.isInCommittee(attester))) {
|
|
21
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './attestation_validator.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type BlockProposal, type P2PValidator, PeerErrorSeverity } from '@aztec/circuit-types';
|
|
2
|
+
import { type EpochCache } from '@aztec/epoch-cache';
|
|
3
|
+
|
|
4
|
+
export class BlockProposalValidator implements P2PValidator<BlockProposal> {
|
|
5
|
+
private epochCache: EpochCache;
|
|
6
|
+
|
|
7
|
+
constructor(epochCache: EpochCache) {
|
|
8
|
+
this.epochCache = epochCache;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async validate(block: BlockProposal): Promise<PeerErrorSeverity | undefined> {
|
|
12
|
+
const { currentProposer, nextProposer, currentSlot, nextSlot } =
|
|
13
|
+
await this.epochCache.getProposerInCurrentOrNextSlot();
|
|
14
|
+
|
|
15
|
+
// Check that the attestation is for the current or next slot
|
|
16
|
+
const slotNumberBigInt = block.payload.header.globalVariables.slotNumber.toBigInt();
|
|
17
|
+
if (slotNumberBigInt !== currentSlot && slotNumberBigInt !== nextSlot) {
|
|
18
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Check that the block proposal is from the current or next proposer
|
|
22
|
+
const proposer = block.getSender();
|
|
23
|
+
if (!proposer.equals(currentProposer) && !proposer.equals(nextProposer)) {
|
|
24
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './block_proposal_validator.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type EpochProofQuote, type P2PValidator, PeerErrorSeverity } from '@aztec/circuit-types';
|
|
2
|
+
import { type EpochCache } from '@aztec/epoch-cache';
|
|
3
|
+
|
|
4
|
+
export class EpochProofQuoteValidator implements P2PValidator<EpochProofQuote> {
|
|
5
|
+
private epochCache: EpochCache;
|
|
6
|
+
|
|
7
|
+
constructor(epochCache: EpochCache) {
|
|
8
|
+
this.epochCache = epochCache;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
validate(message: EpochProofQuote): Promise<PeerErrorSeverity | undefined> {
|
|
12
|
+
const { epoch } = this.epochCache.getEpochAndSlotNow();
|
|
13
|
+
|
|
14
|
+
// Check that the epoch proof quote is for the current epoch
|
|
15
|
+
const epochToProve = message.payload.epochToProve;
|
|
16
|
+
if (epochToProve !== epoch && epochToProve !== epoch - 1n) {
|
|
17
|
+
return Promise.resolve(PeerErrorSeverity.HighToleranceError);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return Promise.resolve(undefined);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EpochProofQuoteValidator } from './epoch_proof_quote_validator.js';
|
|
@@ -10,16 +10,18 @@ export class AggregateTxValidator<T extends Tx | ProcessedTx> implements TxValid
|
|
|
10
10
|
this.#validators = validators;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
async validateTxs(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[]]> {
|
|
13
|
+
async validateTxs(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[], skippedTxs: T[]]> {
|
|
14
14
|
const invalidTxs: T[] = [];
|
|
15
|
+
const skippedTxs: T[] = [];
|
|
15
16
|
let txPool = txs;
|
|
16
17
|
for (const validator of this.#validators) {
|
|
17
|
-
const [valid, invalid] = await validator.validateTxs(txPool);
|
|
18
|
+
const [valid, invalid, skipped] = await validator.validateTxs(txPool);
|
|
18
19
|
invalidTxs.push(...invalid);
|
|
20
|
+
skippedTxs.push(...(skipped ?? []));
|
|
19
21
|
txPool = valid;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
return [txPool, invalidTxs];
|
|
24
|
+
return [txPool, invalidTxs, skippedTxs];
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
async validateTx(tx: T): Promise<boolean> {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { type AnyTx, Tx, type TxValidator } from '@aztec/circuit-types';
|
|
2
|
-
import { Fr } from '@aztec/circuits.js';
|
|
3
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
3
|
|
|
5
4
|
export interface NullifierSource {
|
|
6
|
-
|
|
5
|
+
getNullifierIndices: (nullifiers: Buffer[]) => Promise<(bigint | undefined)[]>;
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
@@ -36,9 +35,7 @@ export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
async #uniqueNullifiers(tx: AnyTx, thisBlockNullifiers: Set<bigint>): Promise<boolean> {
|
|
39
|
-
const nullifiers =
|
|
40
|
-
x.toBigInt(),
|
|
41
|
-
);
|
|
38
|
+
const nullifiers = tx instanceof Tx ? tx.data.getNonEmptyNullifiers() : tx.txEffect.nullifiers;
|
|
42
39
|
|
|
43
40
|
// Ditch this tx if it has repeated nullifiers
|
|
44
41
|
const uniqueNullifiers = new Set(nullifiers);
|
|
@@ -49,16 +46,17 @@ export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
|
49
46
|
|
|
50
47
|
if (this.isValidatingBlock) {
|
|
51
48
|
for (const nullifier of nullifiers) {
|
|
52
|
-
|
|
49
|
+
const nullifierBigInt = nullifier.toBigInt();
|
|
50
|
+
if (thisBlockNullifiers.has(nullifierBigInt)) {
|
|
53
51
|
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating a nullifier in the same block`);
|
|
54
52
|
return false;
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
thisBlockNullifiers.add(
|
|
55
|
+
thisBlockNullifiers.add(nullifierBigInt);
|
|
58
56
|
}
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
const nullifierIndexes = await
|
|
59
|
+
const nullifierIndexes = await this.#nullifierSource.getNullifierIndices(nullifiers.map(n => n.toBuffer()));
|
|
62
60
|
|
|
63
61
|
const hasDuplicates = nullifierIndexes.some(index => index !== undefined);
|
|
64
62
|
if (hasDuplicates) {
|
|
@@ -8,29 +8,19 @@ import type { PeerId } from '@libp2p/interface';
|
|
|
8
8
|
import { type Multiaddr, multiaddr } from '@multiformats/multiaddr';
|
|
9
9
|
import EventEmitter from 'events';
|
|
10
10
|
|
|
11
|
-
import type { P2PConfig } from '
|
|
12
|
-
import { convertToMultiaddr } from '
|
|
13
|
-
import { type PeerDiscoveryService, PeerDiscoveryState } from '
|
|
14
|
-
|
|
15
|
-
export const AZTEC_ENR_KEY = 'aztec_network';
|
|
11
|
+
import type { P2PConfig } from '../../config.js';
|
|
12
|
+
import { convertToMultiaddr } from '../../util.js';
|
|
13
|
+
import { type PeerDiscoveryService, PeerDiscoveryState } from '../service.js';
|
|
14
|
+
import { AZTEC_ENR_KEY, AZTEC_NET, Discv5Event, PeerEvent } from '../types.js';
|
|
16
15
|
|
|
17
16
|
const delayBeforeStart = 2000; // 2sec
|
|
18
17
|
|
|
19
|
-
export enum AztecENR {
|
|
20
|
-
devnet = 0x01,
|
|
21
|
-
testnet = 0x02,
|
|
22
|
-
mainnet = 0x03,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// TODO: Make this an env var
|
|
26
|
-
export const AZTEC_NET = AztecENR.devnet;
|
|
27
|
-
|
|
28
18
|
/**
|
|
29
19
|
* Peer discovery service using Discv5.
|
|
30
20
|
*/
|
|
31
21
|
export class DiscV5Service extends EventEmitter implements PeerDiscoveryService {
|
|
32
22
|
/** The Discv5 instance */
|
|
33
|
-
private discv5: Discv5;
|
|
23
|
+
private discv5: Discv5 & Discv5EventEmitter;
|
|
34
24
|
|
|
35
25
|
/** This instance's ENR */
|
|
36
26
|
private enr: SignableENR;
|
|
@@ -88,13 +78,8 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
88
78
|
metricsRegistry,
|
|
89
79
|
});
|
|
90
80
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const multiAddrTcp = await enr.getFullMultiaddr('tcp');
|
|
94
|
-
const multiAddrUdp = await enr.getFullMultiaddr('udp');
|
|
95
|
-
this.logger.debug(`Added ENR ${enr.encodeTxt()}`, { multiAddrTcp, multiAddrUdp, nodeId: enr.nodeId });
|
|
96
|
-
this.onDiscovered(enr);
|
|
97
|
-
});
|
|
81
|
+
this.discv5.on(Discv5Event.DISCOVERED, this.onDiscovered.bind(this));
|
|
82
|
+
this.discv5.on(Discv5Event.ENR_ADDED, this.onEnrAdded.bind(this));
|
|
98
83
|
}
|
|
99
84
|
|
|
100
85
|
public async start(): Promise<void> {
|
|
@@ -168,10 +153,21 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
168
153
|
}
|
|
169
154
|
|
|
170
155
|
public async stop(): Promise<void> {
|
|
156
|
+
await this.discv5.off(Discv5Event.DISCOVERED, this.onDiscovered);
|
|
157
|
+
await this.discv5.off(Discv5Event.ENR_ADDED, this.onEnrAdded);
|
|
158
|
+
|
|
171
159
|
await this.discv5.stop();
|
|
160
|
+
|
|
172
161
|
this.currentState = PeerDiscoveryState.STOPPED;
|
|
173
162
|
}
|
|
174
163
|
|
|
164
|
+
private async onEnrAdded(enr: ENR) {
|
|
165
|
+
const multiAddrTcp = await enr.getFullMultiaddr('tcp');
|
|
166
|
+
const multiAddrUdp = await enr.getFullMultiaddr('udp');
|
|
167
|
+
this.logger.debug(`Added ENR ${enr.encodeTxt()}`, { multiAddrTcp, multiAddrUdp, nodeId: enr.nodeId });
|
|
168
|
+
this.onDiscovered(enr);
|
|
169
|
+
}
|
|
170
|
+
|
|
175
171
|
private onDiscovered(enr: ENR) {
|
|
176
172
|
// check the peer is an aztec peer
|
|
177
173
|
const value = enr.kvs.get(AZTEC_ENR_KEY);
|
|
@@ -179,7 +175,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
179
175
|
const network = value[0];
|
|
180
176
|
// check if the peer is on the same network
|
|
181
177
|
if (network === AZTEC_NET) {
|
|
182
|
-
this.emit(
|
|
178
|
+
this.emit(PeerEvent.DISCOVERED, enr);
|
|
183
179
|
}
|
|
184
180
|
}
|
|
185
181
|
}
|
|
@@ -49,13 +49,31 @@ export function getMsgIdFn(message: Message) {
|
|
|
49
49
|
return sha256(Buffer.concat(vec)).subarray(0, 20);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Snappy transform for libp2p gossipsub
|
|
54
|
+
*/
|
|
52
55
|
export class SnappyTransform implements DataTransform {
|
|
56
|
+
// Topic string included to satisfy DataTransform interface
|
|
53
57
|
inboundTransform(_topicStr: string, data: Uint8Array): Uint8Array {
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
return this.inboundTransformNoTopic(Buffer.from(data));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public inboundTransformNoTopic(data: Buffer): Buffer {
|
|
62
|
+
if (data.length === 0) {
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
return Buffer.from(uncompressSync(data, { asBuffer: true }));
|
|
56
66
|
}
|
|
57
67
|
|
|
68
|
+
// Topic string included to satisfy DataTransform interface
|
|
58
69
|
outboundTransform(_topicStr: string, data: Uint8Array): Uint8Array {
|
|
59
|
-
return
|
|
70
|
+
return this.outboundTransformNoTopic(Buffer.from(data));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public outboundTransformNoTopic(data: Buffer): Buffer {
|
|
74
|
+
if (data.length === 0) {
|
|
75
|
+
return data;
|
|
76
|
+
}
|
|
77
|
+
return Buffer.from(compressSync(data));
|
|
60
78
|
}
|
|
61
79
|
}
|