@aztec/p2p 0.55.1 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/attestation_pool/attestation_pool.d.ts +2 -1
- package/dest/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/attestation_pool/memory_attestation_pool.d.ts +2 -1
- package/dest/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/attestation_pool/memory_attestation_pool.js +48 -15
- package/dest/attestation_pool/mocks.d.ts +2 -1
- package/dest/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/attestation_pool/mocks.js +7 -7
- package/dest/client/index.d.ts +4 -1
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +7 -3
- package/dest/client/p2p_client.d.ts +25 -6
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +28 -15
- package/dest/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts +7 -0
- package/dest/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts.map +1 -0
- package/dest/epoch_proof_quote_pool/epoch_proof_quote_pool.js +2 -0
- package/dest/epoch_proof_quote_pool/index.d.ts +4 -0
- package/dest/epoch_proof_quote_pool/index.d.ts.map +1 -0
- package/dest/epoch_proof_quote_pool/index.js +4 -0
- package/dest/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts +10 -0
- package/dest/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts.map +1 -0
- package/dest/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js +22 -0
- package/dest/epoch_proof_quote_pool/test_utils.d.ts +8 -0
- package/dest/epoch_proof_quote_pool/test_utils.d.ts.map +1 -0
- package/dest/epoch_proof_quote_pool/test_utils.js +21 -0
- package/dest/index.d.ts +4 -3
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +5 -4
- package/dest/mocks/index.d.ts +13 -4
- package/dest/mocks/index.d.ts.map +1 -1
- package/dest/mocks/index.js +26 -9
- package/dest/service/libp2p_service.d.ts +16 -1
- package/dest/service/libp2p_service.d.ts.map +1 -1
- package/dest/service/libp2p_service.js +55 -25
- package/dest/service/reqresp/interface.d.ts +7 -0
- package/dest/service/reqresp/interface.d.ts.map +1 -1
- package/dest/service/reqresp/interface.js +7 -1
- package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts +13 -3
- package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -1
- package/dest/service/reqresp/rate_limiter/rate_limiter.js +29 -7
- package/dest/service/reqresp/reqresp.d.ts +56 -6
- package/dest/service/reqresp/reqresp.d.ts.map +1 -1
- package/dest/service/reqresp/reqresp.js +79 -12
- package/dest/tx_validator/aggregate_tx_validator.d.ts +1 -0
- package/dest/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/tx_validator/aggregate_tx_validator.js +10 -1
- package/dest/tx_validator/data_validator.d.ts +1 -0
- package/dest/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/tx_validator/data_validator.js +4 -1
- package/dest/tx_validator/double_spend_validator.d.ts +1 -0
- package/dest/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/tx_validator/double_spend_validator.js +4 -1
- package/dest/tx_validator/metadata_validator.d.ts +1 -0
- package/dest/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/tx_validator/metadata_validator.js +4 -1
- package/package.json +10 -6
- package/src/attestation_pool/attestation_pool.ts +2 -1
- package/src/attestation_pool/memory_attestation_pool.ts +56 -17
- package/src/attestation_pool/mocks.ts +11 -6
- package/src/client/index.ts +20 -3
- package/src/client/p2p_client.ts +46 -15
- package/src/epoch_proof_quote_pool/epoch_proof_quote_pool.ts +7 -0
- package/src/epoch_proof_quote_pool/index.ts +3 -0
- package/src/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.ts +26 -0
- package/src/epoch_proof_quote_pool/test_utils.ts +26 -0
- package/src/index.ts +4 -3
- package/src/mocks/index.ts +35 -7
- package/src/service/libp2p_service.ts +59 -26
- package/src/service/reqresp/interface.ts +20 -0
- package/src/service/reqresp/rate_limiter/rate_limiter.ts +30 -7
- package/src/service/reqresp/reqresp.ts +91 -13
- package/src/tx_validator/aggregate_tx_validator.ts +10 -0
- package/src/tx_validator/data_validator.ts +4 -0
- package/src/tx_validator/double_spend_validator.ts +4 -0
- package/src/tx_validator/metadata_validator.ts +4 -0
- package/dest/client/mocks.d.ts +0 -65
- package/dest/client/mocks.d.ts.map +0 -1
- package/dest/client/mocks.js +0 -106
- package/src/client/mocks.ts +0 -129
|
@@ -25,6 +25,9 @@ export class MetadataTxValidator {
|
|
|
25
25
|
}
|
|
26
26
|
return Promise.resolve([validTxs, invalidTxs]);
|
|
27
27
|
}
|
|
28
|
+
validateTx(tx) {
|
|
29
|
+
return Promise.resolve(__classPrivateFieldGet(this, _MetadataTxValidator_instances, "m", _MetadataTxValidator_hasCorrectChainId).call(this, tx) && __classPrivateFieldGet(this, _MetadataTxValidator_instances, "m", _MetadataTxValidator_isValidForBlockNumber).call(this, tx));
|
|
30
|
+
}
|
|
28
31
|
}
|
|
29
32
|
_MetadataTxValidator_log = new WeakMap(), _MetadataTxValidator_instances = new WeakSet(), _MetadataTxValidator_hasCorrectChainId = function _MetadataTxValidator_hasCorrectChainId(tx) {
|
|
30
33
|
if (!tx.data.constants.txContext.chainId.equals(this.chainId)) {
|
|
@@ -47,4 +50,4 @@ _MetadataTxValidator_log = new WeakMap(), _MetadataTxValidator_instances = new W
|
|
|
47
50
|
return true;
|
|
48
51
|
}
|
|
49
52
|
};
|
|
50
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0YWRhdGFfdmFsaWRhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3R4X3ZhbGlkYXRvci9tZXRhZGF0YV92YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxPQUFPLEVBQWMsRUFBRSxFQUFvQixNQUFNLHNCQUFzQixDQUFDO0FBRXhFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE1BQU0sT0FBTyxtQkFBbUI7SUFHOUIsWUFBb0IsT0FBVyxFQUFVLFdBQWU7O1FBQXBDLFlBQU8sR0FBUCxPQUFPLENBQUk7UUFBVSxnQkFBVyxHQUFYLFdBQVcsQ0FBSTtRQUZ4RCxtQ0FBTyxpQkFBaUIsQ0FBQywwQ0FBMEMsQ0FBQyxFQUFDO0lBRVYsQ0FBQztJQUU1RCxXQUFXLENBQUMsR0FBUTtRQUNsQixNQUFNLFFBQVEsR0FBUSxFQUFFLENBQUM7UUFDekIsTUFBTSxVQUFVLEdBQVEsRUFBRSxDQUFDO1FBQzNCLEtBQUssTUFBTSxFQUFFLElBQUksR0FBRyxFQUFFLENBQUM7WUFDckIsSUFBSSxDQUFDLHVCQUFBLElBQUksOEVBQW1CLE1BQXZCLElBQUksRUFBb0IsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDakMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsU0FBUztZQUNYLENBQUM7WUFFRCxJQUFJLENBQUMsdUJBQUEsSUFBSSxrRkFBdUIsTUFBM0IsSUFBSSxFQUF3QixFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNyQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNwQixTQUFTO1lBQ1gsQ0FBQztZQUVELFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEIsQ0FBQztRQUVELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRCxVQUFVLENBQUMsRUFBSztRQUNkLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyx1QkFBQSxJQUFJLDhFQUFtQixNQUF2QixJQUFJLEVBQW9CLEVBQUUsQ0FBQyxJQUFJLHVCQUFBLElBQUksa0ZBQXVCLE1BQTNCLElBQUksRUFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN6RixDQUFDO0NBaUNGO21MQS9Cb0IsRUFBSztJQUN0QixJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDOUQsdUJBQUEsSUFBSSxnQ0FBSyxDQUFDLElBQUksQ0FDWixnQkFBZ0IsRUFBRSxDQUFDLE9BQU8sQ0FDeEIsRUFBRSxDQUNILCtCQUErQixFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FDL0csQ0FBQztRQUNGLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDLG1HQUVzQixFQUFLO0lBQzFCLE1BQU0sTUFBTSxHQUNWLEVBQUUsWUFBWSxFQUFFO1FBQ2QsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLHdCQUF3QixJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBVSxDQUFDLGtCQUFrQixDQUFDLFNBQVM7UUFDaEcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUM7SUFDdkMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQztJQUU3QyxJQUFJLGNBQWMsQ0FBQyxNQUFNLElBQUksY0FBYyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDckUsdUJBQUEsSUFBSSxnQ0FBSyxDQUFDLElBQUksQ0FDWixnQkFBZ0IsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsbURBQzVCLGNBQWMsQ0FBQyxLQUNqQiwyQkFBMkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUMvQyxDQUFDO1FBQ0YsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/p2p",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": "./dest/index.js",
|
|
6
6
|
"typedocOptions": {
|
|
@@ -37,6 +37,9 @@
|
|
|
37
37
|
"parser": {
|
|
38
38
|
"syntax": "typescript",
|
|
39
39
|
"decorators": true
|
|
40
|
+
},
|
|
41
|
+
"transform": {
|
|
42
|
+
"decoratorVersion": "2022-03"
|
|
40
43
|
}
|
|
41
44
|
}
|
|
42
45
|
}
|
|
@@ -56,11 +59,11 @@
|
|
|
56
59
|
"testTimeout": 15000
|
|
57
60
|
},
|
|
58
61
|
"dependencies": {
|
|
59
|
-
"@aztec/circuit-types": "0.
|
|
60
|
-
"@aztec/circuits.js": "0.
|
|
61
|
-
"@aztec/foundation": "0.
|
|
62
|
-
"@aztec/kv-store": "0.
|
|
63
|
-
"@aztec/telemetry-client": "0.
|
|
62
|
+
"@aztec/circuit-types": "0.57.0",
|
|
63
|
+
"@aztec/circuits.js": "0.57.0",
|
|
64
|
+
"@aztec/foundation": "0.57.0",
|
|
65
|
+
"@aztec/kv-store": "0.57.0",
|
|
66
|
+
"@aztec/telemetry-client": "0.57.0",
|
|
64
67
|
"@chainsafe/discv5": "9.0.0",
|
|
65
68
|
"@chainsafe/enr": "3.0.0",
|
|
66
69
|
"@chainsafe/libp2p-gossipsub": "13.0.0",
|
|
@@ -86,6 +89,7 @@
|
|
|
86
89
|
"tslib": "^2.4.0"
|
|
87
90
|
},
|
|
88
91
|
"devDependencies": {
|
|
92
|
+
"@aztec/archiver": "workspace:^",
|
|
89
93
|
"@jest/globals": "^29.5.0",
|
|
90
94
|
"@types/jest": "^29.5.0",
|
|
91
95
|
"@types/node": "^18.14.6",
|
|
@@ -36,7 +36,8 @@ export interface AttestationPool {
|
|
|
36
36
|
* Retrieve all of the attestations observed pertaining to a given slot
|
|
37
37
|
*
|
|
38
38
|
* @param slot - The slot to query
|
|
39
|
+
* @param proposalId - The proposal to query
|
|
39
40
|
* @return BlockAttestations
|
|
40
41
|
*/
|
|
41
|
-
getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]>;
|
|
42
|
+
getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]>;
|
|
42
43
|
}
|
|
@@ -4,33 +4,38 @@ import { createDebugLogger } from '@aztec/foundation/log';
|
|
|
4
4
|
import { type AttestationPool } from './attestation_pool.js';
|
|
5
5
|
|
|
6
6
|
export class InMemoryAttestationPool implements AttestationPool {
|
|
7
|
-
private attestations: Map</*slot=*/ bigint, Map</*address=*/ string, BlockAttestation
|
|
7
|
+
private attestations: Map</*slot=*/ bigint, Map</*proposalId*/ string, Map</*address=*/ string, BlockAttestation>>>;
|
|
8
8
|
|
|
9
9
|
constructor(private log = createDebugLogger('aztec:attestation_pool')) {
|
|
10
10
|
this.attestations = new Map();
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
public getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]> {
|
|
13
|
+
public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
|
|
14
14
|
const slotAttestationMap = this.attestations.get(slot);
|
|
15
15
|
if (slotAttestationMap) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const proposalAttestationMap = slotAttestationMap.get(proposalId);
|
|
17
|
+
if (proposalAttestationMap) {
|
|
18
|
+
return Promise.resolve(Array.from(proposalAttestationMap.values()));
|
|
19
|
+
}
|
|
19
20
|
}
|
|
21
|
+
return Promise.resolve([]);
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
public
|
|
24
|
+
public addAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
23
25
|
for (const attestation of attestations) {
|
|
24
26
|
// Perf: order and group by slot before insertion
|
|
25
|
-
const slotNumber = attestation.header.globalVariables.slotNumber;
|
|
27
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
26
28
|
|
|
27
|
-
const
|
|
29
|
+
const proposalId = attestation.p2pMessageIdentifier().toString();
|
|
30
|
+
const address = attestation.getSender();
|
|
28
31
|
|
|
29
32
|
const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt());
|
|
30
|
-
slotAttestationMap
|
|
33
|
+
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
34
|
+
proposalAttestationMap.set(address.toString(), attestation);
|
|
31
35
|
|
|
32
36
|
this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`);
|
|
33
37
|
}
|
|
38
|
+
return Promise.resolve();
|
|
34
39
|
}
|
|
35
40
|
|
|
36
41
|
public deleteAttestationsForSlot(slot: bigint): Promise<void> {
|
|
@@ -40,14 +45,27 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
40
45
|
return Promise.resolve();
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
public
|
|
48
|
+
public deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
|
|
49
|
+
const slotAttestationMap = this.attestations.get(slot);
|
|
50
|
+
if (slotAttestationMap) {
|
|
51
|
+
slotAttestationMap.delete(proposalId);
|
|
52
|
+
this.log.verbose(`Removed attestation for slot ${slot}`);
|
|
53
|
+
}
|
|
54
|
+
return Promise.resolve();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
44
58
|
for (const attestation of attestations) {
|
|
45
|
-
const slotNumber = attestation.header.globalVariables.slotNumber;
|
|
59
|
+
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
46
60
|
const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
|
|
47
61
|
if (slotAttestationMap) {
|
|
48
|
-
const
|
|
49
|
-
slotAttestationMap
|
|
50
|
-
|
|
62
|
+
const proposalId = attestation.p2pMessageIdentifier().toString();
|
|
63
|
+
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
64
|
+
if (proposalAttestationMap) {
|
|
65
|
+
const address = attestation.getSender();
|
|
66
|
+
proposalAttestationMap.delete(address.toString());
|
|
67
|
+
this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
|
|
68
|
+
}
|
|
51
69
|
}
|
|
52
70
|
}
|
|
53
71
|
return Promise.resolve();
|
|
@@ -58,13 +76,34 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
58
76
|
* Get Slot or Default
|
|
59
77
|
*
|
|
60
78
|
* Fetch the slot mapping, if it does not exist, then create a mapping and return it
|
|
79
|
+
* @param map - The map to fetch from
|
|
80
|
+
* @param slot - The slot to fetch
|
|
81
|
+
* @returns The slot mapping
|
|
61
82
|
*/
|
|
62
83
|
function getSlotOrDefault(
|
|
63
|
-
map: Map<bigint, Map<string, BlockAttestation
|
|
84
|
+
map: Map<bigint, Map<string, Map<string, BlockAttestation>>>,
|
|
64
85
|
slot: bigint,
|
|
65
|
-
): Map<string, BlockAttestation
|
|
86
|
+
): Map<string, Map<string, BlockAttestation>> {
|
|
66
87
|
if (!map.has(slot)) {
|
|
67
|
-
map.set(slot, new Map<string, BlockAttestation
|
|
88
|
+
map.set(slot, new Map<string, Map<string, BlockAttestation>>());
|
|
68
89
|
}
|
|
69
90
|
return map.get(slot)!;
|
|
70
91
|
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get Proposal or Default
|
|
95
|
+
*
|
|
96
|
+
* Fetch the proposal mapping, if it does not exist, then create a mapping and return it
|
|
97
|
+
* @param map - The map to fetch from
|
|
98
|
+
* @param proposalId - The proposal id to fetch
|
|
99
|
+
* @returns The proposal mapping
|
|
100
|
+
*/
|
|
101
|
+
function getProposalOrDefault(
|
|
102
|
+
map: Map<string, Map<string, BlockAttestation>>,
|
|
103
|
+
proposalId: string,
|
|
104
|
+
): Map<string, BlockAttestation> {
|
|
105
|
+
if (!map.has(proposalId)) {
|
|
106
|
+
map.set(proposalId, new Map<string, BlockAttestation>());
|
|
107
|
+
}
|
|
108
|
+
return map.get(proposalId)!;
|
|
109
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BlockAttestation,
|
|
1
|
+
import { BlockAttestation, ConsensusPayload, TxHash } from '@aztec/circuit-types';
|
|
2
2
|
import { makeHeader } from '@aztec/circuits.js/testing';
|
|
3
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
3
4
|
import { Fr } from '@aztec/foundation/fields';
|
|
4
|
-
import { serializeToBuffer } from '@aztec/foundation/serialize';
|
|
5
5
|
|
|
6
6
|
import { type PrivateKeyAccount } from 'viem';
|
|
7
7
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
@@ -22,15 +22,20 @@ export const generateAccount = () => {
|
|
|
22
22
|
* @param slot The slot number the attestation is for
|
|
23
23
|
* @returns A Block Attestation
|
|
24
24
|
*/
|
|
25
|
-
export const mockAttestation = async (
|
|
25
|
+
export const mockAttestation = async (
|
|
26
|
+
signer: PrivateKeyAccount,
|
|
27
|
+
slot: number = 0,
|
|
28
|
+
archive: Fr = Fr.random(),
|
|
29
|
+
): Promise<BlockAttestation> => {
|
|
26
30
|
// Use arbitrary numbers for all other than slot
|
|
27
31
|
const header = makeHeader(1, 2, slot);
|
|
28
|
-
const archive = Fr.random();
|
|
29
32
|
const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random());
|
|
30
33
|
|
|
31
|
-
const
|
|
34
|
+
const payload = new ConsensusPayload(header, archive, txs);
|
|
35
|
+
|
|
36
|
+
const message: `0x${string}` = `0x${payload.getPayloadToSign().toString('hex')}`;
|
|
32
37
|
const sigString = await signer.signMessage({ message });
|
|
33
38
|
|
|
34
39
|
const signature = Signature.from0xString(sigString);
|
|
35
|
-
return new BlockAttestation(
|
|
40
|
+
return new BlockAttestation(payload, signature);
|
|
36
41
|
};
|
package/src/client/index.ts
CHANGED
|
@@ -6,8 +6,11 @@ import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
|
6
6
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
7
7
|
|
|
8
8
|
import { type AttestationPool } from '../attestation_pool/attestation_pool.js';
|
|
9
|
+
import { InMemoryAttestationPool } from '../attestation_pool/memory_attestation_pool.js';
|
|
9
10
|
import { P2PClient } from '../client/p2p_client.js';
|
|
10
11
|
import { type P2PConfig } from '../config.js';
|
|
12
|
+
import { type EpochProofQuotePool } from '../epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
13
|
+
import { MemoryEpochProofQuotePool } from '../epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js';
|
|
11
14
|
import { DiscV5Service } from '../service/discV5_service.js';
|
|
12
15
|
import { DummyP2PService } from '../service/dummy_service.js';
|
|
13
16
|
import { LibP2PService, createLibP2PPeerId } from '../service/index.js';
|
|
@@ -18,16 +21,22 @@ export * from './p2p_client.js';
|
|
|
18
21
|
|
|
19
22
|
export const createP2PClient = async (
|
|
20
23
|
_config: P2PConfig & DataStoreConfig,
|
|
21
|
-
attestationsPool: AttestationPool,
|
|
22
24
|
l2BlockSource: L2BlockSource,
|
|
23
25
|
proofVerifier: ClientProtocolCircuitVerifier,
|
|
24
26
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
25
27
|
telemetry: TelemetryClient = new NoopTelemetryClient(),
|
|
26
|
-
deps: {
|
|
28
|
+
deps: {
|
|
29
|
+
txPool?: TxPool;
|
|
30
|
+
store?: AztecKVStore;
|
|
31
|
+
attestationsPool?: AttestationPool;
|
|
32
|
+
epochProofQuotePool?: EpochProofQuotePool;
|
|
33
|
+
} = {},
|
|
27
34
|
) => {
|
|
28
35
|
let config = { ..._config };
|
|
29
36
|
const store = deps.store ?? (await createStore('p2p', config, createDebugLogger('aztec:p2p:lmdb')));
|
|
30
37
|
const txPool = deps.txPool ?? new AztecKVTxPool(store, telemetry);
|
|
38
|
+
const attestationsPool = deps.attestationsPool ?? new InMemoryAttestationPool();
|
|
39
|
+
const epochProofQuotePool = deps.epochProofQuotePool ?? new MemoryEpochProofQuotePool();
|
|
31
40
|
|
|
32
41
|
let p2pService;
|
|
33
42
|
|
|
@@ -52,7 +61,15 @@ export const createP2PClient = async (
|
|
|
52
61
|
} else {
|
|
53
62
|
p2pService = new DummyP2PService();
|
|
54
63
|
}
|
|
55
|
-
return new P2PClient(
|
|
64
|
+
return new P2PClient(
|
|
65
|
+
store,
|
|
66
|
+
l2BlockSource,
|
|
67
|
+
txPool,
|
|
68
|
+
attestationsPool,
|
|
69
|
+
epochProofQuotePool,
|
|
70
|
+
p2pService,
|
|
71
|
+
config.keepProvenTxsInPoolFor,
|
|
72
|
+
);
|
|
56
73
|
};
|
|
57
74
|
|
|
58
75
|
async function configureP2PClientAddresses(_config: P2PConfig & DataStoreConfig): Promise<P2PConfig & DataStoreConfig> {
|
package/src/client/p2p_client.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type BlockAttestation,
|
|
3
3
|
type BlockProposal,
|
|
4
|
+
type EpochProofQuote,
|
|
4
5
|
type L2Block,
|
|
5
6
|
L2BlockDownloader,
|
|
6
7
|
type L2BlockSource,
|
|
@@ -15,6 +16,7 @@ import { type ENR } from '@chainsafe/enr';
|
|
|
15
16
|
|
|
16
17
|
import { type AttestationPool } from '../attestation_pool/attestation_pool.js';
|
|
17
18
|
import { getP2PConfigEnvVars } from '../config.js';
|
|
19
|
+
import { type EpochProofQuotePool } from '../epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
18
20
|
import { TX_REQ_PROTOCOL } from '../service/reqresp/interface.js';
|
|
19
21
|
import type { P2PService } from '../service/service.js';
|
|
20
22
|
import { type TxPool } from '../tx_pool/index.js';
|
|
@@ -58,9 +60,25 @@ export interface P2P {
|
|
|
58
60
|
* Queries the Attestation pool for attestations for the given slot
|
|
59
61
|
*
|
|
60
62
|
* @param slot - the slot to query
|
|
63
|
+
* @param proposalId - the proposal id to query
|
|
61
64
|
* @returns BlockAttestations
|
|
62
65
|
*/
|
|
63
|
-
getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]>;
|
|
66
|
+
getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Queries the EpochProofQuote pool for quotes for the given epoch
|
|
70
|
+
*
|
|
71
|
+
* @param epoch - the epoch to query
|
|
72
|
+
* @returns EpochProofQuotes
|
|
73
|
+
*/
|
|
74
|
+
getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Broadcasts an EpochProofQuote to other peers.
|
|
78
|
+
*
|
|
79
|
+
* @param quote - the quote to broadcast
|
|
80
|
+
*/
|
|
81
|
+
broadcastEpochProofQuote(quote: EpochProofQuote): void;
|
|
64
82
|
|
|
65
83
|
/**
|
|
66
84
|
* Registers a callback from the validator client that determines how to behave when
|
|
@@ -134,7 +152,7 @@ export interface P2P {
|
|
|
134
152
|
* Indicates if the p2p client is ready for transaction submission.
|
|
135
153
|
* @returns A boolean flag indicating readiness.
|
|
136
154
|
*/
|
|
137
|
-
isReady():
|
|
155
|
+
isReady(): boolean;
|
|
138
156
|
|
|
139
157
|
/**
|
|
140
158
|
* Returns the current status of the p2p client.
|
|
@@ -186,6 +204,7 @@ export class P2PClient implements P2P {
|
|
|
186
204
|
private l2BlockSource: L2BlockSource,
|
|
187
205
|
private txPool: TxPool,
|
|
188
206
|
private attestationPool: AttestationPool,
|
|
207
|
+
private epochProofQuotePool: EpochProofQuotePool,
|
|
189
208
|
private p2pService: P2PService,
|
|
190
209
|
private keepProvenTxsFor: number,
|
|
191
210
|
private log = createDebugLogger('aztec:p2p'),
|
|
@@ -202,6 +221,22 @@ export class P2PClient implements P2P {
|
|
|
202
221
|
this.synchedProvenBlockNumber = store.openSingleton('p2p_pool_last_proven_l2_block');
|
|
203
222
|
}
|
|
204
223
|
|
|
224
|
+
#assertIsReady() {
|
|
225
|
+
if (!this.isReady()) {
|
|
226
|
+
throw new Error('P2P client not ready');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]> {
|
|
231
|
+
return Promise.resolve(this.epochProofQuotePool.getQuotes(epoch));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
broadcastEpochProofQuote(quote: EpochProofQuote): void {
|
|
235
|
+
this.#assertIsReady();
|
|
236
|
+
this.epochProofQuotePool.addQuote(quote);
|
|
237
|
+
return this.p2pService.propagate(quote);
|
|
238
|
+
}
|
|
239
|
+
|
|
205
240
|
/**
|
|
206
241
|
* Starts the P2P client.
|
|
207
242
|
* @returns An empty promise signalling the synching process.
|
|
@@ -281,8 +316,8 @@ export class P2PClient implements P2P {
|
|
|
281
316
|
return this.p2pService.propagate(proposal);
|
|
282
317
|
}
|
|
283
318
|
|
|
284
|
-
public getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]> {
|
|
285
|
-
return Promise.resolve(this.attestationPool.getAttestationsForSlot(slot));
|
|
319
|
+
public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
|
|
320
|
+
return Promise.resolve(this.attestationPool.getAttestationsForSlot(slot, proposalId));
|
|
286
321
|
}
|
|
287
322
|
|
|
288
323
|
// REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
@@ -319,8 +354,6 @@ export class P2PClient implements P2P {
|
|
|
319
354
|
|
|
320
355
|
this.log.debug(`Requested ${txHash.toString()} from peer | success = ${!!tx}`);
|
|
321
356
|
if (tx) {
|
|
322
|
-
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8485): This check is not sufficient to validate the transaction. We need to validate the entire proof.
|
|
323
|
-
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/8483): alter peer scoring system for a validator that returns an invalid transcation
|
|
324
357
|
await this.txPool.addTxs([tx]);
|
|
325
358
|
}
|
|
326
359
|
|
|
@@ -365,10 +398,7 @@ export class P2PClient implements P2P {
|
|
|
365
398
|
* @returns Empty promise.
|
|
366
399
|
**/
|
|
367
400
|
public async sendTx(tx: Tx): Promise<void> {
|
|
368
|
-
|
|
369
|
-
if (!ready) {
|
|
370
|
-
throw new Error('P2P client not ready');
|
|
371
|
-
}
|
|
401
|
+
this.#assertIsReady();
|
|
372
402
|
await this.txPool.addTxs([tx]);
|
|
373
403
|
this.p2pService.propagate(tx);
|
|
374
404
|
}
|
|
@@ -393,10 +423,7 @@ export class P2PClient implements P2P {
|
|
|
393
423
|
* @returns Empty promise.
|
|
394
424
|
**/
|
|
395
425
|
public async deleteTxs(txHashes: TxHash[]): Promise<void> {
|
|
396
|
-
|
|
397
|
-
if (!ready) {
|
|
398
|
-
throw new Error('P2P client not ready');
|
|
399
|
-
}
|
|
426
|
+
this.#assertIsReady();
|
|
400
427
|
await this.txPool.deleteTxs(txHashes);
|
|
401
428
|
}
|
|
402
429
|
|
|
@@ -405,7 +432,7 @@ export class P2PClient implements P2P {
|
|
|
405
432
|
* @returns True if the P2P client is ready to receive txs.
|
|
406
433
|
*/
|
|
407
434
|
public isReady() {
|
|
408
|
-
return
|
|
435
|
+
return this.currentState === P2PClientState.RUNNING;
|
|
409
436
|
}
|
|
410
437
|
|
|
411
438
|
/**
|
|
@@ -501,6 +528,10 @@ export class P2PClient implements P2P {
|
|
|
501
528
|
|
|
502
529
|
await this.synchedProvenBlockNumber.set(lastBlockNum);
|
|
503
530
|
this.log.debug(`Synched to proven block ${lastBlockNum}`);
|
|
531
|
+
const provenEpochNumber = await this.l2BlockSource.getProvenL2EpochNumber();
|
|
532
|
+
if (provenEpochNumber !== undefined) {
|
|
533
|
+
this.epochProofQuotePool.deleteQuotesToEpoch(BigInt(provenEpochNumber));
|
|
534
|
+
}
|
|
504
535
|
await this.startServiceIfSynched();
|
|
505
536
|
}
|
|
506
537
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type EpochProofQuote } from '@aztec/circuit-types';
|
|
2
|
+
|
|
3
|
+
import { type EpochProofQuotePool } from './epoch_proof_quote_pool.js';
|
|
4
|
+
|
|
5
|
+
export class MemoryEpochProofQuotePool implements EpochProofQuotePool {
|
|
6
|
+
private quotes: Map<bigint, EpochProofQuote[]>;
|
|
7
|
+
constructor() {
|
|
8
|
+
this.quotes = new Map();
|
|
9
|
+
}
|
|
10
|
+
addQuote(quote: EpochProofQuote) {
|
|
11
|
+
const epoch = quote.payload.epochToProve;
|
|
12
|
+
if (!this.quotes.has(epoch)) {
|
|
13
|
+
this.quotes.set(epoch, []);
|
|
14
|
+
}
|
|
15
|
+
this.quotes.get(epoch)!.push(quote);
|
|
16
|
+
}
|
|
17
|
+
getQuotes(epoch: bigint): EpochProofQuote[] {
|
|
18
|
+
return this.quotes.get(epoch) || [];
|
|
19
|
+
}
|
|
20
|
+
deleteQuotesToEpoch(epoch: bigint): void {
|
|
21
|
+
const expiredEpochs = Array.from(this.quotes.keys()).filter(k => k <= epoch);
|
|
22
|
+
for (const expiredEpoch of expiredEpochs) {
|
|
23
|
+
this.quotes.delete(expiredEpoch);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EpochProofQuote, EpochProofQuotePayload } from '@aztec/circuit-types';
|
|
2
|
+
import { EthAddress } from '@aztec/circuits.js';
|
|
3
|
+
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
4
|
+
import { Secp256k1Signer, randomBigInt, randomInt } from '@aztec/foundation/crypto';
|
|
5
|
+
|
|
6
|
+
export function makeRandomEpochProofQuotePayload(): EpochProofQuotePayload {
|
|
7
|
+
return EpochProofQuotePayload.from({
|
|
8
|
+
basisPointFee: randomInt(10000),
|
|
9
|
+
bondAmount: 1000000000000000000n,
|
|
10
|
+
epochToProve: randomBigInt(1000000n),
|
|
11
|
+
prover: EthAddress.random(),
|
|
12
|
+
validUntilSlot: randomBigInt(1000000n),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function makeRandomEpochProofQuote(payload?: EpochProofQuotePayload): {
|
|
17
|
+
quote: EpochProofQuote;
|
|
18
|
+
signer: Secp256k1Signer;
|
|
19
|
+
} {
|
|
20
|
+
const signer = Secp256k1Signer.random();
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
quote: EpochProofQuote.new(Buffer32.random(), payload ?? makeRandomEpochProofQuotePayload(), signer),
|
|
24
|
+
signer,
|
|
25
|
+
};
|
|
26
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
export * from './attestation_pool/index.js';
|
|
2
|
+
export * from './bootstrap/bootstrap.js';
|
|
1
3
|
export * from './client/index.js';
|
|
2
4
|
export * from './config.js';
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './attestation_pool/index.js';
|
|
5
|
+
export * from './epoch_proof_quote_pool/index.js';
|
|
5
6
|
export * from './service/index.js';
|
|
6
|
-
export * from './
|
|
7
|
+
export * from './tx_pool/index.js';
|
|
7
8
|
export * from './tx_validator/index.js';
|
package/src/mocks/index.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
import { type ClientProtocolCircuitVerifier, type Tx } from '@aztec/circuit-types';
|
|
2
|
+
|
|
1
3
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
2
4
|
import { yamux } from '@chainsafe/libp2p-yamux';
|
|
3
5
|
import { bootstrap } from '@libp2p/bootstrap';
|
|
4
6
|
import { tcp } from '@libp2p/tcp';
|
|
5
7
|
import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p';
|
|
6
8
|
|
|
9
|
+
import { type PeerManager } from '../service/peer_manager.js';
|
|
7
10
|
import { type P2PReqRespConfig } from '../service/reqresp/config.js';
|
|
8
11
|
import { pingHandler, statusHandler } from '../service/reqresp/handlers.js';
|
|
9
12
|
import {
|
|
10
13
|
PING_PROTOCOL,
|
|
11
14
|
type ReqRespSubProtocolHandlers,
|
|
15
|
+
type ReqRespSubProtocolValidators,
|
|
12
16
|
STATUS_PROTOCOL,
|
|
13
17
|
TX_REQ_PROTOCOL,
|
|
18
|
+
noopValidator,
|
|
14
19
|
} from '../service/reqresp/interface.js';
|
|
15
20
|
import { ReqResp } from '../service/reqresp/reqresp.js';
|
|
16
21
|
|
|
@@ -56,18 +61,29 @@ export const MOCK_SUB_PROTOCOL_HANDLERS: ReqRespSubProtocolHandlers = {
|
|
|
56
61
|
[TX_REQ_PROTOCOL]: (_msg: any) => Promise.resolve(Uint8Array.from(Buffer.from('tx'))),
|
|
57
62
|
};
|
|
58
63
|
|
|
64
|
+
// By default, all requests are valid
|
|
65
|
+
// If you want to test an invalid response, you can override the validator
|
|
66
|
+
export const MOCK_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
|
|
67
|
+
[PING_PROTOCOL]: noopValidator,
|
|
68
|
+
[STATUS_PROTOCOL]: noopValidator,
|
|
69
|
+
[TX_REQ_PROTOCOL]: noopValidator,
|
|
70
|
+
};
|
|
71
|
+
|
|
59
72
|
/**
|
|
60
73
|
* @param numberOfNodes - the number of nodes to create
|
|
61
74
|
* @returns An array of the created nodes
|
|
62
75
|
*/
|
|
63
|
-
export const createNodes = async (numberOfNodes: number): Promise<ReqRespNode[]> => {
|
|
64
|
-
return await Promise.all(Array.from({ length: numberOfNodes }, () => createReqResp()));
|
|
76
|
+
export const createNodes = async (peerManager: PeerManager, numberOfNodes: number): Promise<ReqRespNode[]> => {
|
|
77
|
+
return await Promise.all(Array.from({ length: numberOfNodes }, () => createReqResp(peerManager)));
|
|
65
78
|
};
|
|
66
79
|
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
export const startNodes = async (
|
|
81
|
+
nodes: ReqRespNode[],
|
|
82
|
+
subProtocolHandlers = MOCK_SUB_PROTOCOL_HANDLERS,
|
|
83
|
+
subProtocolValidators = MOCK_SUB_PROTOCOL_VALIDATORS,
|
|
84
|
+
) => {
|
|
69
85
|
for (const node of nodes) {
|
|
70
|
-
await node.req.start(subProtocolHandlers);
|
|
86
|
+
await node.req.start(subProtocolHandlers, subProtocolValidators);
|
|
71
87
|
}
|
|
72
88
|
};
|
|
73
89
|
|
|
@@ -79,13 +95,13 @@ export const stopNodes = async (nodes: ReqRespNode[]): Promise<void> => {
|
|
|
79
95
|
};
|
|
80
96
|
|
|
81
97
|
// Create a req resp node, exposing the underlying p2p node
|
|
82
|
-
export const createReqResp = async (): Promise<ReqRespNode> => {
|
|
98
|
+
export const createReqResp = async (peerManager: PeerManager): Promise<ReqRespNode> => {
|
|
83
99
|
const p2p = await createLibp2pNode();
|
|
84
100
|
const config: P2PReqRespConfig = {
|
|
85
101
|
overallRequestTimeoutMs: 4000,
|
|
86
102
|
individualRequestTimeoutMs: 2000,
|
|
87
103
|
};
|
|
88
|
-
const req = new ReqResp(config, p2p);
|
|
104
|
+
const req = new ReqResp(config, p2p, peerManager);
|
|
89
105
|
return {
|
|
90
106
|
p2p,
|
|
91
107
|
req,
|
|
@@ -104,3 +120,15 @@ export const connectToPeers = async (nodes: ReqRespNode[]): Promise<void> => {
|
|
|
104
120
|
}
|
|
105
121
|
}
|
|
106
122
|
};
|
|
123
|
+
|
|
124
|
+
// Mock circuit verifier for testing - reimplementation from bb to avoid dependency
|
|
125
|
+
export class AlwaysTrueCircuitVerifier implements ClientProtocolCircuitVerifier {
|
|
126
|
+
verifyProof(_tx: Tx): Promise<boolean> {
|
|
127
|
+
return Promise.resolve(true);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export class AlwaysFalseCircuitVerifier implements ClientProtocolCircuitVerifier {
|
|
131
|
+
verifyProof(_tx: Tx): Promise<boolean> {
|
|
132
|
+
return Promise.resolve(false);
|
|
133
|
+
}
|
|
134
|
+
}
|