github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/operations/attestations/kv/aggregated_test.go (about) 1 package kv 2 3 import ( 4 "context" 5 "sort" 6 "testing" 7 8 fssz "github.com/ferranbt/fastssz" 9 c "github.com/patrickmn/go-cache" 10 "github.com/pkg/errors" 11 types "github.com/prysmaticlabs/eth2-types" 12 "github.com/prysmaticlabs/go-bitfield" 13 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 14 "github.com/prysmaticlabs/prysm/shared/bls" 15 "github.com/prysmaticlabs/prysm/shared/testutil" 16 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 17 "github.com/prysmaticlabs/prysm/shared/testutil/require" 18 ) 19 20 func TestKV_Aggregated_AggregateUnaggregatedAttestations(t *testing.T) { 21 cache := NewAttCaches() 22 priv, err := bls.RandKey() 23 require.NoError(t, err) 24 sig1 := priv.Sign([]byte{'a'}) 25 sig2 := priv.Sign([]byte{'b'}) 26 att1 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b1001}, Signature: sig1.Marshal()}) 27 att2 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b1010}, Signature: sig1.Marshal()}) 28 att3 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b1100}, Signature: sig1.Marshal()}) 29 att4 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b1001}, Signature: sig2.Marshal()}) 30 att5 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b1001}, Signature: sig1.Marshal()}) 31 att6 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b1010}, Signature: sig1.Marshal()}) 32 att7 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b1100}, Signature: sig1.Marshal()}) 33 att8 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b1001}, Signature: sig2.Marshal()}) 34 atts := []*ethpb.Attestation{att1, att2, att3, att4, att5, att6, att7, att8} 35 require.NoError(t, cache.SaveUnaggregatedAttestations(atts)) 36 require.NoError(t, cache.AggregateUnaggregatedAttestations(context.Background())) 37 38 require.Equal(t, 1, len(cache.AggregatedAttestationsBySlotIndex(context.Background(), 1, 0)), "Did not aggregate correctly") 39 require.Equal(t, 1, len(cache.AggregatedAttestationsBySlotIndex(context.Background(), 2, 0)), "Did not aggregate correctly") 40 } 41 42 func TestKV_Aggregated_AggregateUnaggregatedAttestationsBySlotIndex(t *testing.T) { 43 cache := NewAttCaches() 44 genData := func(slot types.Slot, committeeIndex types.CommitteeIndex) *ethpb.AttestationData { 45 return testutil.HydrateAttestationData(ðpb.AttestationData{ 46 Slot: slot, 47 CommitteeIndex: committeeIndex, 48 }) 49 } 50 genSign := func() []byte { 51 priv, err := bls.RandKey() 52 require.NoError(t, err) 53 return priv.Sign([]byte{'a'}).Marshal() 54 } 55 56 atts := []*ethpb.Attestation{ 57 // The first slot. 58 {AggregationBits: bitfield.Bitlist{0b1001}, Data: genData(1, 2), Signature: genSign()}, 59 {AggregationBits: bitfield.Bitlist{0b1010}, Data: genData(1, 2), Signature: genSign()}, 60 {AggregationBits: bitfield.Bitlist{0b1100}, Data: genData(1, 2), Signature: genSign()}, 61 {AggregationBits: bitfield.Bitlist{0b1001}, Data: genData(1, 3), Signature: genSign()}, 62 {AggregationBits: bitfield.Bitlist{0b1100}, Data: genData(1, 3), Signature: genSign()}, 63 // The second slot. 64 {AggregationBits: bitfield.Bitlist{0b1001}, Data: genData(2, 3), Signature: genSign()}, 65 {AggregationBits: bitfield.Bitlist{0b1010}, Data: genData(2, 3), Signature: genSign()}, 66 {AggregationBits: bitfield.Bitlist{0b1100}, Data: genData(2, 4), Signature: genSign()}, 67 } 68 ctx := context.Background() 69 70 // Make sure that no error is produced if aggregation is requested on empty unaggregated list. 71 require.NoError(t, cache.AggregateUnaggregatedAttestationsBySlotIndex(ctx, 1, 2)) 72 require.NoError(t, cache.AggregateUnaggregatedAttestationsBySlotIndex(ctx, 2, 3)) 73 require.Equal(t, 0, len(cache.UnaggregatedAttestationsBySlotIndex(ctx, 1, 2))) 74 require.Equal(t, 0, len(cache.AggregatedAttestationsBySlotIndex(ctx, 1, 2)), "Did not aggregate correctly") 75 require.Equal(t, 0, len(cache.UnaggregatedAttestationsBySlotIndex(ctx, 1, 3))) 76 require.Equal(t, 0, len(cache.AggregatedAttestationsBySlotIndex(ctx, 1, 3)), "Did not aggregate correctly") 77 78 // Persist unaggregated attestations, and aggregate on per slot/committee index base. 79 require.NoError(t, cache.SaveUnaggregatedAttestations(atts)) 80 require.NoError(t, cache.AggregateUnaggregatedAttestationsBySlotIndex(ctx, 1, 2)) 81 require.NoError(t, cache.AggregateUnaggregatedAttestationsBySlotIndex(ctx, 2, 3)) 82 83 // Committee attestations at a slot should be aggregated. 84 require.Equal(t, 0, len(cache.UnaggregatedAttestationsBySlotIndex(ctx, 1, 2))) 85 require.Equal(t, 1, len(cache.AggregatedAttestationsBySlotIndex(ctx, 1, 2)), "Did not aggregate correctly") 86 // Committee attestations haven't been aggregated. 87 require.Equal(t, 2, len(cache.UnaggregatedAttestationsBySlotIndex(ctx, 1, 3))) 88 require.Equal(t, 0, len(cache.AggregatedAttestationsBySlotIndex(ctx, 1, 3)), "Did not aggregate correctly") 89 // Committee at a second slot is aggregated. 90 require.Equal(t, 0, len(cache.UnaggregatedAttestationsBySlotIndex(ctx, 2, 3))) 91 require.Equal(t, 1, len(cache.AggregatedAttestationsBySlotIndex(ctx, 2, 3)), "Did not aggregate correctly") 92 // The second committee at second slot is not aggregated. 93 require.Equal(t, 1, len(cache.UnaggregatedAttestationsBySlotIndex(ctx, 2, 4))) 94 require.Equal(t, 0, len(cache.AggregatedAttestationsBySlotIndex(ctx, 2, 4)), "Did not aggregate correctly") 95 } 96 97 func TestKV_Aggregated_SaveAggregatedAttestation(t *testing.T) { 98 tests := []struct { 99 name string 100 att *ethpb.Attestation 101 count int 102 wantErrString string 103 }{ 104 { 105 name: "nil attestation", 106 att: nil, 107 wantErrString: "attestation can't be nil", 108 }, 109 { 110 name: "nil attestation data", 111 att: ðpb.Attestation{}, 112 wantErrString: "attestation's data can't be nil", 113 }, 114 { 115 name: "not aggregated", 116 att: testutil.HydrateAttestation(ðpb.Attestation{ 117 Data: ðpb.AttestationData{}, AggregationBits: bitfield.Bitlist{0b10100}}), 118 wantErrString: "attestation is not aggregated", 119 }, 120 { 121 name: "invalid hash", 122 att: ðpb.Attestation{ 123 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 124 BeaconBlockRoot: []byte{0b0}, 125 }), 126 AggregationBits: bitfield.Bitlist{0b10111}, 127 }, 128 wantErrString: "could not tree hash attestation: " + fssz.ErrBytesLength.Error(), 129 }, 130 { 131 name: "already seen", 132 att: testutil.HydrateAttestation(ðpb.Attestation{ 133 Data: ðpb.AttestationData{ 134 Slot: 100, 135 }, 136 AggregationBits: bitfield.Bitlist{0b11101001}, 137 }), 138 count: 0, 139 }, 140 { 141 name: "normal save", 142 att: testutil.HydrateAttestation(ðpb.Attestation{ 143 Data: ðpb.AttestationData{ 144 Slot: 1, 145 }, 146 AggregationBits: bitfield.Bitlist{0b1101}, 147 }), 148 count: 1, 149 }, 150 } 151 r, err := hashFn(testutil.HydrateAttestationData(ðpb.AttestationData{ 152 Slot: 100, 153 })) 154 require.NoError(t, err) 155 156 for _, tt := range tests { 157 t.Run(tt.name, func(t *testing.T) { 158 cache := NewAttCaches() 159 cache.seenAtt.Set(string(r[:]), []bitfield.Bitlist{{0xff}}, c.DefaultExpiration) 160 assert.Equal(t, 0, len(cache.unAggregatedAtt), "Invalid start pool, atts: %d", len(cache.unAggregatedAtt)) 161 162 err := cache.SaveAggregatedAttestation(tt.att) 163 if tt.wantErrString != "" { 164 assert.ErrorContains(t, tt.wantErrString, err) 165 } else { 166 assert.NoError(t, err) 167 } 168 assert.Equal(t, tt.count, len(cache.aggregatedAtt), "Wrong attestation count") 169 assert.Equal(t, tt.count, cache.AggregatedAttestationCount(), "Wrong attestation count") 170 }) 171 } 172 } 173 174 func TestKV_Aggregated_SaveAggregatedAttestations(t *testing.T) { 175 tests := []struct { 176 name string 177 atts []*ethpb.Attestation 178 count int 179 wantErrString string 180 }{ 181 { 182 name: "no duplicates", 183 atts: []*ethpb.Attestation{ 184 testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, 185 AggregationBits: bitfield.Bitlist{0b1101}}), 186 testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, 187 AggregationBits: bitfield.Bitlist{0b1101}}), 188 }, 189 count: 1, 190 }, 191 } 192 193 for _, tt := range tests { 194 t.Run(tt.name, func(t *testing.T) { 195 cache := NewAttCaches() 196 assert.Equal(t, 0, len(cache.aggregatedAtt), "Invalid start pool, atts: %d", len(cache.unAggregatedAtt)) 197 err := cache.SaveAggregatedAttestations(tt.atts) 198 if tt.wantErrString != "" { 199 assert.ErrorContains(t, tt.wantErrString, err) 200 } else { 201 assert.NoError(t, err) 202 } 203 assert.Equal(t, tt.count, len(cache.aggregatedAtt), "Wrong attestation count") 204 assert.Equal(t, tt.count, cache.AggregatedAttestationCount(), "Wrong attestation count") 205 }) 206 } 207 } 208 209 func TestKV_Aggregated_SaveAggregatedAttestations_SomeGoodSomeBad(t *testing.T) { 210 tests := []struct { 211 name string 212 atts []*ethpb.Attestation 213 count int 214 wantErrString string 215 }{ 216 { 217 name: "the first attestation is bad", 218 atts: []*ethpb.Attestation{ 219 testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, 220 AggregationBits: bitfield.Bitlist{0b1100}}), 221 testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, 222 AggregationBits: bitfield.Bitlist{0b1101}}), 223 }, 224 count: 1, 225 }, 226 } 227 228 for _, tt := range tests { 229 t.Run(tt.name, func(t *testing.T) { 230 cache := NewAttCaches() 231 assert.Equal(t, 0, len(cache.aggregatedAtt), "Invalid start pool, atts: %d", len(cache.unAggregatedAtt)) 232 err := cache.SaveAggregatedAttestations(tt.atts) 233 if tt.wantErrString != "" { 234 assert.ErrorContains(t, tt.wantErrString, err) 235 } else { 236 assert.NoError(t, err) 237 } 238 assert.Equal(t, tt.count, len(cache.aggregatedAtt), "Wrong attestation count") 239 assert.Equal(t, tt.count, cache.AggregatedAttestationCount(), "Wrong attestation count") 240 }) 241 } 242 } 243 244 func TestKV_Aggregated_AggregatedAttestations(t *testing.T) { 245 cache := NewAttCaches() 246 247 att1 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b1101}}) 248 att2 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b1101}}) 249 att3 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 3}, AggregationBits: bitfield.Bitlist{0b1101}}) 250 atts := []*ethpb.Attestation{att1, att2, att3} 251 252 for _, att := range atts { 253 require.NoError(t, cache.SaveAggregatedAttestation(att)) 254 } 255 256 returned := cache.AggregatedAttestations() 257 sort.Slice(returned, func(i, j int) bool { 258 return returned[i].Data.Slot < returned[j].Data.Slot 259 }) 260 assert.DeepSSZEqual(t, atts, returned) 261 } 262 263 func TestKV_Aggregated_DeleteAggregatedAttestation(t *testing.T) { 264 t.Run("nil attestation", func(t *testing.T) { 265 cache := NewAttCaches() 266 assert.ErrorContains(t, "attestation can't be nil", cache.DeleteAggregatedAttestation(nil)) 267 att := testutil.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b10101}, Data: ðpb.AttestationData{Slot: 2}}) 268 assert.NoError(t, cache.DeleteAggregatedAttestation(att)) 269 }) 270 271 t.Run("non aggregated attestation", func(t *testing.T) { 272 cache := NewAttCaches() 273 att := testutil.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b1001}, Data: ðpb.AttestationData{Slot: 2}}) 274 err := cache.DeleteAggregatedAttestation(att) 275 assert.ErrorContains(t, "attestation is not aggregated", err) 276 }) 277 278 t.Run("invalid hash", func(t *testing.T) { 279 cache := NewAttCaches() 280 att := ðpb.Attestation{ 281 AggregationBits: bitfield.Bitlist{0b1111}, 282 Data: ðpb.AttestationData{ 283 Slot: 2, 284 Source: ðpb.Checkpoint{}, 285 Target: ðpb.Checkpoint{}, 286 }, 287 } 288 err := cache.DeleteAggregatedAttestation(att) 289 wantErr := "could not tree hash attestation data: " + fssz.ErrBytesLength.Error() 290 assert.ErrorContains(t, wantErr, err) 291 }) 292 293 t.Run("nonexistent attestation", func(t *testing.T) { 294 cache := NewAttCaches() 295 att := testutil.HydrateAttestation(ðpb.Attestation{AggregationBits: bitfield.Bitlist{0b1111}, Data: ðpb.AttestationData{Slot: 2}}) 296 assert.NoError(t, cache.DeleteAggregatedAttestation(att)) 297 }) 298 299 t.Run("non-filtered deletion", func(t *testing.T) { 300 cache := NewAttCaches() 301 att1 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b11010}}) 302 att2 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b11010}}) 303 att3 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 3}, AggregationBits: bitfield.Bitlist{0b11010}}) 304 att4 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 3}, AggregationBits: bitfield.Bitlist{0b10101}}) 305 atts := []*ethpb.Attestation{att1, att2, att3, att4} 306 require.NoError(t, cache.SaveAggregatedAttestations(atts)) 307 require.NoError(t, cache.DeleteAggregatedAttestation(att1)) 308 require.NoError(t, cache.DeleteAggregatedAttestation(att3)) 309 310 returned := cache.AggregatedAttestations() 311 wanted := []*ethpb.Attestation{att2} 312 assert.DeepEqual(t, wanted, returned) 313 }) 314 315 t.Run("filtered deletion", func(t *testing.T) { 316 cache := NewAttCaches() 317 att1 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b110101}}) 318 att2 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b110111}}) 319 att3 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b110100}}) 320 att4 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 2}, AggregationBits: bitfield.Bitlist{0b110101}}) 321 atts := []*ethpb.Attestation{att1, att2, att3, att4} 322 require.NoError(t, cache.SaveAggregatedAttestations(atts)) 323 324 assert.Equal(t, 2, cache.AggregatedAttestationCount(), "Unexpected number of atts") 325 require.NoError(t, cache.DeleteAggregatedAttestation(att4)) 326 327 returned := cache.AggregatedAttestations() 328 wanted := []*ethpb.Attestation{att1, att2} 329 sort.Slice(returned, func(i, j int) bool { 330 return string(returned[i].AggregationBits) < string(returned[j].AggregationBits) 331 }) 332 assert.DeepEqual(t, wanted, returned) 333 }) 334 } 335 336 func TestKV_Aggregated_HasAggregatedAttestation(t *testing.T) { 337 tests := []struct { 338 name string 339 existing []*ethpb.Attestation 340 input *ethpb.Attestation 341 want bool 342 err error 343 }{ 344 { 345 name: "nil attestation", 346 input: nil, 347 want: false, 348 err: errors.New("can't be nil"), 349 }, 350 { 351 name: "nil attestation data", 352 input: ðpb.Attestation{ 353 AggregationBits: bitfield.Bitlist{0b1111}, 354 }, 355 want: false, 356 err: errors.New("can't be nil"), 357 }, 358 { 359 name: "empty cache aggregated", 360 input: testutil.HydrateAttestation(ðpb.Attestation{ 361 Data: ðpb.AttestationData{ 362 Slot: 1, 363 }, 364 AggregationBits: bitfield.Bitlist{0b1111}}), 365 want: false, 366 }, 367 { 368 name: "empty cache unaggregated", 369 input: testutil.HydrateAttestation(ðpb.Attestation{ 370 Data: ðpb.AttestationData{ 371 Slot: 1, 372 }, 373 AggregationBits: bitfield.Bitlist{0b1001}}), 374 want: false, 375 }, 376 { 377 name: "single attestation in cache with exact match", 378 existing: []*ethpb.Attestation{{ 379 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 380 Slot: 1, 381 }), 382 AggregationBits: bitfield.Bitlist{0b1111}}, 383 }, 384 input: ðpb.Attestation{ 385 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 386 Slot: 1, 387 }), 388 AggregationBits: bitfield.Bitlist{0b1111}}, 389 want: true, 390 }, 391 { 392 name: "single attestation in cache with subset aggregation", 393 existing: []*ethpb.Attestation{{ 394 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 395 Slot: 1, 396 }), 397 AggregationBits: bitfield.Bitlist{0b1111}}, 398 }, 399 input: ðpb.Attestation{ 400 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 401 Slot: 1, 402 }), 403 AggregationBits: bitfield.Bitlist{0b1110}}, 404 want: true, 405 }, 406 { 407 name: "single attestation in cache with superset aggregation", 408 existing: []*ethpb.Attestation{{ 409 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 410 Slot: 1, 411 }), 412 AggregationBits: bitfield.Bitlist{0b1110}}, 413 }, 414 input: ðpb.Attestation{ 415 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 416 Slot: 1, 417 }), 418 AggregationBits: bitfield.Bitlist{0b1111}}, 419 want: false, 420 }, 421 { 422 name: "multiple attestations with same data in cache with overlapping aggregation, input is subset", 423 existing: []*ethpb.Attestation{ 424 { 425 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 426 Slot: 1, 427 }), 428 AggregationBits: bitfield.Bitlist{0b1111000}, 429 }, 430 { 431 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 432 Slot: 1, 433 }), 434 AggregationBits: bitfield.Bitlist{0b1100111}, 435 }, 436 }, 437 input: ðpb.Attestation{ 438 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 439 Slot: 1, 440 }), 441 AggregationBits: bitfield.Bitlist{0b1100000}}, 442 want: true, 443 }, 444 { 445 name: "multiple attestations with same data in cache with overlapping aggregation and input is superset", 446 existing: []*ethpb.Attestation{ 447 { 448 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 449 Slot: 1, 450 }), 451 AggregationBits: bitfield.Bitlist{0b1111000}, 452 }, 453 { 454 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 455 Slot: 1, 456 }), 457 AggregationBits: bitfield.Bitlist{0b1100111}, 458 }, 459 }, 460 input: ðpb.Attestation{ 461 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 462 Slot: 1, 463 }), 464 AggregationBits: bitfield.Bitlist{0b1111111}}, 465 want: false, 466 }, 467 { 468 name: "multiple attestations with different data in cache", 469 existing: []*ethpb.Attestation{ 470 { 471 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 472 Slot: 2, 473 }), 474 AggregationBits: bitfield.Bitlist{0b1111000}, 475 }, 476 { 477 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 478 Slot: 3, 479 }), 480 AggregationBits: bitfield.Bitlist{0b1100111}, 481 }, 482 }, 483 input: ðpb.Attestation{ 484 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 485 Slot: 1, 486 }), 487 AggregationBits: bitfield.Bitlist{0b1111111}}, 488 want: false, 489 }, 490 { 491 name: "attestations with different bitlist lengths", 492 existing: []*ethpb.Attestation{ 493 { 494 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 495 Slot: 2, 496 }), 497 AggregationBits: bitfield.Bitlist{0b1111000}, 498 }, 499 }, 500 input: ðpb.Attestation{ 501 Data: testutil.HydrateAttestationData(ðpb.AttestationData{ 502 Slot: 2, 503 }), 504 AggregationBits: bitfield.Bitlist{0b1111}, 505 }, 506 want: false, 507 err: bitfield.ErrBitlistDifferentLength, 508 }, 509 } 510 511 for _, tt := range tests { 512 t.Run(tt.name, func(t *testing.T) { 513 cache := NewAttCaches() 514 require.NoError(t, cache.SaveAggregatedAttestations(tt.existing)) 515 516 if tt.input != nil && tt.input.Signature == nil { 517 tt.input.Signature = make([]byte, 96) 518 } 519 520 if tt.err != nil { 521 _, err := cache.HasAggregatedAttestation(tt.input) 522 require.ErrorContains(t, tt.err.Error(), err) 523 } else { 524 result, err := cache.HasAggregatedAttestation(tt.input) 525 require.NoError(t, err) 526 assert.Equal(t, tt.want, result) 527 528 // Same test for block attestations 529 cache = NewAttCaches() 530 assert.NoError(t, cache.SaveBlockAttestations(tt.existing)) 531 532 result, err = cache.HasAggregatedAttestation(tt.input) 533 require.NoError(t, err) 534 assert.Equal(t, tt.want, result) 535 } 536 }) 537 } 538 } 539 540 func TestKV_Aggregated_DuplicateAggregatedAttestations(t *testing.T) { 541 cache := NewAttCaches() 542 543 att1 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b1101}}) 544 att2 := testutil.HydrateAttestation(ðpb.Attestation{Data: ðpb.AttestationData{Slot: 1}, AggregationBits: bitfield.Bitlist{0b1111}}) 545 atts := []*ethpb.Attestation{att1, att2} 546 547 for _, att := range atts { 548 require.NoError(t, cache.SaveAggregatedAttestation(att)) 549 } 550 551 returned := cache.AggregatedAttestations() 552 553 // It should have only returned att2. 554 assert.DeepSSZEqual(t, att2, returned[0], "Did not receive correct aggregated atts") 555 assert.Equal(t, 1, len(returned), "Did not receive correct aggregated atts") 556 }