@@ -4,30 +4,34 @@ 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
- return Promise . resolve ( Array . from ( slotAttestationMap . values ( ) ) ) ;
17
- } else {
18
- return Promise . resolve ( [ ] ) ;
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
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
27
const slotNumber = attestation . payload . header . globalVariables . slotNumber ;
26
28
29
+ const proposalId = attestation . p2pMessageIdentifier . toString ( ) ;
27
30
const address = attestation . getSender ( ) ;
28
31
29
32
const slotAttestationMap = getSlotOrDefault ( this . attestations , slotNumber . toBigInt ( ) ) ;
30
- slotAttestationMap . set ( address . toString ( ) , attestation ) ;
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
}
@@ -41,14 +45,27 @@ export class InMemoryAttestationPool implements AttestationPool {
41
45
return Promise . resolve ( ) ;
42
46
}
43
47
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
+
44
57
public deleteAttestations ( attestations : BlockAttestation [ ] ) : Promise < void > {
45
58
for ( const attestation of attestations ) {
46
59
const slotNumber = attestation . payload . header . globalVariables . slotNumber ;
47
60
const slotAttestationMap = this . attestations . get ( slotNumber . toBigInt ( ) ) ;
48
61
if ( slotAttestationMap ) {
49
- const address = attestation . getSender ( ) ;
50
- slotAttestationMap . delete ( address . toString ( ) ) ;
51
- this . log . verbose ( `Deleted attestation for slot ${ slotNumber } from ${ address } ` ) ;
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
+ }
52
69
}
53
70
}
54
71
return Promise . resolve ( ) ;
@@ -59,13 +76,34 @@ export class InMemoryAttestationPool implements AttestationPool {
59
76
* Get Slot or Default
60
77
*
61
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
62
82
*/
63
83
function getSlotOrDefault (
64
- map : Map < bigint , Map < string , BlockAttestation > > ,
84
+ map : Map < bigint , Map < string , Map < string , BlockAttestation > > > ,
65
85
slot : bigint ,
66
- ) : Map < string , BlockAttestation > {
86
+ ) : Map < string , Map < string , BlockAttestation > > {
67
87
if ( ! map . has ( slot ) ) {
68
- map . set ( slot , new Map < string , BlockAttestation > ( ) ) ;
88
+ map . set ( slot , new Map < string , Map < string , BlockAttestation > > ( ) ) ;
69
89
}
70
90
return map . get ( slot ) ! ;
71
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
+ }
0 commit comments