Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: duplicated block attestations #7455

Merged
merged 5 commits into from
Feb 13, 2025
Merged

Conversation

ensi321
Copy link
Contributor

@ensi321 ensi321 commented Feb 12, 2025

Background

Raise by Teku team on discord https://discord.com/channels/595666850260713488/1338793076491026486/1338793635386228756,

Lodestar will generate duplicated attestations and include them in the block body when proposing.

For example https://dora.pectra-devnet-6.ethpandaops.io/slot/54933 has 6 copies of the same attestation with signature 0xae6b928e4866d5a43ae6d4ced869e3aa53f38617d42da5862c76e9a928942783a108e4e281d208766b8a9b2adb286aff0e0af7c14f24d1b013f4ccb47c000a11c256112fab37945d2e5bb3671b997a23b1d57d67d3fe69835ecc06f1f57b1210 .

This is due to getAttestationsForBlockElectra putting multiple copies of the same attestations in consolidations when there are attestations coming from different committees with the same attestation data.

The above attestation having 6 copies because the attestation contains 6 committees (0, 2, 3, 6, 7 and 12).

Proposal

Remove AttestationsConsolidation.score and convert consolidations to a Map<AttestationsConsolidation, number>() to track the score while eliminating duplicates.

@ensi321 ensi321 requested a review from a team as a code owner February 12, 2025 05:33
Copy link
Contributor

github-actions bot commented Feb 12, 2025

Performance Report

🚀🚀 Significant benchmark improvement detected

Benchmark suite Current: cb4cf70 Previous: e45e0eb Ratio
forkChoice updateHead vc 600000 bc 64 eq 300000 13.465 ms/op 56.830 ms/op 0.24
Full benchmark results
Benchmark suite Current: cb4cf70 Previous: e45e0eb Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 941.18 us/op 967.80 us/op 0.97
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 35.402 us/op 35.981 us/op 0.98
BLS verify - blst 1.2466 ms/op 817.77 us/op 1.52
BLS verifyMultipleSignatures 3 - blst 1.5040 ms/op 1.2220 ms/op 1.23
BLS verifyMultipleSignatures 8 - blst 1.9117 ms/op 1.7056 ms/op 1.12
BLS verifyMultipleSignatures 32 - blst 5.7664 ms/op 4.9317 ms/op 1.17
BLS verifyMultipleSignatures 64 - blst 10.956 ms/op 9.1516 ms/op 1.20
BLS verifyMultipleSignatures 128 - blst 17.490 ms/op 18.359 ms/op 0.95
BLS deserializing 10000 signatures 696.70 ms/op 706.46 ms/op 0.99
BLS deserializing 100000 signatures 6.9952 s/op 7.0843 s/op 0.99
BLS verifyMultipleSignatures - same message - 3 - blst 911.43 us/op 1.1020 ms/op 0.83
BLS verifyMultipleSignatures - same message - 8 - blst 1.2631 ms/op 1.2250 ms/op 1.03
BLS verifyMultipleSignatures - same message - 32 - blst 1.6871 ms/op 2.0611 ms/op 0.82
BLS verifyMultipleSignatures - same message - 64 - blst 2.6007 ms/op 2.9255 ms/op 0.89
BLS verifyMultipleSignatures - same message - 128 - blst 4.4031 ms/op 4.8755 ms/op 0.90
BLS aggregatePubkeys 32 - blst 20.145 us/op 20.260 us/op 0.99
BLS aggregatePubkeys 128 - blst 70.695 us/op 73.051 us/op 0.97
notSeenSlots=1 numMissedVotes=1 numBadVotes=10 50.213 ms/op 69.307 ms/op 0.72
notSeenSlots=1 numMissedVotes=0 numBadVotes=4 45.503 ms/op 58.467 ms/op 0.78
notSeenSlots=2 numMissedVotes=1 numBadVotes=10 40.274 ms/op 43.737 ms/op 0.92
getSlashingsAndExits - default max 74.713 us/op 79.359 us/op 0.94
getSlashingsAndExits - 2k 325.51 us/op 436.31 us/op 0.75
proposeBlockBody type=full, size=empty 5.5304 ms/op 7.5658 ms/op 0.73
isKnown best case - 1 super set check 200.00 ns/op 205.00 ns/op 0.98
isKnown normal case - 2 super set checks 198.00 ns/op 202.00 ns/op 0.98
isKnown worse case - 16 super set checks 198.00 ns/op 195.00 ns/op 1.02
InMemoryCheckpointStateCache - add get delete 2.4240 us/op 2.5090 us/op 0.97
validate api signedAggregateAndProof - struct 2.5862 ms/op 1.5124 ms/op 1.71
validate gossip signedAggregateAndProof - struct 2.5875 ms/op 1.9862 ms/op 1.30
batch validate gossip attestation - vc 640000 - chunk 32 133.09 us/op 161.40 us/op 0.82
batch validate gossip attestation - vc 640000 - chunk 64 112.83 us/op 130.27 us/op 0.87
batch validate gossip attestation - vc 640000 - chunk 128 107.66 us/op 129.12 us/op 0.83
batch validate gossip attestation - vc 640000 - chunk 256 102.11 us/op 137.43 us/op 0.74
pickEth1Vote - no votes 953.83 us/op 2.0641 ms/op 0.46
pickEth1Vote - max votes 9.2834 ms/op 11.642 ms/op 0.80
pickEth1Vote - Eth1Data hashTreeRoot value x2048 18.991 ms/op 20.411 ms/op 0.93
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 21.922 ms/op 31.101 ms/op 0.70
pickEth1Vote - Eth1Data fastSerialize value x2048 440.22 us/op 548.83 us/op 0.80
pickEth1Vote - Eth1Data fastSerialize tree x2048 4.1453 ms/op 5.0010 ms/op 0.83
bytes32 toHexString 365.00 ns/op 406.00 ns/op 0.90
bytes32 Buffer.toString(hex) 237.00 ns/op 243.00 ns/op 0.98
bytes32 Buffer.toString(hex) from Uint8Array 332.00 ns/op 447.00 ns/op 0.74
bytes32 Buffer.toString(hex) + 0x 287.00 ns/op 425.00 ns/op 0.68
Object access 1 prop 0.15800 ns/op 0.16200 ns/op 0.98
Map access 1 prop 0.12400 ns/op 0.19200 ns/op 0.65
Object get x1000 6.1460 ns/op 8.2330 ns/op 0.75
Map get x1000 6.4620 ns/op 6.7410 ns/op 0.96
Object set x1000 30.997 ns/op 54.004 ns/op 0.57
Map set x1000 21.400 ns/op 24.415 ns/op 0.88
Return object 10000 times 0.29310 ns/op 0.32000 ns/op 0.92
Throw Error 10000 times 4.4455 us/op 6.3540 us/op 0.70
toHex 133.16 ns/op 148.09 ns/op 0.90
Buffer.from 124.06 ns/op 179.05 ns/op 0.69
shared Buffer 80.192 ns/op 81.836 ns/op 0.98
fastMsgIdFn sha256 / 200 bytes 2.1770 us/op 2.2940 us/op 0.95
fastMsgIdFn h32 xxhash / 200 bytes 203.00 ns/op 210.00 ns/op 0.97
fastMsgIdFn h64 xxhash / 200 bytes 376.00 ns/op 282.00 ns/op 1.33
fastMsgIdFn sha256 / 1000 bytes 7.3570 us/op 7.6310 us/op 0.96
fastMsgIdFn h32 xxhash / 1000 bytes 424.00 ns/op 346.00 ns/op 1.23
fastMsgIdFn h64 xxhash / 1000 bytes 354.00 ns/op 363.00 ns/op 0.98
fastMsgIdFn sha256 / 10000 bytes 64.970 us/op 68.758 us/op 0.94
fastMsgIdFn h32 xxhash / 10000 bytes 1.8070 us/op 1.9000 us/op 0.95
fastMsgIdFn h64 xxhash / 10000 bytes 1.2090 us/op 1.2580 us/op 0.96
send data - 1000 256B messages 13.985 ms/op 18.147 ms/op 0.77
send data - 1000 512B messages 17.034 ms/op 23.192 ms/op 0.73
send data - 1000 1024B messages 25.364 ms/op 30.094 ms/op 0.84
send data - 1000 1200B messages 28.490 ms/op 26.176 ms/op 1.09
send data - 1000 2048B messages 21.759 ms/op 25.956 ms/op 0.84
send data - 1000 4096B messages 24.605 ms/op 29.951 ms/op 0.82
send data - 1000 16384B messages 88.830 ms/op 78.352 ms/op 1.13
send data - 1000 65536B messages 261.70 ms/op 231.64 ms/op 1.13
enrSubnets - fastDeserialize 64 bits 900.00 ns/op 948.00 ns/op 0.95
enrSubnets - ssz BitVector 64 bits 334.00 ns/op 327.00 ns/op 1.02
enrSubnets - fastDeserialize 4 bits 120.00 ns/op 135.00 ns/op 0.89
enrSubnets - ssz BitVector 4 bits 325.00 ns/op 329.00 ns/op 0.99
prioritizePeers score -10:0 att 32-0.1 sync 2-0 121.54 us/op 122.08 us/op 1.00
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 141.81 us/op 149.63 us/op 0.95
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 203.57 us/op 212.68 us/op 0.96
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 392.36 us/op 395.31 us/op 0.99
prioritizePeers score 0:0 att 64-1 sync 4-1 470.96 us/op 478.74 us/op 0.98
array of 16000 items push then shift 1.6630 us/op 1.6753 us/op 0.99
LinkedList of 16000 items push then shift 7.2750 ns/op 8.3880 ns/op 0.87
array of 16000 items push then pop 79.384 ns/op 83.222 ns/op 0.95
LinkedList of 16000 items push then pop 6.9900 ns/op 7.7230 ns/op 0.91
array of 24000 items push then shift 2.3824 us/op 2.4817 us/op 0.96
LinkedList of 24000 items push then shift 7.0250 ns/op 9.0650 ns/op 0.77
array of 24000 items push then pop 111.72 ns/op 129.97 ns/op 0.86
LinkedList of 24000 items push then pop 7.1100 ns/op 8.3300 ns/op 0.85
intersect bitArray bitLen 8 6.4970 ns/op 6.4060 ns/op 1.01
intersect array and set length 8 38.794 ns/op 48.086 ns/op 0.81
intersect bitArray bitLen 128 30.654 ns/op 30.320 ns/op 1.01
intersect array and set length 128 631.59 ns/op 635.75 ns/op 0.99
bitArray.getTrueBitIndexes() bitLen 128 1.0350 us/op 1.0900 us/op 0.95
bitArray.getTrueBitIndexes() bitLen 248 1.8390 us/op 2.2140 us/op 0.83
bitArray.getTrueBitIndexes() bitLen 512 3.7400 us/op 3.9620 us/op 0.94
Buffer.concat 32 items 756.00 ns/op 780.00 ns/op 0.97
Uint8Array.set 32 items 1.1890 us/op 1.9450 us/op 0.61
Buffer.copy 1.9880 us/op 2.5020 us/op 0.79
Uint8Array.set - with subarray 1.8490 us/op 1.6710 us/op 1.11
Uint8Array.set - without subarray 870.00 ns/op 1.2530 us/op 0.69
getUint32 - dataview 196.00 ns/op 194.00 ns/op 1.01
getUint32 - manual 117.00 ns/op 155.00 ns/op 0.75
Set add up to 64 items then delete first 2.0870 us/op 3.1324 us/op 0.67
OrderedSet add up to 64 items then delete first 3.7435 us/op 4.2082 us/op 0.89
Set add up to 64 items then delete last 2.6100 us/op 3.7277 us/op 0.70
OrderedSet add up to 64 items then delete last 4.2709 us/op 4.8845 us/op 0.87
Set add up to 64 items then delete middle 2.4473 us/op 3.2099 us/op 0.76
OrderedSet add up to 64 items then delete middle 5.5346 us/op 6.0673 us/op 0.91
Set add up to 128 items then delete first 5.2276 us/op 6.1757 us/op 0.85
OrderedSet add up to 128 items then delete first 7.6613 us/op 12.986 us/op 0.59
Set add up to 128 items then delete last 5.2683 us/op 6.8848 us/op 0.77
OrderedSet add up to 128 items then delete last 8.0073 us/op 8.2299 us/op 0.97
Set add up to 128 items then delete middle 5.1199 us/op 6.5891 us/op 0.78
OrderedSet add up to 128 items then delete middle 14.281 us/op 18.690 us/op 0.76
Set add up to 256 items then delete first 10.653 us/op 13.208 us/op 0.81
OrderedSet add up to 256 items then delete first 15.924 us/op 23.646 us/op 0.67
Set add up to 256 items then delete last 10.418 us/op 13.629 us/op 0.76
OrderedSet add up to 256 items then delete last 17.835 us/op 28.226 us/op 0.63
Set add up to 256 items then delete middle 11.706 us/op 15.621 us/op 0.75
OrderedSet add up to 256 items then delete middle 42.649 us/op 48.645 us/op 0.88
transfer serialized Status (84 B) 2.5730 us/op 2.3130 us/op 1.11
copy serialized Status (84 B) 1.6180 us/op 1.1980 us/op 1.35
transfer serialized SignedVoluntaryExit (112 B) 2.4560 us/op 3.0560 us/op 0.80
copy serialized SignedVoluntaryExit (112 B) 1.4060 us/op 2.2670 us/op 0.62
transfer serialized ProposerSlashing (416 B) 3.2020 us/op 4.0420 us/op 0.79
copy serialized ProposerSlashing (416 B) 1.9440 us/op 2.0060 us/op 0.97
transfer serialized Attestation (485 B) 2.5590 us/op 3.1420 us/op 0.81
copy serialized Attestation (485 B) 2.4650 us/op 1.3210 us/op 1.87
transfer serialized AttesterSlashing (33232 B) 3.0810 us/op 3.2760 us/op 0.94
copy serialized AttesterSlashing (33232 B) 5.1430 us/op 5.3970 us/op 0.95
transfer serialized Small SignedBeaconBlock (128000 B) 3.4450 us/op 5.0780 us/op 0.68
copy serialized Small SignedBeaconBlock (128000 B) 13.095 us/op 17.829 us/op 0.73
transfer serialized Avg SignedBeaconBlock (200000 B) 4.0200 us/op 6.0880 us/op 0.66
copy serialized Avg SignedBeaconBlock (200000 B) 18.387 us/op 24.069 us/op 0.76
transfer serialized BlobsSidecar (524380 B) 4.1660 us/op 8.2070 us/op 0.51
copy serialized BlobsSidecar (524380 B) 193.59 us/op 96.949 us/op 2.00
transfer serialized Big SignedBeaconBlock (1000000 B) 4.4930 us/op 7.7920 us/op 0.58
copy serialized Big SignedBeaconBlock (1000000 B) 346.72 us/op 362.84 us/op 0.96
pass gossip attestations to forkchoice per slot 2.8689 ms/op 5.0025 ms/op 0.57
forkChoice updateHead vc 100000 bc 64 eq 0 467.41 us/op 713.50 us/op 0.66
forkChoice updateHead vc 600000 bc 64 eq 0 3.1205 ms/op 6.3461 ms/op 0.49
forkChoice updateHead vc 1000000 bc 64 eq 0 5.3077 ms/op 10.787 ms/op 0.49
forkChoice updateHead vc 600000 bc 320 eq 0 3.2165 ms/op 6.0719 ms/op 0.53
forkChoice updateHead vc 600000 bc 1200 eq 0 3.1246 ms/op 5.6614 ms/op 0.55
forkChoice updateHead vc 600000 bc 7200 eq 0 3.3494 ms/op 6.0747 ms/op 0.55
forkChoice updateHead vc 600000 bc 64 eq 1000 12.598 ms/op 11.817 ms/op 1.07
forkChoice updateHead vc 600000 bc 64 eq 10000 10.595 ms/op 12.531 ms/op 0.85
forkChoice updateHead vc 600000 bc 64 eq 300000 13.465 ms/op 56.830 ms/op 0.24
computeDeltas 500000 validators 300 proto nodes 4.1650 ms/op 6.2421 ms/op 0.67
computeDeltas 500000 validators 1200 proto nodes 4.3254 ms/op 6.1386 ms/op 0.70
computeDeltas 500000 validators 7200 proto nodes 4.6422 ms/op 6.3498 ms/op 0.73
computeDeltas 750000 validators 300 proto nodes 7.3733 ms/op 8.4366 ms/op 0.87
computeDeltas 750000 validators 1200 proto nodes 8.0020 ms/op 7.8741 ms/op 1.02
computeDeltas 750000 validators 7200 proto nodes 7.5844 ms/op 6.7574 ms/op 1.12
computeDeltas 1400000 validators 300 proto nodes 12.239 ms/op 12.393 ms/op 0.99
computeDeltas 1400000 validators 1200 proto nodes 11.470 ms/op 17.566 ms/op 0.65
computeDeltas 1400000 validators 7200 proto nodes 11.280 ms/op 12.606 ms/op 0.89
computeDeltas 2100000 validators 300 proto nodes 16.743 ms/op 21.572 ms/op 0.78
computeDeltas 2100000 validators 1200 proto nodes 16.466 ms/op 19.246 ms/op 0.86
computeDeltas 2100000 validators 7200 proto nodes 16.414 ms/op 21.455 ms/op 0.77
altair processAttestation - 250000 vs - 7PWei normalcase 2.0244 ms/op 4.2598 ms/op 0.48
altair processAttestation - 250000 vs - 7PWei worstcase 2.9534 ms/op 4.8564 ms/op 0.61
altair processAttestation - setStatus - 1/6 committees join 131.46 us/op 141.35 us/op 0.93
altair processAttestation - setStatus - 1/3 committees join 244.55 us/op 296.83 us/op 0.82
altair processAttestation - setStatus - 1/2 committees join 340.49 us/op 398.72 us/op 0.85
altair processAttestation - setStatus - 2/3 committees join 441.64 us/op 807.52 us/op 0.55
altair processAttestation - setStatus - 4/5 committees join 601.99 us/op 644.38 us/op 0.93
altair processAttestation - setStatus - 100% committees join 710.35 us/op 1.2432 ms/op 0.57
altair processBlock - 250000 vs - 7PWei normalcase 8.5116 ms/op 8.5889 ms/op 0.99
altair processBlock - 250000 vs - 7PWei normalcase hashState 29.460 ms/op 48.711 ms/op 0.60
altair processBlock - 250000 vs - 7PWei worstcase 43.186 ms/op 58.829 ms/op 0.73
altair processBlock - 250000 vs - 7PWei worstcase hashState 100.27 ms/op 120.64 ms/op 0.83
phase0 processBlock - 250000 vs - 7PWei normalcase 2.2591 ms/op 3.8707 ms/op 0.58
phase0 processBlock - 250000 vs - 7PWei worstcase 22.736 ms/op 31.420 ms/op 0.72
altair processEth1Data - 250000 vs - 7PWei normalcase 331.75 us/op 428.43 us/op 0.77
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 7.8280 us/op 9.3930 us/op 0.83
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 42.811 us/op 47.874 us/op 0.89
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 11.832 us/op 16.374 us/op 0.72
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 5.1160 us/op 8.7880 us/op 0.58
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 163.82 us/op 178.53 us/op 0.92
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.3314 ms/op 1.0913 ms/op 1.22
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.7030 ms/op 1.4398 ms/op 1.18
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.8248 ms/op 1.4339 ms/op 1.27
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.4727 ms/op 3.9726 ms/op 0.87
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.0434 ms/op 1.7316 ms/op 1.18
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 3.4596 ms/op 4.5066 ms/op 0.77
Tree 40 250000 create 423.73 ms/op 969.40 ms/op 0.44
Tree 40 250000 get(125000) 146.04 ns/op 149.24 ns/op 0.98
Tree 40 250000 set(125000) 1.5019 us/op 2.8848 us/op 0.52
Tree 40 250000 toArray() 20.744 ms/op 28.480 ms/op 0.73
Tree 40 250000 iterate all - toArray() + loop 16.576 ms/op 26.099 ms/op 0.64
Tree 40 250000 iterate all - get(i) 50.778 ms/op 66.952 ms/op 0.76
Array 250000 create 3.1516 ms/op 4.7325 ms/op 0.67
Array 250000 clone - spread 1.3672 ms/op 4.4526 ms/op 0.31
Array 250000 get(125000) 0.41800 ns/op 0.41100 ns/op 1.02
Array 250000 set(125000) 0.44600 ns/op 0.43500 ns/op 1.03
Array 250000 iterate all - loop 85.213 us/op 106.08 us/op 0.80
phase0 afterProcessEpoch - 250000 vs - 7PWei 50.921 ms/op 53.980 ms/op 0.94
Array.fill - length 1000000 3.4528 ms/op 9.4050 ms/op 0.37
Array push - length 1000000 14.163 ms/op 33.422 ms/op 0.42
Array.get 0.27526 ns/op 0.48273 ns/op 0.57
Uint8Array.get 0.44539 ns/op 0.47553 ns/op 0.94
phase0 beforeProcessEpoch - 250000 vs - 7PWei 19.664 ms/op 33.637 ms/op 0.58
altair processEpoch - mainnet_e81889 316.31 ms/op 363.36 ms/op 0.87
mainnet_e81889 - altair beforeProcessEpoch 19.047 ms/op 25.462 ms/op 0.75
mainnet_e81889 - altair processJustificationAndFinalization 8.5940 us/op 6.2650 us/op 1.37
mainnet_e81889 - altair processInactivityUpdates 4.3635 ms/op 6.1582 ms/op 0.71
mainnet_e81889 - altair processRewardsAndPenalties 51.209 ms/op 50.373 ms/op 1.02
mainnet_e81889 - altair processRegistryUpdates 696.00 ns/op 826.00 ns/op 0.84
mainnet_e81889 - altair processSlashings 188.00 ns/op 189.00 ns/op 0.99
mainnet_e81889 - altair processEth1DataReset 172.00 ns/op 188.00 ns/op 0.91
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.2485 ms/op 1.3876 ms/op 0.90
mainnet_e81889 - altair processSlashingsReset 952.00 ns/op 1.1020 us/op 0.86
mainnet_e81889 - altair processRandaoMixesReset 1.2630 us/op 1.1520 us/op 1.10
mainnet_e81889 - altair processHistoricalRootsUpdate 191.00 ns/op 225.00 ns/op 0.85
mainnet_e81889 - altair processParticipationFlagUpdates 542.00 ns/op 607.00 ns/op 0.89
mainnet_e81889 - altair processSyncCommitteeUpdates 135.00 ns/op 149.00 ns/op 0.91
mainnet_e81889 - altair afterProcessEpoch 52.680 ms/op 56.001 ms/op 0.94
capella processEpoch - mainnet_e217614 998.99 ms/op 1.0455 s/op 0.96
mainnet_e217614 - capella beforeProcessEpoch 73.022 ms/op 108.01 ms/op 0.68
mainnet_e217614 - capella processJustificationAndFinalization 5.2020 us/op 7.0750 us/op 0.74
mainnet_e217614 - capella processInactivityUpdates 16.423 ms/op 21.268 ms/op 0.77
mainnet_e217614 - capella processRewardsAndPenalties 227.99 ms/op 202.11 ms/op 1.13
mainnet_e217614 - capella processRegistryUpdates 8.6870 us/op 7.0870 us/op 1.23
mainnet_e217614 - capella processSlashings 203.00 ns/op 188.00 ns/op 1.08
mainnet_e217614 - capella processEth1DataReset 172.00 ns/op 186.00 ns/op 0.92
mainnet_e217614 - capella processEffectiveBalanceUpdates 16.681 ms/op 15.901 ms/op 1.05
mainnet_e217614 - capella processSlashingsReset 1.2560 us/op 938.00 ns/op 1.34
mainnet_e217614 - capella processRandaoMixesReset 1.2200 us/op 1.2030 us/op 1.01
mainnet_e217614 - capella processHistoricalRootsUpdate 176.00 ns/op 190.00 ns/op 0.93
mainnet_e217614 - capella processParticipationFlagUpdates 524.00 ns/op 566.00 ns/op 0.93
mainnet_e217614 - capella afterProcessEpoch 124.21 ms/op 129.71 ms/op 0.96
phase0 processEpoch - mainnet_e58758 484.54 ms/op 306.69 ms/op 1.58
mainnet_e58758 - phase0 beforeProcessEpoch 163.68 ms/op 93.576 ms/op 1.75
mainnet_e58758 - phase0 processJustificationAndFinalization 10.032 us/op 5.7170 us/op 1.75
mainnet_e58758 - phase0 processRewardsAndPenalties 64.964 ms/op 38.769 ms/op 1.68
mainnet_e58758 - phase0 processRegistryUpdates 5.1630 us/op 7.0610 us/op 0.73
mainnet_e58758 - phase0 processSlashings 258.00 ns/op 189.00 ns/op 1.37
mainnet_e58758 - phase0 processEth1DataReset 371.00 ns/op 181.00 ns/op 2.05
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 6.8226 ms/op 1.0471 ms/op 6.52
mainnet_e58758 - phase0 processSlashingsReset 2.5700 us/op 1.3080 us/op 1.96
mainnet_e58758 - phase0 processRandaoMixesReset 1.6720 us/op 1.4820 us/op 1.13
mainnet_e58758 - phase0 processHistoricalRootsUpdate 303.00 ns/op 198.00 ns/op 1.53
mainnet_e58758 - phase0 processParticipationRecordUpdates 1.8330 us/op 912.00 ns/op 2.01
mainnet_e58758 - phase0 afterProcessEpoch 50.925 ms/op 44.711 ms/op 1.14
phase0 processEffectiveBalanceUpdates - 250000 normalcase 2.4440 ms/op 1.4321 ms/op 1.71
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 4.2710 ms/op 1.9666 ms/op 2.17
altair processInactivityUpdates - 250000 normalcase 25.431 ms/op 19.470 ms/op 1.31
altair processInactivityUpdates - 250000 worstcase 28.211 ms/op 18.148 ms/op 1.55
phase0 processRegistryUpdates - 250000 normalcase 12.663 us/op 6.1400 us/op 2.06
phase0 processRegistryUpdates - 250000 badcase_full_deposits 474.85 us/op 273.12 us/op 1.74
phase0 processRegistryUpdates - 250000 worstcase 0.5 169.01 ms/op 114.26 ms/op 1.48
altair processRewardsAndPenalties - 250000 normalcase 78.875 ms/op 46.340 ms/op 1.70
altair processRewardsAndPenalties - 250000 worstcase 54.668 ms/op 40.243 ms/op 1.36
phase0 getAttestationDeltas - 250000 normalcase 9.6567 ms/op 7.6236 ms/op 1.27
phase0 getAttestationDeltas - 250000 worstcase 9.4098 ms/op 8.0396 ms/op 1.17
phase0 processSlashings - 250000 worstcase 157.23 us/op 114.07 us/op 1.38
altair processSyncCommitteeUpdates - 250000 171.47 ms/op 132.43 ms/op 1.29
BeaconState.hashTreeRoot - No change 463.00 ns/op 218.00 ns/op 2.12
BeaconState.hashTreeRoot - 1 full validator 111.90 us/op 79.794 us/op 1.40
BeaconState.hashTreeRoot - 32 full validator 1.8036 ms/op 934.47 us/op 1.93
BeaconState.hashTreeRoot - 512 full validator 18.805 ms/op 11.094 ms/op 1.70
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 167.76 us/op 97.368 us/op 1.72
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 2.4082 ms/op 1.2627 ms/op 1.91
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 39.932 ms/op 21.273 ms/op 1.88
BeaconState.hashTreeRoot - 1 balances 91.812 us/op 75.284 us/op 1.22
BeaconState.hashTreeRoot - 32 balances 675.70 us/op 763.26 us/op 0.89
BeaconState.hashTreeRoot - 512 balances 8.6550 ms/op 9.6454 ms/op 0.90
BeaconState.hashTreeRoot - 250000 balances 161.03 ms/op 169.98 ms/op 0.95
aggregationBits - 2048 els - zipIndexesInBitList 24.336 us/op 23.499 us/op 1.04
byteArrayEquals 32 56.164 ns/op 55.311 ns/op 1.02
Buffer.compare 32 18.597 ns/op 17.212 ns/op 1.08
byteArrayEquals 1024 1.6761 us/op 1.6166 us/op 1.04
Buffer.compare 1024 27.906 ns/op 24.844 ns/op 1.12
byteArrayEquals 16384 27.081 us/op 25.931 us/op 1.04
Buffer.compare 16384 212.34 ns/op 184.22 ns/op 1.15
byteArrayEquals 123687377 204.14 ms/op 206.04 ms/op 0.99
Buffer.compare 123687377 8.4155 ms/op 8.8195 ms/op 0.95
byteArrayEquals 32 - diff last byte 54.103 ns/op 54.051 ns/op 1.00
Buffer.compare 32 - diff last byte 17.729 ns/op 17.627 ns/op 1.01
byteArrayEquals 1024 - diff last byte 1.6433 us/op 1.6121 us/op 1.02
Buffer.compare 1024 - diff last byte 25.991 ns/op 26.148 ns/op 0.99
byteArrayEquals 16384 - diff last byte 26.296 us/op 25.598 us/op 1.03
Buffer.compare 16384 - diff last byte 204.47 ns/op 203.99 ns/op 1.00
byteArrayEquals 123687377 - diff last byte 227.02 ms/op 202.97 ms/op 1.12
Buffer.compare 123687377 - diff last byte 10.427 ms/op 11.287 ms/op 0.92
byteArrayEquals 32 - random bytes 5.4690 ns/op 6.2250 ns/op 0.88
Buffer.compare 32 - random bytes 18.385 ns/op 20.684 ns/op 0.89
byteArrayEquals 1024 - random bytes 5.3210 ns/op 5.5090 ns/op 0.97
Buffer.compare 1024 - random bytes 18.061 ns/op 19.483 ns/op 0.93
byteArrayEquals 16384 - random bytes 5.3760 ns/op 7.8680 ns/op 0.68
Buffer.compare 16384 - random bytes 18.156 ns/op 18.903 ns/op 0.96
byteArrayEquals 123687377 - random bytes 6.6800 ns/op 6.7700 ns/op 0.99
Buffer.compare 123687377 - random bytes 19.420 ns/op 21.780 ns/op 0.89
regular array get 100000 times 41.152 us/op 42.670 us/op 0.96
wrappedArray get 100000 times 34.174 us/op 36.010 us/op 0.95
arrayWithProxy get 100000 times 16.174 ms/op 14.329 ms/op 1.13
ssz.Root.equals 48.328 ns/op 70.926 ns/op 0.68
byteArrayEquals 47.467 ns/op 50.612 ns/op 0.94
Buffer.compare 10.894 ns/op 11.719 ns/op 0.93
processSlot - 1 slots 10.936 us/op 17.382 us/op 0.63
processSlot - 32 slots 1.9860 ms/op 2.8196 ms/op 0.70
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 56.623 ms/op 58.595 ms/op 0.97
getCommitteeAssignments - req 1 vs - 250000 vc 2.1285 ms/op 2.1315 ms/op 1.00
getCommitteeAssignments - req 100 vs - 250000 vc 4.1789 ms/op 4.2052 ms/op 0.99
getCommitteeAssignments - req 1000 vs - 250000 vc 4.4775 ms/op 4.4952 ms/op 1.00
findModifiedValidators - 10000 modified validators 717.03 ms/op 919.14 ms/op 0.78
findModifiedValidators - 1000 modified validators 688.82 ms/op 796.03 ms/op 0.87
findModifiedValidators - 100 modified validators 199.88 ms/op 280.73 ms/op 0.71
findModifiedValidators - 10 modified validators 167.38 ms/op 172.14 ms/op 0.97
findModifiedValidators - 1 modified validators 214.99 ms/op 251.63 ms/op 0.85
findModifiedValidators - no difference 166.40 ms/op 228.18 ms/op 0.73
compare ViewDUs 6.1080 s/op 6.3326 s/op 0.96
compare each validator Uint8Array 1.3491 s/op 1.5666 s/op 0.86
compare ViewDU to Uint8Array 1.1841 s/op 1.0515 s/op 1.13
migrate state 1000000 validators, 24 modified, 0 new 850.62 ms/op 882.93 ms/op 0.96
migrate state 1000000 validators, 1700 modified, 1000 new 1.1494 s/op 1.2166 s/op 0.94
migrate state 1000000 validators, 3400 modified, 2000 new 1.3361 s/op 1.7488 s/op 0.76
migrate state 1500000 validators, 24 modified, 0 new 953.51 ms/op 1.0521 s/op 0.91
migrate state 1500000 validators, 1700 modified, 1000 new 1.1555 s/op 1.1006 s/op 1.05
migrate state 1500000 validators, 3400 modified, 2000 new 1.4702 s/op 1.2702 s/op 1.16
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 4.2900 ns/op 4.2800 ns/op 1.00
state getBlockRootAtSlot - 250000 vs - 7PWei 465.08 ns/op 557.41 ns/op 0.83
computeProposers - vc 250000 7.9998 ms/op 8.5687 ms/op 0.93
computeEpochShuffling - vc 250000 43.558 ms/op 42.165 ms/op 1.03
getNextSyncCommittee - vc 250000 138.50 ms/op 149.30 ms/op 0.93
computeSigningRoot for AttestationData 24.179 us/op 21.638 us/op 1.12
hash AttestationData serialized data then Buffer.toString(base64) 1.5985 us/op 1.5852 us/op 1.01
toHexString serialized data 846.68 ns/op 1.1423 us/op 0.74
Buffer.toString(base64) 150.56 ns/op 167.98 ns/op 0.90
nodejs block root to RootHex using toHex 143.73 ns/op 145.00 ns/op 0.99
nodejs block root to RootHex using toRootHex 85.695 ns/op 87.170 ns/op 0.98
browser block root to RootHex using the deprecated toHexString 222.01 ns/op 233.88 ns/op 0.95
browser block root to RootHex using toHex 174.60 ns/op 179.95 ns/op 0.97
browser block root to RootHex using toRootHex 161.79 ns/op 159.96 ns/op 1.01

by benchmarkbot/action

Copy link

codecov bot commented Feb 12, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 50.25%. Comparing base (2247c16) to head (8de5c80).
Report is 4 commits behind head on unstable.

Additional details and impacted files
@@            Coverage Diff            @@
##           unstable    #7455   +/-   ##
=========================================
  Coverage     50.25%   50.25%           
=========================================
  Files           602      602           
  Lines         40401    40416   +15     
  Branches       2204     2203    -1     
=========================================
+ Hits          20305    20313    +8     
- Misses        20056    20063    +7     
  Partials         40       40           

Copy link
Member

@nflaig nflaig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably best if @twoeths give this a review

@@ -385,19 +383,22 @@ export class AggregatedAttestationPool {
if (score < minScore) {
minScore = score;
}
consolidations.push({...consolidation, score});

consolidations.set(consolidation, score);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this would override the record? might be better to just continue if it already exists.

But why do we have duplicates in sameAttDataCons shouldn't this be aggregated earlier into a single one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this would override the record? might be better to just continue if it already exists.

That's the whole point. The current implementation would insert the same consolidation with different score into consolidations, hence the duplication.

But why do we have duplicates in sameAttDataCons shouldn't this be aggregated earlier into a single one?

The aggregation earlier only aggregates the SignedAggregateAndProofs from the same committee. Notice how they are stored by committee index and MatchingDataAttestationGroup only store aggregated attestations from the same committee.

    private readonly attestationGroupByIndexByDataHexBySlot = new MapDef<
    Slot,
    Map<DataRootHex, Map<CommitteeIndex, MatchingDataAttestationGroup>>>

.slice(0, MAX_ATTESTATIONS_ELECTRA);

Copy link
Member

@nflaig nflaig Feb 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed we are not cloning here

// attestations could be modified in this op pool, so we need to clone for block
attestationsForBlock.push(ssz.phase0.Attestation.clone(attestationWithScore.attestation));

but might be fine due to aggregateConsolidation

@ensi321
Copy link
Contributor Author

ensi321 commented Feb 12, 2025

It took me a while to understand what getAttestationsForBlockElectra does. I will try to explain here for easier review:

Suppose you have committee 100 and committee 101 both contain members who vote for the same attestation data.

Then they will share the same sameAttDataCons when looping inside this for loop - for (const [committeeIndex, attestationGroup] of attestationGroupByIndex.entries()).

In the first iteration of the above for loop, sameAttDataCons[i] will be updated to something like

          sameAttDataCons[i] = {
            byCommittee: {100: ...}
            attData: attestationNonParticipation.attestation.data,
            totalNotSeenCount: 32,
            score: 0,
          };

and then each sameAttDataCons[i] will be inserted into consolidations. Now consolidations should contain [{...sameAttDataCons[0], score: 32}, {...sameAttDataCons[1], score: 58}, {...sameAttDataCons[2], score: 82}]

In the second iteration, sameAttDataCons[i] will be updated to

          sameAttDataCons[i] = {
            byCommittee: {100: ..., 101: ...}
            attData: attestationNonParticipation.attestation.data,
            totalNotSeenCount: 58,
            score: 0,
          };

and again sameAttDataCons[i] will be inserted into consolidations. Because consolidations elements are still referencing sameAttDataCons[i], now consolidations is

[{...sameAttDataCons[0], score: 32}, {...sameAttDataCons[1], score: 58}, {...sameAttDataCons[2], score: 82}, {...sameAttDataCons[0], score: 128}, {...sameAttDataCons[1], score: 167}, {...sameAttDataCons[2], score: 170}]

where each element's byCommittee contain committee 100 and 101, so things are being duplicated.

ensi321 and others added 2 commits February 12, 2025 10:57
…ol.ts

Co-authored-by: Nico Flaig <nflaig@protonmail.com>
@ensi321
Copy link
Contributor Author

ensi321 commented Feb 12, 2025

Can confirm this PR fixes the issue.

https://dora.pectra-devnet-6.ethpandaops.io/slot/66426 no longer sees duplicates.

@twoeths
Copy link
Contributor

twoeths commented Feb 13, 2025

@ensi321 could you reproduce the issue in a unit test?

Copy link
Member

@nflaig nflaig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could add tests in a follow-up PR since the branch has been tested on the devnet

@nflaig nflaig merged commit 398c796 into unstable Feb 13, 2025
19 of 20 checks passed
@nflaig nflaig deleted the nc/deduplicate-block-attestations2 branch February 13, 2025 13:04
@wemeetagain
Copy link
Member

🎉 This PR is included in v1.27.0 🎉

wemeetagain pushed a commit that referenced this pull request Feb 18, 2025
Follow up on
#7455 (comment)
to add unit test of the changes introduced in #7455.

---------

Co-authored-by: Nico Flaig <nflaig@protonmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants