This is a high-level analysis of blocks produced on the Hoodi testnet. I've reused some of the statistics that I looked at on the Holešky testnet after the Pectra incident. The aim is mostly to identify if any of the clients are doing something much better or much worse than others.
I'm leaving the interpretation to client teams.
Analysed epoch range: 2,248 - 2,748 and 8,450 – 8,550
Produced CL block value
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 39,326,651 / 74,928,753 / ['20%: 22,760,000', '40%: 41,994,455', '60%: 43,363,166', '80%: 44,207,643']
Client.LIGHTHOUSE : [681] 46,843,545 / 128,176,181 / ['20%: 41,100,465', '40%: 42,357,849', '60%: 43,085,722', '80%: 44,043,804']
Client.LODESTAR : [732] 45,766,447 / 121,112,434 / ['20%: 40,118,604', '40%: 41,291,764', '60%: 42,065,438', '80%: 43,024,664']
Client.NIMBUS : [748] 22,699,790 / 100,873,088 / ['20%: 2,047,826', '40%: 2,533,740', '60%: 40,269,822', '80%: 42,157,382']
Client.PRYSM : [770] 48,883,144 / 107,039,934 / ['20%: 42,118,886', '40%: 43,483,601', '60%: 44,252,403', '80%: 46,284,012']
Client.TEKU : [789] 42,862,826 / 101,743,465 / ['20%: 39,406,656', '40%: 41,039,653', '60%: 41,750,272', '80%: 42,637,180']
Client.UNKNOWN : [10276] 45,737,969 / 164,016,308 / ['20%: 41,074,578', '40%: 42,383,749', '60%: 43,431,139', '80%: 44,883,610']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 47,589,227 / 78,203,467 / ['20%: 45,742,361', '40%: 45,966,955', '60%: 46,320,917', '80%: 46,620,536']
Client.LIGHTHOUSE : [127] 47,794,241 / 77,961,353 / ['20%: 45,606,549', '40%: 45,789,578', '60%: 45,930,292', '80%: 46,198,768']
Client.LODESTAR : [136] 45,879,745 / 78,280,519 / ['20%: 44,931,206', '40%: 45,305,371', '60%: 45,433,888', '80%: 45,540,578']
Client.NIMBUS : [155] 45,273,469 / 110,453,007 / ['20%: 45,228,935', '40%: 45,431,997', '60%: 45,608,321', '80%: 45,769,027']
Client.PRYSM : [156] 48,855,158 / 107,574,476 / ['20%: 46,064,615', '40%: 46,349,501', '60%: 46,713,747', '80%: 47,634,652']
Client.TEKU : [131] 43,768,215 / 75,107,582 / ['20%: 44,933,298', '40%: 45,311,709', '60%: 45,414,632', '80%: 45,561,778']
Client.UNKNOWN : [2248] 46,738,936 / 112,355,567 / ['20%: 45,318,578', '40%: 45,544,071', '60%: 45,917,852', '80%: 46,600,136']
Produced CL block value - attestations only
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 37,851,405 / 73,411,123 / ['20%: 21,216,895', '40%: 40,504,581', '60%: 41,865,383', '80%: 42,712,117']
Client.LIGHTHOUSE : [681] 45,361,533 / 126,709,761 / ['20%: 39,620,678', '40%: 40,870,607', '60%: 41,574,072', '80%: 42,525,288']
Client.LODESTAR : [732] 44,303,136 / 119,686,542 / ['20%: 38,598,857', '40%: 39,795,745', '60%: 40,546,216', '80%: 41,507,962']
Client.NIMBUS : [748] 21,230,357 / 99,359,576 / ['20%: 576,826', '40%: 1,060,528', '60%: 38,825,458', '80%: 40,669,827']
Client.PRYSM : [770] 47,423,392 / 105,526,002 / ['20%: 40,684,730', '40%: 41,992,460', '60%: 42,738,468', '80%: 44,798,186']
Client.TEKU : [789] 41,429,067 / 100,235,522 / ['20%: 37,940,690', '40%: 39,558,236', '60%: 40,249,864', '80%: 41,145,051']
Client.UNKNOWN : [10276] 44,260,912 / 162,448,303 / ['20%: 39,615,449', '40%: 40,884,750', '60%: 41,923,257', '80%: 43,372,489']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 45,952,319 / 76,563,553 / ['20%: 44,120,523', '40%: 44,326,743', '60%: 44,680,804', '80%: 44,987,623']
Client.LIGHTHOUSE : [127] 46,159,969 / 76,311,560 / ['20%: 43,965,639', '40%: 44,149,265', '60%: 44,280,499', '80%: 44,574,097']
Client.LODESTAR : [136] 44,258,765 / 76,630,726 / ['20%: 43,304,334', '40%: 43,660,746', '60%: 43,793,974', '80%: 43,901,919']
Client.NIMBUS : [155] 43,638,009 / 108,812,595 / ['20%: 43,588,523', '40%: 43,799,637', '60%: 43,969,020', '80%: 44,123,053']
Client.PRYSM : [156] 47,235,922 / 105,934,562 / ['20%: 44,426,747', '40%: 44,715,708', '60%: 45,073,335', '80%: 46,040,280']
Client.TEKU : [131] 42,170,435 / 73,467,668 / ['20%: 43,310,877', '40%: 43,671,958', '60%: 43,770,197', '80%: 43,917,249']
Client.UNKNOWN : [2248] 45,110,138 / 110,715,155 / ['20%: 43,678,867', '40%: 43,903,705', '60%: 44,285,859', '80%: 44,957,107']
Number of attestations included in block
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 7.22 / 8 / ['20%: 7.0', '40%: 8.0', '60%: 8.0', '80%: 8.0']
Client.LIGHTHOUSE : [681] 7.82 / 8 / ['20%: 8.0', '40%: 8.0', '60%: 8.0', '80%: 8.0']
Client.LODESTAR : [732] 5.75 / 8 / ['20%: 4.0', '40%: 5.0', '60%: 6.0', '80%: 8.0']
Client.NIMBUS : [748] 7.95 / 8 / ['20%: 8.0', '40%: 8.0', '60%: 8.0', '80%: 8.0']
Client.PRYSM : [770] 8.00 / 8 / ['20%: 8.0', '40%: 8.0', '60%: 8.0', '80%: 8.0']
Client.TEKU : [789] 5.02 / 8 / ['20%: 3.0', '40%: 4.0', '60%: 5.0', '80%: 8.0']
Client.UNKNOWN : [10276] 7.11 / 8 / ['20%: 6.0', '40%: 8.0', '60%: 8.0', '80%: 8.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 6.08 / 8 / ['20%: 3.8', '40%: 6.0', '60%: 8.0', '80%: 8.0']
Client.LIGHTHOUSE : [127] 7.02 / 8 / ['20%: 5.6', '40%: 8.0', '60%: 8.0', '80%: 8.0']
Client.LODESTAR : [136] 2.32 / 8 / ['20%: 1.0', '40%: 2.0', '60%: 2.0', '80%: 3.0']
Client.NIMBUS : [155] 5.34 / 8 / ['20%: 2.0', '40%: 4.0', '60%: 7.0', '80%: 8.0']
Client.PRYSM : [156] 8.00 / 8 / ['20%: 8.0', '40%: 8.0', '60%: 8.0', '80%: 8.0']
Client.TEKU : [131] 2.40 / 7 / ['20%: 1.0', '40%: 2.0', '60%: 2.0', '80%: 3.0']
Client.UNKNOWN : [2248] 5.41 / 8 / ['20%: 2.0', '40%: 4.0', '60%: 8.0', '80%: 8.0']
Code
len(block.message.body.attestations)
Number of single attestations included in block
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 48,466 / 63,701 / ['20%: 34,581', '40%: 48,591', '60%: 54,940', '80%: 58,810']
Client.LIGHTHOUSE : [681] 88,106 / 180,604 / ['20%: 65,603', '40%: 90,240', '60%: 93,445', '80%: 95,349']
Client.LODESTAR : [732] 54,033 / 163,403 / ['20%: 40,132', '40%: 46,120', '60%: 51,264', '80%: 61,393']
Client.NIMBUS : [748] 36,303 / 106,595 / ['20%: 18,749', '40%: 31,222', '60%: 40,846', '80%: 51,242']
Client.PRYSM : [770] 56,431 / 118,826 / ['20%: 42,848', '40%: 48,912', '60%: 57,161', '80%: 69,502']
Client.TEKU : [789] 45,986 / 160,492 / ['20%: 34,777', '40%: 39,777', '60%: 44,509', '80%: 51,766']
Client.UNKNOWN : [10276] 76,769 / 241,322 / ['20%: 48,485', '40%: 64,232', '60%: 90,993', '80%: 94,748']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 49,778 / 67,848 / ['20%: 36,079', '40%: 43,986', '60%: 53,827', '80%: 64,250']
Client.LIGHTHOUSE : [127] 86,092 / 180,247 / ['20%: 67,699', '40%: 100,375', '60%: 101,626', '80%: 102,117']
Client.LODESTAR : [136] 36,155 / 81,507 / ['20%: 33,602', '40%: 33,718', '60%: 34,084', '80%: 35,491']
Client.NIMBUS : [155] 41,355 / 102,524 / ['20%: 33,773', '40%: 36,747', '60%: 39,966', '80%: 49,355']
Client.PRYSM : [156] 58,158 / 138,026 / ['20%: 40,774', '40%: 49,308', '60%: 56,863', '80%: 75,011']
Client.TEKU : [131] 34,174 / 73,982 / ['20%: 33,520', '40%: 33,688', '60%: 34,054', '80%: 34,991']
Client.UNKNOWN : [2248] 57,392 / 207,527 / ['20%: 34,028', '40%: 39,203', '60%: 59,497', '80%: 80,296']
Code
sum(sum(att.aggregation_bits) for att in block.message.body.attestations)
Number of unique attesters voting for any slot whose attestation was included
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 48,291.61 / 63,701 / ['20%: 34,580.6', '40%: 48,241.4', '60%: 54,658.0', '80%: 58,575.4']
Client.LIGHTHOUSE : [681] 86,728.10 / 170,960 / ['20%: 63,257.6', '40%: 89,100.8', '60%: 92,224.4', '80%: 93,947.4']
Client.LODESTAR : [732] 42,892.32 / 111,489 / ['20%: 31,390.8', '40%: 37,710.2', '60%: 42,353.2', '80%: 49,633.8']
Client.NIMBUS : [748] 36,184.86 / 106,595 / ['20%: 18,694.6', '40%: 31,202.4', '60%: 40,708.2', '80%: 51,025.6']
Client.PRYSM : [770] 52,371.72 / 101,589 / ['20%: 40,055.0', '40%: 46,020.6', '60%: 53,542.4', '80%: 64,065.6']
Client.TEKU : [789] 40,992.10 / 154,751 / ['20%: 30,481.0', '40%: 35,278.0', '60%: 40,003.0', '80%: 45,659.0']
Client.UNKNOWN : [10276] 74,090.25 / 215,444 / ['20%: 45,506.0', '40%: 62,278.0', '60%: 89,664.2', '80%: 93,488.6']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 49,635.44 / 67,848 / ['20%: 35,798.8', '40%: 43,966.4', '60%: 53,817.8', '80%: 64,044.2']
Client.LIGHTHOUSE : [127] 85,079.04 / 180,225 / ['20%: 67,205.8', '40%: 97,632.6', '60%: 101,011.8', '80%: 101,303.8']
Client.LODESTAR : [136] 35,268.51 / 77,140 / ['20%: 33,396.2', '40%: 33,546.0', '60%: 33,631.6', '80%: 33,755.2']
Client.NIMBUS : [155] 41,308.34 / 102,524 / ['20%: 33,773.0', '40%: 36,747.0', '60%: 39,966.4', '80%: 49,355.4']
Client.PRYSM : [156] 56,145.21 / 134,702 / ['20%: 39,739.0', '40%: 47,701.2', '60%: 55,925.0', '80%: 72,491.8']
Client.TEKU : [131] 33,243.10 / 64,979 / ['20%: 33,386.8', '40%: 33,547.6', '60%: 33,612.6', '80%: 33,822.6']
Client.UNKNOWN : [2248] 55,796.18 / 199,482 / ['20%: 33,622.8', '40%: 37,469.6', '60%: 57,434.2', '80%: 76,321.0']
Code
unique_attesters_included_in_block = set() for att in block.message.body.attestations: commmitees = await get_committee(state_id=att.data.slot) agg_bits_offset = 0 for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: val_count = len(committee["validators"]) committee_agg_bits = att.aggregation_bits[ agg_bits_offset:agg_bits_offset + val_count] agg_bits_offset += val_count for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: unique_attesters_included_in_block.add(val_idx)
% of unique single attestations vs total single attestations included (max possible: 100%)
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 99.66 / 100 / ['20%: 99.3', '40%: 99.8', '60%: 100.0', '80%: 100.0']
Client.LIGHTHOUSE : [681] 98.39 / 100 / ['20%: 97.8', '40%: 98.3', '60%: 98.7', '80%: 99.3']
Client.LODESTAR : [732] 80.91 / 98 / ['20%: 72.0', '40%: 79.3', '60%: 84.7', '80%: 90.0']
Client.NIMBUS : [748] 99.72 / 100 / ['20%: 99.5', '40%: 99.7', '60%: 100.0', '80%: 100.0']
Client.PRYSM : [770] 93.19 / 100 / ['20%: 90.3', '40%: 92.9', '60%: 95.1', '80%: 96.9']
Client.TEKU : [789] 89.70 / 100 / ['20%: 84.0', '40%: 89.2', '60%: 92.9', '80%: 95.9']
Client.UNKNOWN : [10276] 96.64 / 100 / ['20%: 96.3', '40%: 98.2', '60%: 98.9', '80%: 99.6']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 99.68 / 100 / ['20%: 99.7', '40%: 100.0', '60%: 100.0', '80%: 100.0']
Client.LIGHTHOUSE : [127] 98.71 / 100 / ['20%: 98.0', '40%: 98.7', '60%: 99.3', '80%: 99.6']
Client.LODESTAR : [136] 97.73 / 100 / ['20%: 96.8', '40%: 98.7', '60%: 99.9', '80%: 100.0']
Client.NIMBUS : [155] 99.90 / 100 / ['20%: 99.9', '40%: 100.0', '60%: 100.0', '80%: 100.0']
Client.PRYSM : [156] 96.76 / 100 / ['20%: 95.4', '40%: 97.1', '60%: 97.9', '80%: 98.6']
Client.TEKU : [131] 97.69 / 100 / ['20%: 97.4', '40%: 98.7', '60%: 100.0', '80%: 100.0']
Client.UNKNOWN : [2248] 97.53 / 100 / ['20%: 97.1', '40%: 98.5', '60%: 99.3', '80%: 100.0']
Code
total_single_attestations_included = 0 unique_attesters_included_in_block = set() for att in block.message.body.attestations: commmitees = await get_committee(state_id=att.data.slot) agg_bits_offset = 0 for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: val_count = len(committee["validators"]) committee_agg_bits = att.aggregation_bits[ agg_bits_offset:agg_bits_offset + val_count] agg_bits_offset += val_count total_single_attestations_included += sum(committee_agg_bits) for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: unique_attesters_included_in_block.add(val_idx) ratio = len(unique_attesters_included_in_block) / total_single_attestations_included
Weighted mean attestation inclusion distance in blocks built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 3.47 / 15 / ['20%: 2.0', '40%: 2.5', '60%: 3.2', '80%: 4.7']
Client.LIGHTHOUSE : [681] 2.16 / 14 / ['20%: 1.9', '40%: 2.0', '60%: 2.0', '80%: 2.0']
Client.LODESTAR : [732] 1.34 / 4 / ['20%: 1.1', '40%: 1.2', '60%: 1.3', '80%: 1.5']
Client.NIMBUS : [748] 7.29 / 21 / ['20%: 3.1', '40%: 4.8', '60%: 7.4', '80%: 12.0']
Client.PRYSM : [770] 1.52 / 4 / ['20%: 1.3', '40%: 1.4', '60%: 1.5', '80%: 1.7']
Client.TEKU : [789] 1.62 / 22 / ['20%: 1.1', '40%: 1.2', '60%: 1.3', '80%: 1.6']
Client.UNKNOWN : [10276] 2.34 / 30 / ['20%: 1.5', '40%: 2.0', '60%: 2.0', '80%: 2.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 1.87 / 6 / ['20%: 1.2', '40%: 1.6', '60%: 1.9', '80%: 2.3']
Client.LIGHTHOUSE : [127] 1.86 / 8 / ['20%: 1.5', '40%: 2.0', '60%: 2.0', '80%: 2.0']
Client.LODESTAR : [136] 1.04 / 2 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.NIMBUS : [155] 2.03 / 12 / ['20%: 1.0', '40%: 1.3', '60%: 1.7', '80%: 2.3']
Client.PRYSM : [156] 2.60 / 16 / ['20%: 1.5', '40%: 1.9', '60%: 2.2', '80%: 3.1']
Client.TEKU : [131] 1.05 / 2 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.UNKNOWN : [2248] 1.91 / 19 / ['20%: 1.0', '40%: 1.4', '60%: 1.9', '80%: 2.2']
Code
weighted_mean_denominator = sum(sum(att.aggregation_bits) for att in block.message.body.attestations) weighted_mean_attestation_inclusion_distance = sum((sum(att.aggregation_bits) / weighted_mean_denominator) * (block_slot - att.data.slot) for att in block.message.body.attestations)
Minimal attestation inclusion distance in blocks built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.LIGHTHOUSE : [681] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.LODESTAR : [732] 1.00 / 2 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.NIMBUS : [748] 2.06 / 16 / ['20%: 1.0', '40%: 1.0', '60%: 2.0', '80%: 3.0']
Client.PRYSM : [770] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.TEKU : [789] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.UNKNOWN : [10276] 1.07 / 14 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.LIGHTHOUSE : [127] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.LODESTAR : [136] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.NIMBUS : [155] 1.08 / 6 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.PRYSM : [156] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.TEKU : [131] 1.00 / 1 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.UNKNOWN : [2248] 1.01 / 7 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Code
min(block_slot - att.data.slot for att in block.message.body.attestations)
% of fresh attestations in blocks built by client
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 75.35 / 100 / ['20%: 55.0', '40%: 66.4', '60%: 82.3', '80%: 97.0']
Client.LIGHTHOUSE : [127] 48.77 / 100 / ['20%: 33.3', '40%: 33.5', '60%: 48.0', '80%: 65.8']
Client.LODESTAR : [136] 95.87 / 100 / ['20%: 94.5', '40%: 98.5', '60%: 99.5', '80%: 100.0']
Client.NIMBUS : [155] 81.66 / 100 / ['20%: 69.2', '40%: 83.3', '60%: 90.3', '80%: 98.4']
Client.PRYSM : [156] 68.37 / 98 / ['20%: 53.2', '40%: 63.9', '60%: 73.7', '80%: 84.8']
Client.TEKU : [131] 94.94 / 100 / ['20%: 95.3', '40%: 98.5', '60%: 99.8', '80%: 100.0']
Client.UNKNOWN : [2248] 71.16 / 100 / ['20%: 46.7', '40%: 61.9', '60%: 87.9', '80%: 98.5']
Code
for attestation in block.message.body.attestations: attesters_in_attestation = ... first_seen_attestations_in_block += len(set(attesters_in_att) - EPOCH_ATTESTER_TRACKER[att_for_block_in_epoch]) previously_seen_attestations_in_block += len(set(attesters_in_att).intersection(EPOCH_ATTESTER_TRACKER[att_for_block_in_epoch])) EPOCH_ATTESTER_TRACKER[att_for_block_in_epoch].update(attesters_in_att) fresh_attestation_ratio = first_seen_attestations_in_block / (first_seen_attestations_in_block + previously_seen_attestations_in_block)
Unique attesters voting for correct target included in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 48,082 / 63,701 / ['20%: 34,438', '40%: 47,907', '60%: 54,648', '80%: 58,575']
Client.LIGHTHOUSE : [681] 86,667 / 170,960 / ['20%: 63,171', '40%: 89,040', '60%: 92,224', '80%: 93,947']
Client.LODESTAR : [732] 42,892 / 111,489 / ['20%: 31,391', '40%: 37,710', '60%: 42,353', '80%: 49,634']
Client.NIMBUS : [748] 36,130 / 106,595 / ['20%: 18,674', '40%: 31,090', '60%: 40,606', '80%: 51,026']
Client.PRYSM : [770] 52,297 / 101,589 / ['20%: 40,055', '40%: 45,963', '60%: 53,489', '80%: 64,048']
Client.TEKU : [789] 40,934 / 154,751 / ['20%: 30,469', '40%: 35,177', '60%: 39,996', '80%: 45,621']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 49,626 / 67,848 / ['20%: 35,799', '40%: 43,966', '60%: 53,517', '80%: 64,044']
Client.LIGHTHOUSE : [127] 85,060 / 180,225 / ['20%: 67,206', '40%: 97,633', '60%: 101,012', '80%: 101,304']
Client.LODESTAR : [136] 35,058 / 77,140 / ['20%: 33,396', '40%: 33,546', '60%: 33,632', '80%: 33,755']
Client.NIMBUS : [155] 41,297 / 102,524 / ['20%: 33,759', '40%: 36,747', '60%: 39,966', '80%: 49,355']
Client.PRYSM : [156] 55,681 / 134,702 / ['20%: 39,739', '40%: 47,429', '60%: 55,160', '80%: 70,665']
Client.TEKU : [131] 33,243 / 64,979 / ['20%: 33,387', '40%: 33,548', '60%: 33,613', '80%: 33,823']
Code
def get_correct_target_checkpoint(attestation_slot: int) -> tuple[int, str]: epoch_boundary_slot = 32 * (attestation_slot // 32) target_slot = epoch_boundary_slot while True: try: client_used, block_data = get_raw_block(target_slot) break except BlockNotFound: target_slot -= 1 block = SpecBeaconBlock.ElectraBlockSigned.from_obj(block_data) return target_slot // 32, "0x" + block.message.hash_tree_root().hex() unique_attesters_voting_for_correct_target_included_in_block = set() unique_attesters_voting_for_incorrect_target_included_in_block = set() for att in block.message.body.attestations: correct_target_epoch, correct_target_block_root = get_correct_target_checkpoint(att.data.slot) is_voting_for_correct_target = str(att.data.target.root) == correct_target_block_root for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_target: unique_attesters_voting_for_correct_target_included_in_block.add(val_idx) else: unique_attesters_voting_for_incorrect_target_included_in_block.add(val_idx)
Unique attesters voting for incorrect target included in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [145] 2,102 / 28,077 / ['20%: 0', '40%: 0', '60%: 0', '80%: 1,891']
Client.LIGHTHOUSE : [127] 1,738 / 29,632 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.LODESTAR : [149] 1,346 / 29,329 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.NIMBUS : [131] 1,478 / 29,992 / ['20%: 0', '40%: 0', '60%: 0', '80%: 985']
Client.PRYSM : [156] 1,529 / 30,020 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.TEKU : [178] 1,261 / 29,428 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 10 / 1,277 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.LIGHTHOUSE : [127] 19 / 2,414 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.LODESTAR : [136] 210 / 28,541 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.NIMBUS : [155] 11 / 577 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.PRYSM : [156] 477 / 27,515 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.TEKU : [131] 0 / 0 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Code
def get_correct_target_checkpoint(attestation_slot: int) -> tuple[int, str]: epoch_boundary_slot = 32 * (attestation_slot // 32) target_slot = epoch_boundary_slot while True: try: client_used, block_data = get_raw_block(target_slot) break except BlockNotFound: target_slot -= 1 block = SpecBeaconBlock.ElectraBlockSigned.from_obj(block_data) return target_slot // 32, "0x" + block.message.hash_tree_root().hex() unique_attesters_voting_for_correct_target_included_in_block = set() unique_attesters_voting_for_incorrect_target_included_in_block = set() for att in block.message.body.attestations: correct_target_epoch, correct_target_block_root = get_correct_target_checkpoint(att.data.slot) is_voting_for_correct_target = str(att.data.target.root) == correct_target_block_root for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_target: unique_attesters_voting_for_correct_target_included_in_block.add(val_idx) else: unique_attesters_voting_for_incorrect_target_included_in_block.add(val_idx)
Unique attesters voting for previous epoch target included in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 3,836 / 40,401 / ['20%: 0', '40%: 0', '60%: 1,307', '80%: 5,464']
Client.LIGHTHOUSE : [681] 5,397 / 124,804 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.LODESTAR : [732] 2,556 / 79,759 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.NIMBUS : [748] 7,019 / 82,923 / ['20%: 0', '40%: 990', '60%: 5,398', '80%: 12,106']
Client.PRYSM : [770] 2,105 / 98,970 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.TEKU : [789] 2,508 / 92,119 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 1,814 / 52,540 / ['20%: 0', '40%: 0', '60%: 0', '80%: 560']
Client.LIGHTHOUSE : [127] 4,910 / 101,295 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.LODESTAR : [136] 2,724 / 65,436 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.NIMBUS : [155] 2,298 / 38,399 / ['20%: 0', '40%: 0', '60%: 0', '80%: 2,096']
Client.PRYSM : [156] 4,853 / 71,551 / ['20%: 0', '40%: 0', '60%: 843', '80%: 4,676']
Client.TEKU : [131] 573 / 33,615 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Code
unique_attesters_voting_for_target_prev_epoch = set() unique_attesters_voting_for_target_current_epoch = set() for att in block.message.body.attestations: is_current_epoch_target = att.data.target.epoch == block_slot // 32 for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_current_epoch_target: unique_attesters_voting_for_target_current_epoch.add(val_idx) else: unique_attesters_voting_for_target_prev_epoch.add(val_idx)
Unique attesters voting for current epoch target included in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 44,558 / 63,701 / ['20%: 32,788', '40%: 43,242', '60%: 51,997', '80%: 57,305']
Client.LIGHTHOUSE : [681] 81,489 / 170,960 / ['20%: 61,376', '40%: 87,079', '60%: 92,061', '80%: 93,240']
Client.LODESTAR : [732] 40,360 / 111,489 / ['20%: 30,099', '40%: 36,584', '60%: 41,505', '80%: 48,008']
Client.NIMBUS : [748] 29,285 / 106,595 / ['20%: 8,574', '40%: 22,218', '60%: 34,493', '80%: 46,644']
Client.PRYSM : [770] 50,300 / 101,589 / ['20%: 38,308', '40%: 44,575', '60%: 52,485', '80%: 63,463']
Client.TEKU : [789] 38,538 / 127,405 / ['20%: 29,918', '40%: 33,711', '60%: 39,110', '80%: 44,045']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 47,846 / 67,848 / ['20%: 34,358', '40%: 41,823', '60%: 53,351', '80%: 63,811']
Client.LIGHTHOUSE : [127] 80,333 / 180,225 / ['20%: 52,267', '40%: 67,593', '60%: 100,997', '80%: 101,300']
Client.LODESTAR : [136] 32,545 / 77,140 / ['20%: 33,148', '40%: 33,484', '60%: 33,608', '80%: 33,724']
Client.NIMBUS : [155] 39,057 / 102,524 / ['20%: 33,624', '40%: 35,607', '60%: 38,483', '80%: 46,951']
Client.PRYSM : [156] 51,428 / 134,702 / ['20%: 36,446', '40%: 41,738', '60%: 52,455', '80%: 64,995']
Client.TEKU : [131] 32,671 / 64,979 / ['20%: 33,361', '40%: 33,544', '60%: 33,608', '80%: 33,823']
Code
unique_attesters_voting_for_target_prev_epoch = set() unique_attesters_voting_for_target_current_epoch = set() for att in block.message.body.attestations: is_current_epoch_target = att.data.target.epoch == block_slot // 32 for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_current_epoch_target: unique_attesters_voting_for_target_current_epoch.add(val_idx) else: unique_attesters_voting_for_target_prev_epoch.add(val_idx)
Unique attesters voting for correct target *managed by* client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [14608] 2,869 / 11,056 / ['20%: 1,537', '40%: 2,313', '60%: 3,168', '80%: 4,672']
Client.LIGHTHOUSE : [14608] 3,349 / 10,767 / ['20%: 1,975', '40%: 2,857', '60%: 4,215', '80%: 4,605']
Client.LODESTAR : [14608] 3,429 / 10,971 / ['20%: 2,013', '40%: 2,922', '60%: 4,454', '80%: 4,698']
Client.NIMBUS : [14608] 3,440 / 10,988 / ['20%: 2,017', '40%: 2,935', '60%: 4,483', '80%: 4,698']
Client.PRYSM : [14608] 3,414 / 11,046 / ['20%: 1,993', '40%: 2,920', '60%: 4,400', '80%: 4,694']
Client.TEKU : [14608] 3,350 / 11,009 / ['20%: 1,975', '40%: 2,830', '60%: 4,046', '80%: 4,666']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [3096] 2,490 / 9,062 / ['20%: 1,569', '40%: 1,676', '60%: 2,416', '80%: 3,242']
Client.LIGHTHOUSE : [3096] 2,494 / 9,166 / ['20%: 1,437', '40%: 1,648', '60%: 2,726', '80%: 3,649']
Client.LODESTAR : [3096] 2,486 / 9,193 / ['20%: 1,570', '40%: 1,687', '60%: 2,370', '80%: 3,228']
Client.NIMBUS : [3096] 2,492 / 9,207 / ['20%: 1,569', '40%: 1,681', '60%: 2,398', '80%: 3,231']
Client.PRYSM : [3096] 2,484 / 9,151 / ['20%: 1,569', '40%: 1,682', '60%: 2,392', '80%: 3,229']
Client.TEKU : [3096] 2,444 / 9,127 / ['20%: 1,561', '40%: 1,670', '60%: 2,398', '80%: 3,239']
Code
def get_correct_target_checkpoint(attestation_slot: int) -> tuple[int, str]: epoch_boundary_slot = 32 * (attestation_slot // 32) target_slot = epoch_boundary_slot while True: try: client_used, block_data = get_raw_block(target_slot) break except BlockNotFound: target_slot -= 1 block = SpecBeaconBlock.ElectraBlockSigned.from_obj(block_data) return target_slot // 32, "0x" + block.message.hash_tree_root().hex() attesting_client_unique_attesters_correct_target = {c: set() for c in Client} for att in block.message.body.attestations: correct_target_epoch, correct_target_block_root = get_correct_target_checkpoint(att.data.slot) is_voting_for_correct_target = str(att.data.target.root) == correct_target_block_root for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_target: attesting_client_unique_attesters_correct_target[get_client_for_validator_idx(int(val_idx))].add(val_idx)
Unique attesters voting for correct head included in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 47,922 / 63,701 / ['20%: 34,317', '40%: 47,724', '60%: 54,597', '80%: 58,503']
Client.LIGHTHOUSE : [681] 86,336 / 170,960 / ['20%: 63,046', '40%: 88,974', '60%: 92,177', '80%: 93,914']
Client.LODESTAR : [732] 42,472 / 111,489 / ['20%: 31,080', '40%: 37,501', '60%: 42,268', '80%: 49,284']
Client.NIMBUS : [748] 35,881 / 106,595 / ['20%: 18,537', '40%: 30,785', '60%: 40,291', '80%: 50,767']
Client.PRYSM : [770] 51,990 / 101,587 / ['20%: 39,722', '40%: 45,778', '60%: 53,170', '80%: 63,602']
Client.TEKU : [789] 40,698 / 154,187 / ['20%: 30,356', '40%: 34,878', '60%: 39,928', '80%: 45,475']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 49,597 / 67,848 / ['20%: 35,798', '40%: 43,961', '60%: 53,451', '80%: 64,044']
Client.LIGHTHOUSE : [127] 85,054 / 180,225 / ['20%: 67,096', '40%: 97,633', '60%: 101,012', '80%: 101,291']
Client.LODESTAR : [136] 35,046 / 76,187 / ['20%: 33,396', '40%: 33,546', '60%: 33,632', '80%: 33,755']
Client.NIMBUS : [155] 41,290 / 102,504 / ['20%: 33,758', '40%: 36,700', '60%: 39,963', '80%: 49,355']
Client.PRYSM : [156] 55,665 / 134,702 / ['20%: 39,738', '40%: 47,403', '60%: 55,160', '80%: 70,348']
Client.TEKU : [131] 33,242 / 64,979 / ['20%: 33,387', '40%: 33,548', '60%: 33,610', '80%: 33,823']
Code
def get_correct_head_root(slot: int) -> str: while True: try: client_used, block_data = get_raw_block(slot) break except BlockNotFound: slot -= 1 block = SpecBeaconBlock.ElectraBlockSigned.from_obj(block_data) return "0x" + block.message.hash_tree_root().hex() unique_attesters_voting_for_correct_head_included_in_block = set() unique_attesters_voting_for_incorrect_head_included_in_block = set() for att in block.message.body.attestations: correct_head_root = get_correct_head_root(att.data.slot) is_voting_for_correct_head = str(att.data.beacon_block_root) == correct_head_root for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_head: unique_attesters_voting_for_correct_head_included_in_block.add(val_idx) else: unique_attesters_voting_for_incorrect_head_included_in_block.add(val_idx)
Unique attesters voting for incorrect head included in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 375 / 30,298 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.LIGHTHOUSE : [681] 397 / 31,056 / ['20%: 0', '40%: 0', '60%: 0', '80%: 1']
Client.LODESTAR : [732] 420 / 30,629 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.NIMBUS : [748] 307 / 59,440 / ['20%: 0', '40%: 1', '60%: 2', '80%: 5']
Client.PRYSM : [770] 382 / 59,698 / ['20%: 0', '40%: 3', '60%: 5', '80%: 7']
Client.TEKU : [789] 300 / 31,983 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 39 / 1,943 / ['20%: 0', '40%: 0', '60%: 2', '80%: 4']
Client.LIGHTHOUSE : [127] 25 / 2,471 / ['20%: 0', '40%: 0', '60%: 0', '80%: 1']
Client.LODESTAR : [136] 223 / 28,541 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Client.NIMBUS : [155] 18 / 578 / ['20%: 0', '40%: 0', '60%: 1', '80%: 7']
Client.PRYSM : [156] 494 / 27,515 / ['20%: 0', '40%: 0', '60%: 0', '80%: 3']
Client.TEKU : [131] 1 / 154 / ['20%: 0', '40%: 0', '60%: 0', '80%: 0']
Code
def get_correct_head_root(slot: int) -> str: while True: try: client_used, block_data = get_raw_block(slot) break except BlockNotFound: slot -= 1 block = SpecBeaconBlock.ElectraBlockSigned.from_obj(block_data) return "0x" + block.message.hash_tree_root().hex() unique_attesters_voting_for_correct_head_included_in_block = set() unique_attesters_voting_for_incorrect_head_included_in_block = set() for att in block.message.body.attestations: correct_head_root = get_correct_head_root(att.data.slot) is_voting_for_correct_head = str(att.data.beacon_block_root) == correct_head_root for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_head: unique_attesters_voting_for_correct_head_included_in_block.add(val_idx) else: unique_attesters_voting_for_incorrect_head_included_in_block.add(val_idx)
Unique attesters voting for correct head *managed by* client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [14608] 2,858 / 11,056 / ['20%: 1,532', '40%: 2,300', '60%: 3,162', '80%: 4,670']
Client.LIGHTHOUSE : [14608] 3,333 / 10,767 / ['20%: 1,962', '40%: 2,845', '60%: 4,175', '80%: 4,603']
Client.LODESTAR : [14608] 3,410 / 10,971 / ['20%: 2,000', '40%: 2,903', '60%: 4,380', '80%: 4,696']
Client.NIMBUS : [14608] 3,424 / 10,988 / ['20%: 2,004', '40%: 2,920', '60%: 4,441', '80%: 4,697']
Client.PRYSM : [14608] 3,395 / 11,046 / ['20%: 1,978', '40%: 2,894', '60%: 4,314', '80%: 4,692']
Client.TEKU : [14608] 3,326 / 11,009 / ['20%: 1,958', '40%: 2,799', '60%: 3,954', '80%: 4,665']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [3096] 2,490 / 9,062 / ['20%: 1,569', '40%: 1,676', '60%: 2,416', '80%: 3,242']
Client.LIGHTHOUSE : [3096] 2,492 / 9,166 / ['20%: 1,437', '40%: 1,648', '60%: 2,724', '80%: 3,641']
Client.LODESTAR : [3096] 2,484 / 9,193 / ['20%: 1,570', '40%: 1,686', '60%: 2,369', '80%: 3,222']
Client.NIMBUS : [3096] 2,492 / 9,207 / ['20%: 1,569', '40%: 1,681', '60%: 2,398', '80%: 3,231']
Client.PRYSM : [3096] 2,481 / 9,151 / ['20%: 1,569', '40%: 1,682', '60%: 2,391', '80%: 3,225']
Client.TEKU : [3096] 2,441 / 9,127 / ['20%: 1,561', '40%: 1,669', '60%: 2,391', '80%: 3,228']
Code
def get_correct_head_root(slot: int) -> str: while True: try: client_used, block_data = get_raw_block(slot) break except BlockNotFound: slot -= 1 block = SpecBeaconBlock.ElectraBlockSigned.from_obj(block_data) return "0x" + block.message.hash_tree_root().hex() attesting_client_unique_attesters_correct_head = {c: set() for c in Client} for att in block.message.body.attestations: is_voting_for_correct_head = str(att.data.beacon_block_root) == get_correct_head_root(att.data.slot) for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_head: attesting_client_unique_attesters_correct_head[get_client_for_validator_idx(int(val_idx))].add(val_idx)
Data related to attestations voting for the previous slot only - the most recently made attestations
Number of attestations for previous slot included in block
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 1.17 / 3 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.LIGHTHOUSE : [681] 4.67 / 8 / ['20%: 3.0', '40%: 4.0', '60%: 5.0', '80%: 6.0']
Client.LODESTAR : [732] 2.99 / 6 / ['20%: 3.0', '40%: 3.0', '60%: 3.0', '80%: 3.0']
Client.NIMBUS : [748] 0.66 / 2 / ['20%: 0.0', '40%: 0.0', '60%: 1.0', '80%: 1.0']
Client.PRYSM : [770] 3.08 / 8 / ['20%: 2.0', '40%: 3.0', '60%: 3.0', '80%: 4.0']
Client.TEKU : [789] 2.74 / 8 / ['20%: 2.0', '40%: 3.0', '60%: 3.0', '80%: 3.0']
Client.UNKNOWN : [10276] 3.19 / 8 / ['20%: 2.0', '40%: 3.0', '60%: 3.0', '80%: 5.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 1.50 / 3 / ['20%: 1.0', '40%: 1.0', '60%: 2.0', '80%: 2.0']
Client.LIGHTHOUSE : [127] 3.95 / 8 / ['20%: 2.0', '40%: 3.0', '60%: 5.0', '80%: 6.0']
Client.LODESTAR : [136] 1.83 / 4 / ['20%: 1.0', '40%: 2.0', '60%: 2.0', '80%: 2.0']
Client.NIMBUS : [155] 1.05 / 2 / ['20%: 1.0', '40%: 1.0', '60%: 1.0', '80%: 1.0']
Client.PRYSM : [156] 2.34 / 5 / ['20%: 2.0', '40%: 2.0', '60%: 2.0', '80%: 3.0']
Client.TEKU : [131] 1.85 / 5 / ['20%: 1.0', '40%: 2.0', '60%: 2.0', '80%: 2.0']
Client.UNKNOWN : [2248] 2.22 / 8 / ['20%: 1.0', '40%: 2.0', '60%: 2.0', '80%: 3.0']
Code
len(a for a in block.message.body.attestations if a.data.slot == slot - 1)
Highest number of aggregation bits in an attestation voting for the previous slot
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 25,257.84 / 31,688 / ['20%: 14,789.0', '40%: 29,469.4', '60%: 30,390.4', '80%: 30,780.4']
Client.LIGHTHOUSE : [681] 29,903.80 / 31,436 / ['20%: 29,117.8', '40%: 29,981.8', '60%: 30,356.0', '80%: 30,670.2']
Client.LODESTAR : [732] 25,324.02 / 29,436 / ['20%: 23,907.6', '40%: 25,371.2', '60%: 26,070.4', '80%: 26,978.8']
Client.NIMBUS : [748] 14,266.82 / 31,291 / ['20%: 0.0', '40%: 0.0', '60%: 28,470.2', '80%: 30,177.4']
Client.PRYSM : [770] 29,883.16 / 31,579 / ['20%: 28,777.8', '40%: 29,969.8', '60%: 30,434.2', '80%: 30,709.8']
Client.TEKU : [789] 27,861.01 / 31,115 / ['20%: 28,146.0', '40%: 29,305.0', '60%: 29,771.0', '80%: 30,165.0']
Client.UNKNOWN : [10276] 28,785.46 / 32,179 / ['20%: 28,740.0', '40%: 29,942.8', '60%: 30,441.0', '80%: 30,820.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 33,670.28 / 33,999 / ['20%: 33,423.2', '40%: 33,765.8', '60%: 33,880.0', '80%: 33,915.0']
Client.LIGHTHOUSE : [127] 33,569.65 / 33,903 / ['20%: 33,346.2', '40%: 33,649.0', '60%: 33,751.0', '80%: 33,795.4']
Client.LODESTAR : [136] 33,311.45 / 33,763 / ['20%: 33,138.2', '40%: 33,446.2', '60%: 33,574.2', '80%: 33,636.6']
Client.NIMBUS : [155] 31,907.81 / 33,850 / ['20%: 33,164.4', '40%: 33,511.2', '60%: 33,588.0', '80%: 33,683.0']
Client.PRYSM : [156] 33,416.41 / 33,865 / ['20%: 33,407.4', '40%: 33,614.0', '60%: 33,675.6', '80%: 33,729.8']
Client.TEKU : [131] 31,714.07 / 33,795 / ['20%: 33,054.4', '40%: 33,441.0', '60%: 33,558.4', '80%: 33,632.0']
Client.UNKNOWN : [2248] 33,079.87 / 34,064 / ['20%: 33,317.0', '40%: 33,540.6', '60%: 33,643.0', '80%: 33,739.0']
Code
max(sum(att.aggregation_bits) for att in attestations_for_prev_slot)
Highest number of committee bits in an attestation voting for the previous slot
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 63.55 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.LIGHTHOUSE : [681] 64.00 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.LODESTAR : [732] 63.72 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.NIMBUS : [748] 30.94 / 64 / ['20%: 0.0', '40%: 0.0', '60%: 64.0', '80%: 64.0']
Client.PRYSM : [770] 64.00 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.TEKU : [789] 61.19 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.UNKNOWN : [10276] 61.62 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 64.00 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.LIGHTHOUSE : [127] 64.00 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.LODESTAR : [136] 64.00 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.NIMBUS : [155] 61.11 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.PRYSM : [156] 64.00 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.TEKU : [131] 61.36 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Client.UNKNOWN : [2248] 63.49 / 64 / ['20%: 64.0', '40%: 64.0', '60%: 64.0', '80%: 64.0']
Code
max(sum(att.committee_bits) for att in attestations_for_prev_slot)
Number of unique attesters voting for the previous slot whose attestation was included in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 25,324.07 / 31,688 / ['20%: 14,805.8', '40%: 29,531.8', '60%: 30,443.8', '80%: 30,812.6']
Client.LIGHTHOUSE : [681] 29,990.20 / 31,483 / ['20%: 29,182.2', '40%: 30,057.6', '60%: 30,406.0', '80%: 30,719.0']
Client.LODESTAR : [732] 29,358.46 / 31,091 / ['20%: 28,528.2', '40%: 29,608.0', '60%: 29,949.8', '80%: 30,311.2']
Client.NIMBUS : [748] 14,272.19 / 31,291 / ['20%: 0.0', '40%: 0.0', '60%: 28,470.2', '80%: 30,177.4']
Client.PRYSM : [770] 30,299.20 / 31,895 / ['20%: 29,102.6', '40%: 30,406.8', '60%: 30,788.4', '80%: 31,026.4']
Client.TEKU : [789] 28,027.03 / 31,135 / ['20%: 28,265.0', '40%: 29,397.0', '60%: 29,853.0', '80%: 30,219.0']
Client.UNKNOWN : [10276] 28,955.52 / 32,388 / ['20%: 28,874.0', '40%: 30,036.0', '60%: 30,517.0', '80%: 30,918.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 33,769.94 / 33,999 / ['20%: 33,669.4', '40%: 33,837.6', '60%: 33,888.4', '80%: 33,916.4']
Client.LIGHTHOUSE : [127] 33,601.24 / 33,916 / ['20%: 33,432.2', '40%: 33,672.8', '60%: 33,769.6', '80%: 33,813.0']
Client.LODESTAR : [136] 33,346.81 / 33,763 / ['20%: 33,158.4', '40%: 33,453.4', '60%: 33,581.8', '80%: 33,642.0']
Client.NIMBUS : [155] 31,910.50 / 33,850 / ['20%: 33,166.4', '40%: 33,511.2', '60%: 33,588.0', '80%: 33,683.0']
Client.PRYSM : [156] 33,894.15 / 34,063 / ['20%: 33,887.4', '40%: 33,944.2', '60%: 33,977.2', '80%: 34,001.6']
Client.TEKU : [131] 31,736.89 / 33,797 / ['20%: 33,062.6', '40%: 33,462.0', '60%: 33,564.0', '80%: 33,640.6']
Client.UNKNOWN : [2248] 33,326.06 / 34,075 / ['20%: 33,439.0', '40%: 33,603.6', '60%: 33,757.0', '80%: 33,961.2']
Code
unique_attesters_for_prev_slot = set() for att in block.message.body.attestations: if att.data.slot != slot - 1: continue commmitees = await get_committee(state_id=att.data.slot) agg_bits_offset = 0 for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: val_count = len(committee["validators"]) committee_agg_bits = att.aggregation_bits[ agg_bits_offset:agg_bits_offset + val_count] agg_bits_offset += val_count for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: unique_attesters_for_prev_slot.add(val_idx)
Number of unique attesters voting for the previous slot + correct target in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 25,130.34 / 31,688 / ['20%: 14,730.0', '40%: 29,531.8', '60%: 30,443.8', '80%: 30,812.6']
Client.LIGHTHOUSE : [681] 29,973.88 / 31,483 / ['20%: 29,182.2', '40%: 30,057.6', '60%: 30,406.0', '80%: 30,719.0']
Client.LODESTAR : [732] 29,358.46 / 31,091 / ['20%: 28,528.2', '40%: 29,608.0', '60%: 29,949.8', '80%: 30,311.2']
Client.NIMBUS : [748] 14,244.86 / 31,291 / ['20%: 0.0', '40%: 0.0', '60%: 28,470.2', '80%: 30,177.4']
Client.PRYSM : [770] 30,265.58 / 31,895 / ['20%: 29,059.2', '40%: 30,406.8', '60%: 30,788.4', '80%: 31,026.4']
Client.TEKU : [789] 28,005.62 / 31,135 / ['20%: 28,265.0', '40%: 29,397.0', '60%: 29,853.0', '80%: 30,219.0']
Client.UNKNOWN : [10276] 28,927.07 / 32,388 / ['20%: 28,868.4', '40%: 30,036.0', '60%: 30,517.0', '80%: 30,918.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 33,769.94 / 33,999 / ['20%: 33,669.4', '40%: 33,837.6', '60%: 33,888.4', '80%: 33,916.4']
Client.LIGHTHOUSE : [127] 33,601.24 / 33,916 / ['20%: 33,432.2', '40%: 33,672.8', '60%: 33,769.6', '80%: 33,813.0']
Client.LODESTAR : [136] 33,136.65 / 33,763 / ['20%: 33,158.4', '40%: 33,453.4', '60%: 33,581.8', '80%: 33,642.0']
Client.NIMBUS : [155] 31,910.50 / 33,850 / ['20%: 33,166.4', '40%: 33,511.2', '60%: 33,588.0', '80%: 33,683.0']
Client.PRYSM : [156] 33,805.07 / 34,063 / ['20%: 33,886.4', '40%: 33,940.8', '60%: 33,977.2', '80%: 34,001.6']
Client.TEKU : [131] 31,736.89 / 33,797 / ['20%: 33,062.6', '40%: 33,462.0', '60%: 33,564.0', '80%: 33,640.6']
Client.UNKNOWN : [2248] 33,277.04 / 34,075 / ['20%: 33,437.0', '40%: 33,602.6', '60%: 33,756.0', '80%: 33,961.0']
Code
unique_attesters_for_prev_slot_correct_target = set() for att in block.message.body.attestations: if att.data.slot != slot - 1: continue commmitees = await get_committee(state_id=att.data.slot) agg_bits_offset = 0 for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_target: unique_attesters_for_prev_slot_correct_target.add(val_idx)
Number of unique attesters voting for the previous slot + correct head in block built by client
Epoch range: 2,248 - 2,748
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [612] 25,035.95 / 31,688 / ['20%: 14,685.6', '40%: 29,495.4', '60%: 30,443.8', '80%: 30,812.6']
Client.LIGHTHOUSE : [614] 30,149.36 / 31,483 / ['20%: 29,675.0', '40%: 30,189.0', '60%: 30,454.0', '80%: 30,836.0']
Client.LODESTAR : [670] 29,170.57 / 31,091 / ['20%: 29,037.2', '40%: 29,719.4', '60%: 29,988.0', '80%: 30,340.8']
Client.NIMBUS : [656] 14,870.08 / 31,291 / ['20%: 0.0', '40%: 0.0', '60%: 29,421.8', '80%: 30,244.6']
Client.PRYSM : [699] 30,400.53 / 31,890 / ['20%: 29,787.0', '40%: 30,500.0', '60%: 30,824.0', '80%: 31,046.0']
Client.TEKU : [721] 28,028.10 / 31,135 / ['20%: 28,623.0', '40%: 29,559.0', '60%: 29,906.0', '80%: 30,262.6']
Client.UNKNOWN : [9329] 28,998.13 / 32,386 / ['20%: 29,407.0', '40%: 30,180.0', '60%: 30,583.0', '80%: 30,963.0']
Epoch range: 8,450 – 8,550
Format: [sample size] mean/max/quantiles
Client.GRANDINE : [143] 33,751.57 / 33,999 / ['20%: 33,669.2', '40%: 33,836.6', '60%: 33,888.4', '80%: 33,915.6']
Client.LIGHTHOUSE : [127] 33,596.02 / 33,916 / ['20%: 33,390.2', '40%: 33,672.8', '60%: 33,769.6', '80%: 33,812.4']
Client.LODESTAR : [136] 33,131.01 / 33,763 / ['20%: 33,158.4', '40%: 33,453.4', '60%: 33,581.0', '80%: 33,642.0']
Client.NIMBUS : [155] 31,907.81 / 33,850 / ['20%: 33,164.4', '40%: 33,511.2', '60%: 33,588.0', '80%: 33,683.0']
Client.PRYSM : [156] 33,800.87 / 34,063 / ['20%: 33,883.6', '40%: 33,940.0', '60%: 33,977.0', '80%: 34,001.6']
Client.TEKU : [131] 31,735.60 / 33,797 / ['20%: 33,062.6', '40%: 33,462.0', '60%: 33,564.0', '80%: 33,640.6']
Client.UNKNOWN : [2248] 33,271.59 / 34,075 / ['20%: 33,430.6', '40%: 33,599.6', '60%: 33,753.0', '80%: 33,959.2']
Code
unique_attesters_for_prev_slot_correct_head = set() for att in block.message.body.attestations: if att.data.slot != slot - 1: continue commmitees = await get_committee(state_id=att.data.slot) agg_bits_offset = 0 for committee in commmitees: idx = int(committee["index"]) if att.committee_bits[idx] == 1: for val_committee_idx, val_idx in enumerate(committee["validators"]): if committee_agg_bits[val_committee_idx] == 1: if is_voting_for_correct_head: unique_attesters_for_prev_slot_correct_head.add(val_idx)