@aztec/p2p 4.0.0-nightly.20260111 → 4.0.0-nightly.20260113
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/interface.d.ts +18 -5
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +9 -12
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +59 -103
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +61 -42
- 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 +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 +225 -262
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +21 -18
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +113 -108
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -16
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +89 -128
- package/dest/mem_pools/attestation_pool/mocks.d.ts +7 -6
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +9 -8
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -4
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +12 -10
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -5
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +5 -5
- package/dest/msg_validators/index.d.ts +2 -2
- package/dest/msg_validators/index.d.ts.map +1 -1
- package/dest/msg_validators/index.js +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
- package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/index.js +3 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/{block_proposal_validator/block_proposal_validator.js → proposal_validator/proposal_validator.js} +19 -21
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +183 -0
- package/dest/services/dummy_service.d.ts +6 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +3 -0
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +4 -2
- package/dest/services/libp2p/libp2p_service.d.ts +26 -10
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +218 -88
- package/dest/services/service.d.ts +16 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +25 -11
- package/dest/testbench/worker_client_manager.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +6 -1
- package/package.json +14 -14
- package/src/client/interface.ts +19 -4
- package/src/client/p2p_client.ts +69 -110
- package/src/mem_pools/attestation_pool/attestation_pool.ts +68 -41
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +231 -287
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +162 -140
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -164
- package/src/mem_pools/attestation_pool/mocks.ts +13 -9
- package/src/msg_validators/attestation_validator/attestation_validator.ts +16 -13
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +7 -7
- package/src/msg_validators/index.ts +1 -1
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
- package/src/msg_validators/proposal_validator/index.ts +3 -0
- package/src/msg_validators/{block_proposal_validator/block_proposal_validator.ts → proposal_validator/proposal_validator.ts} +23 -28
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +206 -0
- package/src/services/dummy_service.ts +6 -0
- package/src/services/encoding.ts +3 -1
- package/src/services/libp2p/libp2p_service.ts +258 -94
- package/src/services/service.ts +19 -4
- package/src/testbench/p2p_client_testbench_worker.ts +34 -11
- package/src/testbench/worker_client_manager.ts +6 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.js +0 -1
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,60 +1,93 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
2
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
3
|
+
import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
|
|
3
4
|
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
4
5
|
import { ATTESTATION_CAP_BUFFER, MAX_PROPOSALS_PER_SLOT } from './kv_attestation_pool.js';
|
|
5
6
|
export class InMemoryAttestationPool {
|
|
6
7
|
log;
|
|
7
8
|
metrics;
|
|
8
|
-
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
9
|
-
attestations;
|
|
10
9
|
proposals;
|
|
10
|
+
// Checkpoint attestations
|
|
11
|
+
// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
12
|
+
checkpointAttestations;
|
|
13
|
+
checkpointProposals;
|
|
11
14
|
constructor(telemetry = getTelemetryClient(), log = createLogger('p2p:attestation_pool')){
|
|
12
15
|
this.log = log;
|
|
13
16
|
this.poolStats = ()=>{
|
|
14
17
|
return Promise.resolve({
|
|
15
|
-
itemCount: this.
|
|
18
|
+
itemCount: this.checkpointAttestations.size
|
|
16
19
|
});
|
|
17
20
|
};
|
|
18
|
-
this.attestations = new Map();
|
|
19
21
|
this.proposals = new Map();
|
|
22
|
+
this.checkpointAttestations = new Map();
|
|
23
|
+
this.checkpointProposals = new Map();
|
|
20
24
|
this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL, this.poolStats);
|
|
21
25
|
}
|
|
22
26
|
poolStats;
|
|
23
27
|
isEmpty() {
|
|
24
|
-
return Promise.resolve(this.
|
|
28
|
+
return Promise.resolve(this.checkpointAttestations.size === 0 && this.proposals.size === 0);
|
|
25
29
|
}
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
addBlockProposal(blockProposal) {
|
|
31
|
+
// Strip signedTxs before storing to avoid holding full tx data in memory
|
|
32
|
+
this.proposals.set(blockProposal.archive.toString(), blockProposal.withoutSignedTxs());
|
|
33
|
+
return Promise.resolve();
|
|
28
34
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
getBlockProposal(id) {
|
|
36
|
+
return Promise.resolve(this.proposals.get(id));
|
|
37
|
+
}
|
|
38
|
+
hasBlockProposal(idOrProposal) {
|
|
39
|
+
const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.archive.toString();
|
|
40
|
+
return Promise.resolve(this.proposals.has(id));
|
|
41
|
+
}
|
|
42
|
+
canAddProposal(_block) {
|
|
43
|
+
// TODO(palla/mbps): See when to allow
|
|
44
|
+
return Promise.resolve(true);
|
|
45
|
+
}
|
|
46
|
+
// Checkpoint attestation methods
|
|
47
|
+
async addCheckpointProposal(proposal) {
|
|
48
|
+
if (!await this.canAddCheckpointProposal(proposal)) {
|
|
49
|
+
throw new ProposalSlotCapExceededError(`Maximum checkpoint proposals per slot reached: slot=${proposal.slotNumber} cap=${MAX_PROPOSALS_PER_SLOT} proposal=${proposal.archive.toString()}`);
|
|
36
50
|
}
|
|
37
|
-
|
|
51
|
+
// Extract and validate the block proposal if present
|
|
52
|
+
const blockProposal = proposal.getBlockProposal();
|
|
53
|
+
if (blockProposal && !await this.canAddProposal(blockProposal)) {
|
|
54
|
+
throw new ProposalSlotCapExceededError(`Maximum block proposals per slot reached when extracting from checkpoint: slot=${proposal.slotNumber} proposal=${blockProposal.archive.toString()}`);
|
|
55
|
+
}
|
|
56
|
+
const slotProposalMapping = getCheckpointSlotOrDefault(this.checkpointAttestations, proposal.slotNumber);
|
|
57
|
+
slotProposalMapping.set(proposal.archive.toString(), new Map());
|
|
58
|
+
// Store the checkpoint proposal as core (without lastBlock) to avoid duplication
|
|
59
|
+
this.checkpointProposals.set(proposal.archive.toString(), proposal.toCore());
|
|
60
|
+
// Store the extracted block proposal separately
|
|
61
|
+
if (blockProposal) {
|
|
62
|
+
this.proposals.set(blockProposal.archive.toString(), blockProposal.withoutSignedTxs());
|
|
63
|
+
}
|
|
64
|
+
return Promise.resolve();
|
|
65
|
+
}
|
|
66
|
+
getCheckpointProposal(id) {
|
|
67
|
+
return Promise.resolve(this.checkpointProposals.get(id));
|
|
38
68
|
}
|
|
39
|
-
|
|
69
|
+
hasCheckpointProposal(idOrProposal) {
|
|
70
|
+
const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.archive.toString();
|
|
71
|
+
return Promise.resolve(this.checkpointProposals.has(id));
|
|
72
|
+
}
|
|
73
|
+
addCheckpointAttestations(attestations) {
|
|
40
74
|
for (const attestation of attestations){
|
|
41
|
-
// Perf: order and group by slot before insertion
|
|
42
75
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
43
76
|
const proposalId = attestation.archive.toString();
|
|
44
77
|
const sender = attestation.getSender();
|
|
45
78
|
// Skip attestations with invalid signatures
|
|
46
79
|
if (!sender) {
|
|
47
|
-
this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber}`, {
|
|
80
|
+
this.log.warn(`Skipping checkpoint attestation with invalid signature for slot ${slotNumber}`, {
|
|
48
81
|
signature: attestation.signature.toString(),
|
|
49
82
|
slotNumber,
|
|
50
83
|
proposalId
|
|
51
84
|
});
|
|
52
85
|
continue;
|
|
53
86
|
}
|
|
54
|
-
const slotAttestationMap =
|
|
55
|
-
const proposalAttestationMap =
|
|
87
|
+
const slotAttestationMap = getCheckpointSlotOrDefault(this.checkpointAttestations, slotNumber);
|
|
88
|
+
const proposalAttestationMap = getCheckpointProposalOrDefault(slotAttestationMap, proposalId);
|
|
56
89
|
proposalAttestationMap.set(sender.toString(), attestation);
|
|
57
|
-
this.log.verbose(`Added attestation for slot ${slotNumber} from ${sender}`, {
|
|
90
|
+
this.log.verbose(`Added checkpoint attestation for slot ${slotNumber} from ${sender}`, {
|
|
58
91
|
signature: attestation.signature.toString(),
|
|
59
92
|
slotNumber,
|
|
60
93
|
address: sender,
|
|
@@ -63,22 +96,22 @@ export class InMemoryAttestationPool {
|
|
|
63
96
|
}
|
|
64
97
|
return Promise.resolve();
|
|
65
98
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
99
|
+
getCheckpointAttestationsForSlot(slot) {
|
|
100
|
+
return Promise.resolve(Array.from(this.checkpointAttestations.get(slot)?.values() ?? []).flatMap((proposalAttestationMap)=>Array.from(proposalAttestationMap.values())));
|
|
101
|
+
}
|
|
102
|
+
getCheckpointAttestationsForSlotAndProposal(slot, proposalId) {
|
|
103
|
+
const slotAttestationMap = this.checkpointAttestations.get(slot);
|
|
69
104
|
if (slotAttestationMap) {
|
|
70
|
-
|
|
71
|
-
|
|
105
|
+
const proposalAttestationMap = slotAttestationMap.get(proposalId);
|
|
106
|
+
if (proposalAttestationMap) {
|
|
107
|
+
return Promise.resolve(Array.from(proposalAttestationMap.values()));
|
|
72
108
|
}
|
|
73
109
|
}
|
|
74
|
-
return
|
|
110
|
+
return Promise.resolve([]);
|
|
75
111
|
}
|
|
76
|
-
|
|
112
|
+
deleteCheckpointAttestationsOlderThan(oldestSlot) {
|
|
77
113
|
const olderThan = [];
|
|
78
|
-
|
|
79
|
-
// Note: this will only prune correctly if attestations are added in order of rising slot, it is important that we do not allow
|
|
80
|
-
// insertion of attestations that are old. #(https://github.com/AztecProtocol/aztec-packages/issues/10322)
|
|
81
|
-
const slots = this.attestations.keys();
|
|
114
|
+
const slots = this.checkpointAttestations.keys();
|
|
82
115
|
for (const slot of slots){
|
|
83
116
|
if (slot < oldestSlot) {
|
|
84
117
|
olderThan.push(slot);
|
|
@@ -87,57 +120,32 @@ export class InMemoryAttestationPool {
|
|
|
87
120
|
}
|
|
88
121
|
}
|
|
89
122
|
for (const oldSlot of olderThan){
|
|
90
|
-
|
|
123
|
+
const proposalIds = this.checkpointAttestations.get(oldSlot)?.keys();
|
|
124
|
+
proposalIds?.forEach((proposalId)=>this.checkpointProposals.delete(proposalId));
|
|
125
|
+
this.checkpointAttestations.delete(oldSlot);
|
|
91
126
|
}
|
|
92
127
|
return Promise.resolve();
|
|
93
128
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
let proposalIdsToDeleteCount = 0;
|
|
99
|
-
proposalIdsToDelete?.forEach((proposalId)=>{
|
|
100
|
-
this.proposals.delete(proposalId);
|
|
101
|
-
proposalIdsToDeleteCount++;
|
|
102
|
-
});
|
|
103
|
-
this.attestations.delete(slot);
|
|
104
|
-
this.log.verbose(`Removed ${numberOfAttestations} attestations and ${proposalIdsToDeleteCount} proposals for slot ${slot}`);
|
|
105
|
-
return Promise.resolve();
|
|
129
|
+
hasReachedCheckpointProposalCap(slot) {
|
|
130
|
+
const slotAttestationMap = this.checkpointAttestations.get(slot);
|
|
131
|
+
const proposalCount = slotAttestationMap?.size ?? 0;
|
|
132
|
+
return Promise.resolve(proposalCount >= MAX_PROPOSALS_PER_SLOT);
|
|
106
133
|
}
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const numberOfAttestations = slotAttestationMap.get(proposalId)?.size ?? 0;
|
|
112
|
-
slotAttestationMap.delete(proposalId);
|
|
113
|
-
this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
this.proposals.delete(proposalId);
|
|
117
|
-
return Promise.resolve();
|
|
134
|
+
hasReachedCheckpointAttestationCap(slot, proposalId, committeeSize) {
|
|
135
|
+
const limit = committeeSize + ATTESTATION_CAP_BUFFER;
|
|
136
|
+
const count = this.checkpointAttestations.get(slot)?.get(proposalId)?.size ?? 0;
|
|
137
|
+
return Promise.resolve(limit <= 0 || count >= limit);
|
|
118
138
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const slotNumber = attestation.payload.header.slotNumber;
|
|
122
|
-
const slotAttestationMap = this.attestations.get(slotNumber);
|
|
123
|
-
if (slotAttestationMap) {
|
|
124
|
-
const proposalId = attestation.archive.toString();
|
|
125
|
-
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
126
|
-
if (proposalAttestationMap) {
|
|
127
|
-
const sender = attestation.getSender();
|
|
128
|
-
// Skip attestations with invalid signatures
|
|
129
|
-
if (!sender) {
|
|
130
|
-
this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber}`);
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
proposalAttestationMap.delete(sender.toString());
|
|
134
|
-
this.log.debug(`Deleted attestation for slot ${slotNumber} from ${sender}`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return Promise.resolve();
|
|
139
|
+
async canAddCheckpointProposal(proposal) {
|
|
140
|
+
return this.checkpointProposals.has(proposal.archive.toString()) || !await this.hasReachedCheckpointProposalCap(proposal.slotNumber);
|
|
139
141
|
}
|
|
140
|
-
|
|
142
|
+
async canAddCheckpointAttestation(attestation, committeeSize) {
|
|
143
|
+
const sender = attestation.getSender();
|
|
144
|
+
const slot = attestation.payload.header.slotNumber;
|
|
145
|
+
const pid = attestation.archive.toString();
|
|
146
|
+
return !!sender && ((this.checkpointAttestations.get(slot)?.get(pid)?.has(sender.toString()) ?? false) || !await this.hasReachedCheckpointAttestationCap(slot, pid, committeeSize));
|
|
147
|
+
}
|
|
148
|
+
hasCheckpointAttestation(attestation) {
|
|
141
149
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
142
150
|
const proposalId = attestation.archive.toString();
|
|
143
151
|
const sender = attestation.getSender();
|
|
@@ -145,7 +153,7 @@ export class InMemoryAttestationPool {
|
|
|
145
153
|
if (!sender) {
|
|
146
154
|
return Promise.resolve(false);
|
|
147
155
|
}
|
|
148
|
-
const slotAttestationMap = this.
|
|
156
|
+
const slotAttestationMap = this.checkpointAttestations.get(slotNumber);
|
|
149
157
|
if (!slotAttestationMap) {
|
|
150
158
|
return Promise.resolve(false);
|
|
151
159
|
}
|
|
@@ -155,63 +163,16 @@ export class InMemoryAttestationPool {
|
|
|
155
163
|
}
|
|
156
164
|
return Promise.resolve(proposalAttestationMap.has(sender.toString()));
|
|
157
165
|
}
|
|
158
|
-
addBlockProposal(blockProposal) {
|
|
159
|
-
// We initialize slot-proposal mapping if it does not exist
|
|
160
|
-
// This is important to ensure we can delete this proposal if there were not attestations for it
|
|
161
|
-
const slotProposalMapping = getSlotOrDefault(this.attestations, blockProposal.slotNumber);
|
|
162
|
-
slotProposalMapping.set(blockProposal.payload.archive.toString(), new Map());
|
|
163
|
-
this.proposals.set(blockProposal.payload.archive.toString(), blockProposal);
|
|
164
|
-
return Promise.resolve();
|
|
165
|
-
}
|
|
166
|
-
getBlockProposal(id) {
|
|
167
|
-
return Promise.resolve(this.proposals.get(id));
|
|
168
|
-
}
|
|
169
|
-
hasBlockProposal(idOrProposal) {
|
|
170
|
-
const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.payload.archive.toString();
|
|
171
|
-
return Promise.resolve(this.proposals.has(id));
|
|
172
|
-
}
|
|
173
|
-
hasReachedProposalCap(slot) {
|
|
174
|
-
const slotAttestationMap = this.attestations.get(slot);
|
|
175
|
-
const proposalCount = slotAttestationMap?.size ?? 0;
|
|
176
|
-
return Promise.resolve(proposalCount >= MAX_PROPOSALS_PER_SLOT);
|
|
177
|
-
}
|
|
178
|
-
hasReachedAttestationCap(slot, proposalId, committeeSize) {
|
|
179
|
-
const limit = committeeSize + ATTESTATION_CAP_BUFFER;
|
|
180
|
-
const count = this.attestations.get(slot)?.get(proposalId)?.size ?? 0;
|
|
181
|
-
return Promise.resolve(limit <= 0 || count >= limit);
|
|
182
|
-
}
|
|
183
|
-
async canAddProposal(block) {
|
|
184
|
-
return this.proposals.has(block.archive.toString()) || !await this.hasReachedProposalCap(block.slotNumber);
|
|
185
|
-
}
|
|
186
|
-
async canAddAttestation(attestation, committeeSize) {
|
|
187
|
-
const sender = attestation.getSender();
|
|
188
|
-
const slot = attestation.payload.header.slotNumber;
|
|
189
|
-
const pid = attestation.archive.toString();
|
|
190
|
-
return !!sender && ((this.attestations.get(slot)?.get(pid)?.has(sender.toString()) ?? false) || !await this.hasReachedAttestationCap(slot, pid, committeeSize));
|
|
191
|
-
}
|
|
192
166
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
*
|
|
196
|
-
* Fetch the slot mapping, if it does not exist, then create a mapping and return it
|
|
197
|
-
* @param map - The map to fetch from
|
|
198
|
-
* @param slot - The slot to fetch
|
|
199
|
-
* @returns The slot mapping
|
|
200
|
-
*/ function getSlotOrDefault(// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
167
|
+
// Checkpoint attestation helper functions
|
|
168
|
+
function getCheckpointSlotOrDefault(// eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
|
|
201
169
|
map, slot) {
|
|
202
170
|
if (!map.has(slot)) {
|
|
203
171
|
map.set(slot, new Map());
|
|
204
172
|
}
|
|
205
173
|
return map.get(slot);
|
|
206
174
|
}
|
|
207
|
-
|
|
208
|
-
* Get Proposal or Default
|
|
209
|
-
*
|
|
210
|
-
* Fetch the proposal mapping, if it does not exist, then create a mapping and return it
|
|
211
|
-
* @param map - The map to fetch from
|
|
212
|
-
* @param proposalId - The proposal id to fetch
|
|
213
|
-
* @returns The proposal mapping
|
|
214
|
-
*/ function getProposalOrDefault(map, proposalId) {
|
|
175
|
+
function getCheckpointProposalOrDefault(map, proposalId) {
|
|
215
176
|
if (!map.has(proposalId)) {
|
|
216
177
|
map.set(proposalId, new Map());
|
|
217
178
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Secp256k1Signer } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
-
import {
|
|
3
|
+
import { CheckpointAttestation } from '@aztec/stdlib/p2p';
|
|
4
4
|
/** Generate Account
|
|
5
5
|
*
|
|
6
6
|
* Create a random signer
|
|
@@ -229,11 +229,12 @@ export declare const generateAccount: () => {
|
|
|
229
229
|
source: string;
|
|
230
230
|
type: "local";
|
|
231
231
|
};
|
|
232
|
-
/** Mock Attestation
|
|
232
|
+
/** Mock Checkpoint Attestation
|
|
233
233
|
*
|
|
234
|
-
* @param signer A
|
|
234
|
+
* @param signer A Secp256k1Signer to create a signature
|
|
235
235
|
* @param slot The slot number the attestation is for
|
|
236
|
-
* @
|
|
236
|
+
* @param archive The archive root (defaults to random)
|
|
237
|
+
* @returns A Checkpoint Attestation
|
|
237
238
|
*/
|
|
238
|
-
export declare const
|
|
239
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
239
|
+
export declare const mockCheckpointAttestation: (signer: Secp256k1Signer, slot?: number, archive?: Fr) => CheckpointAttestation;
|
|
240
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9ja3MuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tZW1fcG9vbHMvYXR0ZXN0YXRpb25fcG9vbC9tb2Nrcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUNqRixPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxFQUNMLHFCQUFxQixFQUl0QixNQUFNLG1CQUFtQixDQUFDO0FBSzNCOzs7O0dBSUc7QUFDSCxlQUFPLE1BQU0sZUFBZTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBRzNCLENBQUM7QUFFRjs7Ozs7O0dBTUc7QUFDSCxlQUFPLE1BQU0seUJBQXlCLGlGQW1CckMsQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mocks.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/mocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"mocks.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/mocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EACL,qBAAqB,EAItB,MAAM,mBAAmB,CAAC;AAK3B;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG3B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,iFAmBrC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
|
-
import {
|
|
2
|
+
import { CheckpointAttestation, ConsensusPayload, SignatureDomainSeparator, getHashedSignaturePayloadEthSignedMessage } from '@aztec/stdlib/p2p';
|
|
3
3
|
import { makeL2BlockHeader } from '@aztec/stdlib/testing';
|
|
4
4
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
5
5
|
/** Generate Account
|
|
@@ -10,18 +10,19 @@ import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
|
10
10
|
const privateKey = generatePrivateKey();
|
|
11
11
|
return privateKeyToAccount(privateKey);
|
|
12
12
|
};
|
|
13
|
-
/** Mock Attestation
|
|
13
|
+
/** Mock Checkpoint Attestation
|
|
14
14
|
*
|
|
15
|
-
* @param signer A
|
|
15
|
+
* @param signer A Secp256k1Signer to create a signature
|
|
16
16
|
* @param slot The slot number the attestation is for
|
|
17
|
-
* @
|
|
18
|
-
|
|
17
|
+
* @param archive The archive root (defaults to random)
|
|
18
|
+
* @returns A Checkpoint Attestation
|
|
19
|
+
*/ export const mockCheckpointAttestation = (signer, slot = 0, archive = Fr.random())=>{
|
|
19
20
|
// Use arbitrary numbers for all other than slot
|
|
20
21
|
const header = makeL2BlockHeader(1, 2, slot);
|
|
21
22
|
const payload = new ConsensusPayload(header.toCheckpointHeader(), archive);
|
|
22
|
-
const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.
|
|
23
|
+
const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.checkpointAttestation);
|
|
23
24
|
const attestationSignature = signer.sign(attestationHash);
|
|
24
|
-
const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.
|
|
25
|
+
const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.checkpointProposal);
|
|
25
26
|
const proposerSignature = signer.sign(proposalHash);
|
|
26
|
-
return new
|
|
27
|
+
return new CheckpointAttestation(payload, attestationSignature, proposerSignature);
|
|
27
28
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
2
|
import { type Logger } from '@aztec/foundation/log';
|
|
3
|
-
import { type
|
|
4
|
-
export declare class
|
|
3
|
+
import { type CheckpointAttestation, type P2PValidator, PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
4
|
+
export declare class CheckpointAttestationValidator implements P2PValidator<CheckpointAttestation> {
|
|
5
5
|
protected epochCache: EpochCacheInterface;
|
|
6
6
|
protected logger: Logger;
|
|
7
7
|
constructor(epochCache: EpochCacheInterface);
|
|
8
|
-
validate(message:
|
|
8
|
+
validate(message: CheckpointAttestation): Promise<PeerErrorSeverity | undefined>;
|
|
9
9
|
}
|
|
10
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZXN0YXRpb25fdmFsaWRhdG9yLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbXNnX3ZhbGlkYXRvcnMvYXR0ZXN0YXRpb25fdmFsaWRhdG9yL2F0dGVzdGF0aW9uX3ZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRTlELE9BQU8sRUFBRSxLQUFLLE1BQU0sRUFBZ0IsTUFBTSx1QkFBdUIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsS0FBSyxxQkFBcUIsRUFBRSxLQUFLLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXJHLHFCQUFhLDhCQUErQixZQUFXLFlBQVksQ0FBQyxxQkFBcUIsQ0FBQztJQUN4RixTQUFTLENBQUMsVUFBVSxFQUFFLG1CQUFtQixDQUFDO0lBQzFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDO0lBRXpCLFlBQVksVUFBVSxFQUFFLG1CQUFtQixFQUcxQztJQUVLLFFBQVEsQ0FBQyxPQUFPLEVBQUUscUJBQXFCLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixHQUFHLFNBQVMsQ0FBQyxDQXdEckY7Q0FDRiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attestation_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/attestation_validator/attestation_validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"attestation_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/attestation_validator/attestation_validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAErG,qBAAa,8BAA+B,YAAW,YAAY,CAAC,qBAAqB,CAAC;IACxF,SAAS,CAAC,UAAU,EAAE,mBAAmB,CAAC;IAC1C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IAEzB,YAAY,UAAU,EAAE,mBAAmB,EAG1C;IAEK,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAwDrF;CACF"}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { NoCommitteeError } from '@aztec/ethereum/contracts';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
4
|
-
export class
|
|
4
|
+
export class CheckpointAttestationValidator {
|
|
5
5
|
epochCache;
|
|
6
6
|
logger;
|
|
7
7
|
constructor(epochCache){
|
|
8
8
|
this.epochCache = epochCache;
|
|
9
|
-
this.logger = createLogger('p2p:attestation-validator');
|
|
9
|
+
this.logger = createLogger('p2p:checkpoint-attestation-validator');
|
|
10
10
|
}
|
|
11
11
|
async validate(message) {
|
|
12
12
|
const slotNumber = message.payload.header.slotNumber;
|
|
13
13
|
try {
|
|
14
|
-
const {
|
|
14
|
+
const { currentSlot, nextSlot } = await this.epochCache.getProposerAttesterAddressInCurrentOrNextSlot();
|
|
15
15
|
if (slotNumber !== currentSlot && slotNumber !== nextSlot) {
|
|
16
|
-
this.logger.warn(`
|
|
16
|
+
this.logger.warn(`Checkpoint attestation slot ${slotNumber} is not current (${currentSlot}) or next (${nextSlot}) slot`);
|
|
17
17
|
return PeerErrorSeverity.HighToleranceError;
|
|
18
18
|
}
|
|
19
19
|
// Verify the signature is valid
|
|
20
20
|
const attester = message.getSender();
|
|
21
21
|
if (attester === undefined) {
|
|
22
|
-
this.logger.warn(`Invalid signature in attestation for slot ${slotNumber}`);
|
|
22
|
+
this.logger.warn(`Invalid signature in checkpoint attestation for slot ${slotNumber}`);
|
|
23
23
|
return PeerErrorSeverity.LowToleranceError;
|
|
24
24
|
}
|
|
25
25
|
// Verify the attester is in the committee for this slot
|
|
@@ -27,26 +27,28 @@ export class AttestationValidator {
|
|
|
27
27
|
this.logger.warn(`Attester ${attester.toString()} is not in committee for slot ${slotNumber}`);
|
|
28
28
|
return PeerErrorSeverity.HighToleranceError;
|
|
29
29
|
}
|
|
30
|
-
// Verify the proposer signature matches the expected proposer for
|
|
30
|
+
// Verify the proposer signature matches the expected proposer for the attestation's slot
|
|
31
|
+
// We look up the proposer for the specific slot rather than using currentSlot/nextSlot
|
|
32
|
+
// since timing differences could cause mismatches
|
|
31
33
|
const proposer = message.getProposer();
|
|
32
|
-
const expectedProposer = slotNumber
|
|
34
|
+
const expectedProposer = await this.epochCache.getProposerAttesterAddressInSlot(slotNumber);
|
|
33
35
|
if (!expectedProposer) {
|
|
34
36
|
this.logger.warn(`No proposer defined for slot ${slotNumber}`);
|
|
35
37
|
return PeerErrorSeverity.HighToleranceError;
|
|
36
38
|
}
|
|
37
39
|
if (!proposer) {
|
|
38
|
-
this.logger.warn(`Invalid proposer signature in attestation for slot ${slotNumber}`);
|
|
40
|
+
this.logger.warn(`Invalid proposer signature in checkpoint attestation for slot ${slotNumber}`);
|
|
39
41
|
return PeerErrorSeverity.LowToleranceError;
|
|
40
42
|
}
|
|
41
43
|
if (!proposer.equals(expectedProposer)) {
|
|
42
|
-
this.logger.warn(`Proposer signature mismatch in attestation. ` + `Expected ${expectedProposer?.toString() ?? 'none'} but got ${proposer.toString()} for slot ${slotNumber}`);
|
|
44
|
+
this.logger.warn(`Proposer signature mismatch in checkpoint attestation. ` + `Expected ${expectedProposer?.toString() ?? 'none'} but got ${proposer.toString()} for slot ${slotNumber}`);
|
|
43
45
|
return PeerErrorSeverity.HighToleranceError;
|
|
44
46
|
}
|
|
45
47
|
return undefined;
|
|
46
48
|
} catch (e) {
|
|
47
49
|
// People shouldn't be sending us attestations if the committee doesn't exist
|
|
48
50
|
if (e instanceof NoCommitteeError) {
|
|
49
|
-
this.logger.warn(`No committee exists for attestation for slot ${slotNumber}`);
|
|
51
|
+
this.logger.warn(`No committee exists for checkpoint attestation for slot ${slotNumber}`);
|
|
50
52
|
return PeerErrorSeverity.LowToleranceError;
|
|
51
53
|
}
|
|
52
54
|
throw e;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import { type
|
|
2
|
+
import { type CheckpointAttestation, PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
3
3
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
4
4
|
import type { AttestationPool } from '../../mem_pools/attestation_pool/attestation_pool.js';
|
|
5
|
-
import {
|
|
5
|
+
import { CheckpointAttestationValidator } from './attestation_validator.js';
|
|
6
6
|
/**
|
|
7
7
|
* FishermanAttestationValidator extends the base AttestationValidator to add
|
|
8
8
|
* additional validation for fisherman nodes: verifying that attestations sign
|
|
@@ -11,10 +11,10 @@ import { AttestationValidator } from './attestation_validator.js';
|
|
|
11
11
|
* handled by LibP2PService based on the fishermanMode config to ensure a better
|
|
12
12
|
* view of the network.
|
|
13
13
|
*/
|
|
14
|
-
export declare class FishermanAttestationValidator extends
|
|
14
|
+
export declare class FishermanAttestationValidator extends CheckpointAttestationValidator {
|
|
15
15
|
private attestationPool;
|
|
16
16
|
private invalidAttestationCounter;
|
|
17
17
|
constructor(epochCache: EpochCacheInterface, attestationPool: AttestationPool, telemetryClient: TelemetryClient);
|
|
18
|
-
validate(message:
|
|
18
|
+
validate(message: CheckpointAttestation): Promise<PeerErrorSeverity | undefined>;
|
|
19
19
|
}
|
|
20
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlzaGVybWFuX2F0dGVzdGF0aW9uX3ZhbGlkYXRvci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21zZ192YWxpZGF0b3JzL2F0dGVzdGF0aW9uX3ZhbGlkYXRvci9maXNoZXJtYW5fYXR0ZXN0YXRpb25fdmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDOUQsT0FBTyxFQUFFLEtBQUsscUJBQXFCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNsRixPQUFPLEVBQXVCLEtBQUssZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFcEYsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0RBQXNELENBQUM7QUFDNUYsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFNUU7Ozs7Ozs7R0FPRztBQUNILHFCQUFhLDZCQUE4QixTQUFRLDhCQUE4QjtJQUs3RSxPQUFPLENBQUMsZUFBZTtJQUp6QixPQUFPLENBQUMseUJBQXlCLENBQUM7SUFFbEMsWUFDRSxVQUFVLEVBQUUsbUJBQW1CLEVBQ3ZCLGVBQWUsRUFBRSxlQUFlLEVBQ3hDLGVBQWUsRUFBRSxlQUFlLEVBT2pDO0lBRWMsUUFBUSxDQUFDLE9BQU8sRUFBRSxxQkFBcUIsR0FBRyxPQUFPLENBQUMsaUJBQWlCLEdBQUcsU0FBUyxDQUFDLENBd0Q5RjtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fisherman_attestation_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/attestation_validator/fisherman_attestation_validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"fisherman_attestation_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/attestation_validator/fisherman_attestation_validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,KAAK,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sDAAsD,CAAC;AAC5F,OAAO,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AAE5E;;;;;;;GAOG;AACH,qBAAa,6BAA8B,SAAQ,8BAA8B;IAK7E,OAAO,CAAC,eAAe;IAJzB,OAAO,CAAC,yBAAyB,CAAC;IAElC,YACE,UAAU,EAAE,mBAAmB,EACvB,eAAe,EAAE,eAAe,EACxC,eAAe,EAAE,eAAe,EAOjC;IAEc,QAAQ,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAwD9F;CACF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
2
2
|
import { Attributes, Metrics } from '@aztec/telemetry-client';
|
|
3
|
-
import {
|
|
3
|
+
import { CheckpointAttestationValidator } from './attestation_validator.js';
|
|
4
4
|
/**
|
|
5
5
|
* FishermanAttestationValidator extends the base AttestationValidator to add
|
|
6
6
|
* additional validation for fisherman nodes: verifying that attestations sign
|
|
@@ -8,7 +8,7 @@ import { AttestationValidator } from './attestation_validator.js';
|
|
|
8
8
|
* Invalid attestations are rejected (not propagated), but peer penalization is
|
|
9
9
|
* handled by LibP2PService based on the fishermanMode config to ensure a better
|
|
10
10
|
* view of the network.
|
|
11
|
-
*/ export class FishermanAttestationValidator extends
|
|
11
|
+
*/ export class FishermanAttestationValidator extends CheckpointAttestationValidator {
|
|
12
12
|
attestationPool;
|
|
13
13
|
invalidAttestationCounter;
|
|
14
14
|
constructor(epochCache, attestationPool, telemetryClient){
|
|
@@ -35,17 +35,17 @@ import { AttestationValidator } from './attestation_validator.js';
|
|
|
35
35
|
return undefined;
|
|
36
36
|
}
|
|
37
37
|
const proposalId = message.archive.toString();
|
|
38
|
-
const proposal = await this.attestationPool.
|
|
38
|
+
const proposal = await this.attestationPool.getCheckpointProposal(proposalId);
|
|
39
39
|
if (proposal) {
|
|
40
40
|
// Compare the attestation payload with the proposal payload
|
|
41
|
-
if (!message.payload.equals(proposal
|
|
41
|
+
if (!message.payload.equals(proposal)) {
|
|
42
42
|
this.logger.error(`Attestation payload mismatch for slot ${slotNumberBigInt}! ` + `Attester ${attester.toString()} signed different data than the proposal.`, {
|
|
43
43
|
slot: slotNumberBigInt.toString(),
|
|
44
44
|
attester: attester.toString(),
|
|
45
45
|
proposer: proposer.toString(),
|
|
46
46
|
proposalArchive: proposal.archive.toString(),
|
|
47
47
|
attestationArchive: message.archive.toString(),
|
|
48
|
-
proposalHeader: proposal.
|
|
48
|
+
proposalHeader: proposal.checkpointHeader.hash().toString(),
|
|
49
49
|
attestationHeader: message.payload.header.hash().toString()
|
|
50
50
|
});
|
|
51
51
|
// Track invalid attestation metric
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from './tx_validator/index.js';
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './proposal_validator/index.js';
|
|
3
3
|
export * from './attestation_validator/index.js';
|
|
4
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tc2dfdmFsaWRhdG9ycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxrQ0FBa0MsQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/msg_validators/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/msg_validators/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
+
import type { BlockProposal, P2PValidator } from '@aztec/stdlib/p2p';
|
|
3
|
+
import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
4
|
+
export declare class BlockProposalValidator extends ProposalValidator<BlockProposal> implements P2PValidator<BlockProposal> {
|
|
5
|
+
constructor(epochCache: EpochCacheInterface, opts: {
|
|
6
|
+
txsPermitted: boolean;
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfcHJvcG9zYWxfdmFsaWRhdG9yLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbXNnX3ZhbGlkYXRvcnMvcHJvcG9zYWxfdmFsaWRhdG9yL2Jsb2NrX3Byb3Bvc2FsX3ZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUVyRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUVoRixxQkFBYSxzQkFBdUIsU0FBUSxpQkFBaUIsQ0FBQyxhQUFhLENBQUUsWUFBVyxZQUFZLENBQUMsYUFBYSxDQUFDO0lBQ2pILFlBQVksVUFBVSxFQUFFLG1CQUFtQixFQUFFLElBQUksRUFBRTtRQUFFLFlBQVksRUFBRSxPQUFPLENBQUE7S0FBRSxFQUUzRTtDQUNGIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block_proposal_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/proposal_validator/block_proposal_validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAEhF,qBAAa,sBAAuB,SAAQ,iBAAiB,CAAC,aAAa,CAAE,YAAW,YAAY,CAAC,aAAa,CAAC;IACjH,YAAY,UAAU,EAAE,mBAAmB,EAAE,IAAI,EAAE;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,EAE3E;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
+
import type { CheckpointProposal, P2PValidator } from '@aztec/stdlib/p2p';
|
|
3
|
+
import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
|
|
4
|
+
export declare class CheckpointProposalValidator extends ProposalValidator<CheckpointProposal> implements P2PValidator<CheckpointProposal> {
|
|
5
|
+
constructor(epochCache: EpochCacheInterface, opts: {
|
|
6
|
+
txsPermitted: boolean;
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF9wcm9wb3NhbF92YWxpZGF0b3IuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tc2dfdmFsaWRhdG9ycy9wcm9wb3NhbF92YWxpZGF0b3IvY2hlY2twb2ludF9wcm9wb3NhbF92YWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUUxRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUVoRixxQkFBYSwyQkFDWCxTQUFRLGlCQUFpQixDQUFDLGtCQUFrQixDQUM1QyxZQUFXLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQztJQUUzQyxZQUFZLFVBQVUsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUU7UUFBRSxZQUFZLEVBQUUsT0FBTyxDQUFBO0tBQUUsRUFFM0U7Q0FDRiJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint_proposal_validator.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAEhF,qBAAa,2BACX,SAAQ,iBAAiB,CAAC,kBAAkB,CAC5C,YAAW,YAAY,CAAC,kBAAkB,CAAC;IAE3C,YAAY,UAAU,EAAE,mBAAmB,EAAE,IAAI,EAAE;QAAE,YAAY,EAAE,OAAO,CAAA;KAAE,EAE3E;CACF"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export * from './block_proposal_validator.js';
|
|
2
|
+
export * from './checkpoint_proposal_validator.js';
|
|
3
|
+
export * from './proposal_validator.js';
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tc2dfdmFsaWRhdG9ycy9wcm9wb3NhbF92YWxpZGF0b3IvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxjQUFjLG9DQUFvQyxDQUFDO0FBQ25ELGNBQWMseUJBQXlCLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/msg_validators/proposal_validator/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,yBAAyB,CAAC"}
|