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

feat: restart aware doppelganger protection #6012

Merged
merged 15 commits into from
Oct 17, 2023

Conversation

nflaig
Copy link
Member

@nflaig nflaig commented Oct 1, 2023

Motivation

Closes #5856

Description

Skip doppelganger detection for validator if client restart is detected by checking if an attestation from previous epoch exists for this validator in the slashing protection database. This means there is now almost no downside to using doppelganger protection while still getting all security benefits. The only time doppelganger detection will run is if validator is imported for the first time or has not been active for more than one epoch due to a longer downtime / maintenance.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 1, 2023

Performance Report

✔️ no performance regression detected

Full benchmark results
Benchmark suite Current: 3b13ea3 Previous: 6629242 Ratio
getPubkeys - index2pubkey - req 1000 vs - 250000 vc 784.27 us/op 615.31 us/op 1.27
getPubkeys - validatorsArr - req 1000 vs - 250000 vc 110.07 us/op 101.07 us/op 1.09
BLS verify - blst-native 1.5967 ms/op 1.4251 ms/op 1.12
BLS verifyMultipleSignatures 3 - blst-native 3.4262 ms/op 2.9524 ms/op 1.16
BLS verifyMultipleSignatures 8 - blst-native 7.9562 ms/op 6.3172 ms/op 1.26
BLS verifyMultipleSignatures 32 - blst-native 28.540 ms/op 23.128 ms/op 1.23
BLS verifyMultipleSignatures 64 - blst-native 55.543 ms/op 48.135 ms/op 1.15
BLS verifyMultipleSignatures 128 - blst-native 100.16 ms/op 96.326 ms/op 1.04
BLS deserializing 10000 signatures 1.0016 s/op 1.0053 s/op 1.00
BLS deserializing 100000 signatures 10.090 s/op 9.4375 s/op 1.07
BLS verifyMultipleSignatures - same message - 3 - blst-native 1.4516 ms/op 1.3825 ms/op 1.05
BLS verifyMultipleSignatures - same message - 8 - blst-native 1.8353 ms/op 1.6142 ms/op 1.14
BLS verifyMultipleSignatures - same message - 32 - blst-native 2.7495 ms/op 2.4025 ms/op 1.14
BLS verifyMultipleSignatures - same message - 64 - blst-native 4.2983 ms/op 3.5583 ms/op 1.21
BLS verifyMultipleSignatures - same message - 128 - blst-native 6.4716 ms/op 5.7928 ms/op 1.12
BLS aggregatePubkeys 32 - blst-native 29.896 us/op 26.634 us/op 1.12
BLS aggregatePubkeys 128 - blst-native 118.23 us/op 101.78 us/op 1.16
getAttestationsForBlock 51.447 ms/op 45.755 ms/op 1.12
isKnown best case - 1 super set check 390.00 ns/op 315.00 ns/op 1.24
isKnown normal case - 2 super set checks 409.00 ns/op 290.00 ns/op 1.41
isKnown worse case - 16 super set checks 405.00 ns/op 396.00 ns/op 1.02
CheckpointStateCache - add get delete 6.5570 us/op 5.6820 us/op 1.15
validate api signedAggregateAndProof - struct 3.1817 ms/op 2.8916 ms/op 1.10
validate gossip signedAggregateAndProof - struct 3.1839 ms/op 2.9032 ms/op 1.10
validate gossip attestation - vc 640000 1.5235 ms/op 1.4491 ms/op 1.05
batch validate gossip attestation - vc 640000 - chunk 32 197.74 us/op 172.82 us/op 1.14
batch validate gossip attestation - vc 640000 - chunk 64 182.57 us/op 147.94 us/op 1.23
batch validate gossip attestation - vc 640000 - chunk 128 169.99 us/op 138.50 us/op 1.23
batch validate gossip attestation - vc 640000 - chunk 256 183.62 us/op 136.45 us/op 1.35
pickEth1Vote - no votes 1.5724 ms/op 1.3034 ms/op 1.21
pickEth1Vote - max votes 17.175 ms/op 9.6698 ms/op 1.78
pickEth1Vote - Eth1Data hashTreeRoot value x2048 31.066 ms/op 17.959 ms/op 1.73
pickEth1Vote - Eth1Data hashTreeRoot tree x2048 47.284 ms/op 25.508 ms/op 1.85
pickEth1Vote - Eth1Data fastSerialize value x2048 905.25 us/op 647.85 us/op 1.40
pickEth1Vote - Eth1Data fastSerialize tree x2048 8.6433 ms/op 8.0548 ms/op 1.07
bytes32 toHexString 760.00 ns/op 571.00 ns/op 1.33
bytes32 Buffer.toString(hex) 434.00 ns/op 318.00 ns/op 1.36
bytes32 Buffer.toString(hex) from Uint8Array 637.00 ns/op 498.00 ns/op 1.28
bytes32 Buffer.toString(hex) + 0x 365.00 ns/op 332.00 ns/op 1.10
Object access 1 prop 0.27300 ns/op 0.19400 ns/op 1.41
Map access 1 prop 0.20100 ns/op 0.16100 ns/op 1.25
Object get x1000 9.7450 ns/op 7.7630 ns/op 1.26
Map get x1000 1.0020 ns/op 0.65900 ns/op 1.52
Object set x1000 84.546 ns/op 56.583 ns/op 1.49
Map set x1000 58.406 ns/op 43.827 ns/op 1.33
Return object 10000 times 0.42500 ns/op 0.25810 ns/op 1.65
Throw Error 10000 times 5.5133 us/op 3.9242 us/op 1.40
fastMsgIdFn sha256 / 200 bytes 4.3940 us/op 3.3420 us/op 1.31
fastMsgIdFn h32 xxhash / 200 bytes 345.00 ns/op 322.00 ns/op 1.07
fastMsgIdFn h64 xxhash / 200 bytes 441.00 ns/op 370.00 ns/op 1.19
fastMsgIdFn sha256 / 1000 bytes 14.244 us/op 11.568 us/op 1.23
fastMsgIdFn h32 xxhash / 1000 bytes 550.00 ns/op 428.00 ns/op 1.29
fastMsgIdFn h64 xxhash / 1000 bytes 608.00 ns/op 420.00 ns/op 1.45
fastMsgIdFn sha256 / 10000 bytes 130.02 us/op 111.41 us/op 1.17
fastMsgIdFn h32 xxhash / 10000 bytes 2.5230 us/op 2.0880 us/op 1.21
fastMsgIdFn h64 xxhash / 10000 bytes 1.6300 us/op 1.3500 us/op 1.21
send data - 1000 256B messages 27.274 ms/op 19.418 ms/op 1.40
send data - 1000 512B messages 34.659 ms/op 26.806 ms/op 1.29
send data - 1000 1024B messages 49.518 ms/op 41.353 ms/op 1.20
send data - 1000 1200B messages 39.634 ms/op 23.193 ms/op 1.71
send data - 1000 2048B messages 37.610 ms/op 31.930 ms/op 1.18
send data - 1000 4096B messages 39.972 ms/op 36.592 ms/op 1.09
send data - 1000 16384B messages 86.925 ms/op 82.612 ms/op 1.05
send data - 1000 65536B messages 356.46 ms/op 277.03 ms/op 1.29
enrSubnets - fastDeserialize 64 bits 1.5690 us/op 1.2370 us/op 1.27
enrSubnets - ssz BitVector 64 bits 527.00 ns/op 442.00 ns/op 1.19
enrSubnets - fastDeserialize 4 bits 216.00 ns/op 173.00 ns/op 1.25
enrSubnets - ssz BitVector 4 bits 537.00 ns/op 452.00 ns/op 1.19
prioritizePeers score -10:0 att 32-0.1 sync 2-0 130.07 us/op 119.70 us/op 1.09
prioritizePeers score 0:0 att 32-0.25 sync 2-0.25 170.02 us/op 128.48 us/op 1.32
prioritizePeers score 0:0 att 32-0.5 sync 2-0.5 232.66 us/op 177.82 us/op 1.31
prioritizePeers score 0:0 att 64-0.75 sync 4-0.75 390.41 us/op 308.47 us/op 1.27
prioritizePeers score 0:0 att 64-1 sync 4-1 462.04 us/op 359.71 us/op 1.28
array of 16000 items push then shift 2.0135 us/op 1.7205 us/op 1.17
LinkedList of 16000 items push then shift 11.938 ns/op 9.5140 ns/op 1.25
array of 16000 items push then pop 118.18 ns/op 101.37 ns/op 1.17
LinkedList of 16000 items push then pop 11.135 ns/op 9.4450 ns/op 1.18
array of 24000 items push then shift 2.9073 us/op 2.7036 us/op 1.08
LinkedList of 24000 items push then shift 11.852 ns/op 9.0990 ns/op 1.30
array of 24000 items push then pop 162.96 ns/op 130.38 ns/op 1.25
LinkedList of 24000 items push then pop 10.808 ns/op 9.1160 ns/op 1.19
intersect bitArray bitLen 8 8.0120 ns/op 7.0380 ns/op 1.14
intersect array and set length 8 84.455 ns/op 57.763 ns/op 1.46
intersect bitArray bitLen 128 37.774 ns/op 32.575 ns/op 1.16
intersect array and set length 128 1.1918 us/op 784.24 ns/op 1.52
bitArray.getTrueBitIndexes() bitLen 128 2.1790 us/op 1.5630 us/op 1.39
bitArray.getTrueBitIndexes() bitLen 248 3.4320 us/op 2.5690 us/op 1.34
bitArray.getTrueBitIndexes() bitLen 512 7.0070 us/op 5.3900 us/op 1.30
Buffer.concat 32 items 1.1730 us/op 1.1060 us/op 1.06
Uint8Array.set 32 items 2.6920 us/op 2.8340 us/op 0.95
Set add up to 64 items then delete first 5.5429 us/op 4.4916 us/op 1.23
OrderedSet add up to 64 items then delete first 7.1145 us/op 5.5283 us/op 1.29
Set add up to 64 items then delete last 5.6427 us/op 4.8138 us/op 1.17
OrderedSet add up to 64 items then delete last 6.9541 us/op 6.3924 us/op 1.09
Set add up to 64 items then delete middle 5.8593 us/op 4.7753 us/op 1.23
OrderedSet add up to 64 items then delete middle 8.9310 us/op 8.0692 us/op 1.11
Set add up to 128 items then delete first 11.620 us/op 9.7055 us/op 1.20
OrderedSet add up to 128 items then delete first 15.881 us/op 12.017 us/op 1.32
Set add up to 128 items then delete last 11.266 us/op 10.041 us/op 1.12
OrderedSet add up to 128 items then delete last 14.959 us/op 13.267 us/op 1.13
Set add up to 128 items then delete middle 11.331 us/op 9.4233 us/op 1.20
OrderedSet add up to 128 items then delete middle 21.589 us/op 18.259 us/op 1.18
Set add up to 256 items then delete first 23.941 us/op 18.687 us/op 1.28
OrderedSet add up to 256 items then delete first 31.438 us/op 23.279 us/op 1.35
Set add up to 256 items then delete last 21.919 us/op 19.208 us/op 1.14
OrderedSet add up to 256 items then delete last 28.422 us/op 26.157 us/op 1.09
Set add up to 256 items then delete middle 22.634 us/op 19.159 us/op 1.18
OrderedSet add up to 256 items then delete middle 57.576 us/op 47.138 us/op 1.22
transfer serialized Status (84 B) 2.1890 us/op 1.7810 us/op 1.23
copy serialized Status (84 B) 1.6780 us/op 1.4960 us/op 1.12
transfer serialized SignedVoluntaryExit (112 B) 2.1200 us/op 1.9500 us/op 1.09
copy serialized SignedVoluntaryExit (112 B) 1.8160 us/op 1.5660 us/op 1.16
transfer serialized ProposerSlashing (416 B) 2.5440 us/op 2.1790 us/op 1.17
copy serialized ProposerSlashing (416 B) 2.4460 us/op 2.0790 us/op 1.18
transfer serialized Attestation (485 B) 2.7060 us/op 2.2280 us/op 1.21
copy serialized Attestation (485 B) 2.6450 us/op 2.1820 us/op 1.21
transfer serialized AttesterSlashing (33232 B) 2.6610 us/op 2.2290 us/op 1.19
copy serialized AttesterSlashing (33232 B) 11.008 us/op 6.1410 us/op 1.79
transfer serialized Small SignedBeaconBlock (128000 B) 4.5420 us/op 2.5920 us/op 1.75
copy serialized Small SignedBeaconBlock (128000 B) 26.295 us/op 16.065 us/op 1.64
transfer serialized Avg SignedBeaconBlock (200000 B) 5.0070 us/op 3.2470 us/op 1.54
copy serialized Avg SignedBeaconBlock (200000 B) 37.364 us/op 24.295 us/op 1.54
transfer serialized BlobsSidecar (524380 B) 5.3850 us/op 4.2420 us/op 1.27
copy serialized BlobsSidecar (524380 B) 126.81 us/op 105.35 us/op 1.20
transfer serialized Big SignedBeaconBlock (1000000 B) 5.4250 us/op 4.3160 us/op 1.26
copy serialized Big SignedBeaconBlock (1000000 B) 202.30 us/op 257.56 us/op 0.79
pass gossip attestations to forkchoice per slot 4.3344 ms/op 3.9366 ms/op 1.10
forkChoice updateHead vc 100000 bc 64 eq 0 863.84 us/op 878.48 us/op 0.98
forkChoice updateHead vc 600000 bc 64 eq 0 7.0075 ms/op 5.5774 ms/op 1.26
forkChoice updateHead vc 1000000 bc 64 eq 0 8.2107 ms/op 8.2465 ms/op 1.00
forkChoice updateHead vc 600000 bc 320 eq 0 4.6621 ms/op 5.1731 ms/op 0.90
forkChoice updateHead vc 600000 bc 1200 eq 0 4.7437 ms/op 5.3054 ms/op 0.89
forkChoice updateHead vc 600000 bc 7200 eq 0 5.7120 ms/op 6.2372 ms/op 0.92
forkChoice updateHead vc 600000 bc 64 eq 1000 11.816 ms/op 12.820 ms/op 0.92
forkChoice updateHead vc 600000 bc 64 eq 10000 13.671 ms/op 12.981 ms/op 1.05
forkChoice updateHead vc 600000 bc 64 eq 300000 22.627 ms/op 34.545 ms/op 0.65
computeDeltas 500000 validators 300 proto nodes 7.0816 ms/op 6.7715 ms/op 1.05
computeDeltas 500000 validators 1200 proto nodes 6.9048 ms/op 6.7413 ms/op 1.02
computeDeltas 500000 validators 7200 proto nodes 6.9689 ms/op 6.7593 ms/op 1.03
computeDeltas 750000 validators 300 proto nodes 10.562 ms/op 10.605 ms/op 1.00
computeDeltas 750000 validators 1200 proto nodes 10.489 ms/op 10.653 ms/op 0.98
computeDeltas 750000 validators 7200 proto nodes 10.225 ms/op 10.103 ms/op 1.01
computeDeltas 1400000 validators 300 proto nodes 18.653 ms/op 18.524 ms/op 1.01
computeDeltas 1400000 validators 1200 proto nodes 18.625 ms/op 18.542 ms/op 1.00
computeDeltas 1400000 validators 7200 proto nodes 18.576 ms/op 18.254 ms/op 1.02
computeDeltas 2100000 validators 300 proto nodes 27.837 ms/op 27.374 ms/op 1.02
computeDeltas 2100000 validators 1200 proto nodes 27.261 ms/op 27.733 ms/op 0.98
computeDeltas 2100000 validators 7200 proto nodes 27.783 ms/op 28.221 ms/op 0.98
computeProposerBoostScoreFromBalances 500000 validators 3.3787 ms/op 3.4873 ms/op 0.97
computeProposerBoostScoreFromBalances 750000 validators 3.3152 ms/op 3.3826 ms/op 0.98
computeProposerBoostScoreFromBalances 1400000 validators 3.3511 ms/op 3.3951 ms/op 0.99
computeProposerBoostScoreFromBalances 2100000 validators 3.3807 ms/op 3.4965 ms/op 0.97
altair processAttestation - 250000 vs - 7PWei normalcase 2.5817 ms/op 3.9137 ms/op 0.66
altair processAttestation - 250000 vs - 7PWei worstcase 3.3462 ms/op 3.2501 ms/op 1.03
altair processAttestation - setStatus - 1/6 committees join 175.76 us/op 209.63 us/op 0.84
altair processAttestation - setStatus - 1/3 committees join 356.57 us/op 368.17 us/op 0.97
altair processAttestation - setStatus - 1/2 committees join 454.75 us/op 476.76 us/op 0.95
altair processAttestation - setStatus - 2/3 committees join 579.40 us/op 591.40 us/op 0.98
altair processAttestation - setStatus - 4/5 committees join 793.85 us/op 917.07 us/op 0.87
altair processAttestation - setStatus - 100% committees join 916.42 us/op 1.0854 ms/op 0.84
altair processBlock - 250000 vs - 7PWei normalcase 7.7012 ms/op 8.5156 ms/op 0.90
altair processBlock - 250000 vs - 7PWei normalcase hashState 30.640 ms/op 34.546 ms/op 0.89
altair processBlock - 250000 vs - 7PWei worstcase 38.665 ms/op 42.558 ms/op 0.91
altair processBlock - 250000 vs - 7PWei worstcase hashState 92.296 ms/op 98.707 ms/op 0.94
phase0 processBlock - 250000 vs - 7PWei normalcase 2.6030 ms/op 3.0899 ms/op 0.84
phase0 processBlock - 250000 vs - 7PWei worstcase 34.837 ms/op 33.890 ms/op 1.03
altair processEth1Data - 250000 vs - 7PWei normalcase 585.63 us/op 769.23 us/op 0.76
getExpectedWithdrawals 250000 eb:1,eth1:1,we:0,wn:0,smpl:15 13.816 us/op 16.213 us/op 0.85
getExpectedWithdrawals 250000 eb:0.95,eth1:0.1,we:0.05,wn:0,smpl:219 39.771 us/op 80.764 us/op 0.49
getExpectedWithdrawals 250000 eb:0.95,eth1:0.3,we:0.05,wn:0,smpl:42 19.585 us/op 36.421 us/op 0.54
getExpectedWithdrawals 250000 eb:0.95,eth1:0.7,we:0.05,wn:0,smpl:18 15.357 us/op 18.376 us/op 0.84
getExpectedWithdrawals 250000 eb:0.1,eth1:0.1,we:0,wn:0,smpl:1020 189.35 us/op 206.53 us/op 0.92
getExpectedWithdrawals 250000 eb:0.03,eth1:0.03,we:0,wn:0,smpl:11777 1.2744 ms/op 1.5843 ms/op 0.80
getExpectedWithdrawals 250000 eb:0.01,eth1:0.01,we:0,wn:0,smpl:16384 1.6021 ms/op 2.0299 ms/op 0.79
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,smpl:16384 1.7021 ms/op 2.3910 ms/op 0.71
getExpectedWithdrawals 250000 eb:0,eth1:0,we:0,wn:0,nocache,smpl:16384 3.8583 ms/op 5.1279 ms/op 0.75
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,smpl:16384 2.6691 ms/op 3.1922 ms/op 0.84
getExpectedWithdrawals 250000 eb:0,eth1:1,we:0,wn:0,nocache,smpl:16384 5.5592 ms/op 7.7326 ms/op 0.72
Tree 40 250000 create 325.73 ms/op 377.50 ms/op 0.86
Tree 40 250000 get(125000) 209.29 ns/op 218.57 ns/op 0.96
Tree 40 250000 set(125000) 949.06 ns/op 1.4814 us/op 0.64
Tree 40 250000 toArray() 21.789 ms/op 26.852 ms/op 0.81
Tree 40 250000 iterate all - toArray() + loop 22.475 ms/op 25.939 ms/op 0.87
Tree 40 250000 iterate all - get(i) 73.493 ms/op 80.161 ms/op 0.92
MutableVector 250000 create 13.950 ms/op 18.775 ms/op 0.74
MutableVector 250000 get(125000) 7.4330 ns/op 7.2010 ns/op 1.03
MutableVector 250000 set(125000) 274.45 ns/op 533.06 ns/op 0.51
MutableVector 250000 toArray() 3.9883 ms/op 5.1606 ms/op 0.77
MutableVector 250000 iterate all - toArray() + loop 3.8675 ms/op 6.2992 ms/op 0.61
MutableVector 250000 iterate all - get(i) 1.6049 ms/op 1.7007 ms/op 0.94
Array 250000 create 3.5980 ms/op 4.8154 ms/op 0.75
Array 250000 clone - spread 1.0645 ms/op 1.4943 ms/op 0.71
Array 250000 get(125000) 0.52300 ns/op 0.65200 ns/op 0.80
Array 250000 set(125000) 0.61200 ns/op 0.82500 ns/op 0.74
Array 250000 iterate all - loop 88.681 us/op 97.900 us/op 0.91
effectiveBalanceIncrements clone Uint8Array 300000 36.848 us/op 70.485 us/op 0.52
effectiveBalanceIncrements clone MutableVector 300000 299.00 ns/op 400.00 ns/op 0.75
effectiveBalanceIncrements rw all Uint8Array 300000 200.96 us/op 200.41 us/op 1.00
effectiveBalanceIncrements rw all MutableVector 300000 84.709 ms/op 202.66 ms/op 0.42
phase0 afterProcessEpoch - 250000 vs - 7PWei 120.15 ms/op 149.82 ms/op 0.80
phase0 beforeProcessEpoch - 250000 vs - 7PWei 39.918 ms/op 79.296 ms/op 0.50
altair processEpoch - mainnet_e81889 526.42 ms/op 660.13 ms/op 0.80
mainnet_e81889 - altair beforeProcessEpoch 54.503 ms/op 85.251 ms/op 0.64
mainnet_e81889 - altair processJustificationAndFinalization 25.988 us/op 28.678 us/op 0.91
mainnet_e81889 - altair processInactivityUpdates 7.1850 ms/op 10.426 ms/op 0.69
mainnet_e81889 - altair processRewardsAndPenalties 66.984 ms/op 82.130 ms/op 0.82
mainnet_e81889 - altair processRegistryUpdates 3.0340 us/op 5.6490 us/op 0.54
mainnet_e81889 - altair processSlashings 474.00 ns/op 1.2090 us/op 0.39
mainnet_e81889 - altair processEth1DataReset 526.00 ns/op 875.00 ns/op 0.60
mainnet_e81889 - altair processEffectiveBalanceUpdates 1.2915 ms/op 1.3786 ms/op 0.94
mainnet_e81889 - altair processSlashingsReset 3.8490 us/op 3.7340 us/op 1.03
mainnet_e81889 - altair processRandaoMixesReset 4.7410 us/op 7.6340 us/op 0.62
mainnet_e81889 - altair processHistoricalRootsUpdate 670.00 ns/op 1.3900 us/op 0.48
mainnet_e81889 - altair processParticipationFlagUpdates 1.9460 us/op 4.2660 us/op 0.46
mainnet_e81889 - altair processSyncCommitteeUpdates 807.00 ns/op 1.3920 us/op 0.58
mainnet_e81889 - altair afterProcessEpoch 126.68 ms/op 148.38 ms/op 0.85
capella processEpoch - mainnet_e217614 1.5461 s/op 1.8955 s/op 0.82
mainnet_e217614 - capella beforeProcessEpoch 248.93 ms/op 363.85 ms/op 0.68
mainnet_e217614 - capella processJustificationAndFinalization 16.599 us/op 29.140 us/op 0.57
mainnet_e217614 - capella processInactivityUpdates 20.181 ms/op 28.608 ms/op 0.71
mainnet_e217614 - capella processRewardsAndPenalties 266.58 ms/op 412.98 ms/op 0.65
mainnet_e217614 - capella processRegistryUpdates 19.832 us/op 43.689 us/op 0.45
mainnet_e217614 - capella processSlashings 572.00 ns/op 2.1910 us/op 0.26
mainnet_e217614 - capella processEth1DataReset 602.00 ns/op 1.8130 us/op 0.33
mainnet_e217614 - capella processEffectiveBalanceUpdates 4.2944 ms/op 7.8350 ms/op 0.55
mainnet_e217614 - capella processSlashingsReset 3.2210 us/op 7.5030 us/op 0.43
mainnet_e217614 - capella processRandaoMixesReset 6.8760 us/op 11.288 us/op 0.61
mainnet_e217614 - capella processHistoricalRootsUpdate 1.5170 us/op 1.8090 us/op 0.84
mainnet_e217614 - capella processParticipationFlagUpdates 1.8050 us/op 5.6840 us/op 0.32
mainnet_e217614 - capella afterProcessEpoch 313.27 ms/op 379.73 ms/op 0.82
phase0 processEpoch - mainnet_e58758 441.91 ms/op 685.00 ms/op 0.65
mainnet_e58758 - phase0 beforeProcessEpoch 120.28 ms/op 182.41 ms/op 0.66
mainnet_e58758 - phase0 processJustificationAndFinalization 16.888 us/op 28.198 us/op 0.60
mainnet_e58758 - phase0 processRewardsAndPenalties 53.032 ms/op 68.471 ms/op 0.77
mainnet_e58758 - phase0 processRegistryUpdates 10.713 us/op 16.250 us/op 0.66
mainnet_e58758 - phase0 processSlashings 523.00 ns/op 783.00 ns/op 0.67
mainnet_e58758 - phase0 processEth1DataReset 454.00 ns/op 1.0590 us/op 0.43
mainnet_e58758 - phase0 processEffectiveBalanceUpdates 1.0895 ms/op 1.1312 ms/op 0.96
mainnet_e58758 - phase0 processSlashingsReset 2.1080 us/op 4.6780 us/op 0.45
mainnet_e58758 - phase0 processRandaoMixesReset 3.9240 us/op 9.5780 us/op 0.41
mainnet_e58758 - phase0 processHistoricalRootsUpdate 651.00 ns/op 1.2250 us/op 0.53
mainnet_e58758 - phase0 processParticipationRecordUpdates 4.0520 us/op 7.2020 us/op 0.56
mainnet_e58758 - phase0 afterProcessEpoch 110.50 ms/op 119.39 ms/op 0.93
phase0 processEffectiveBalanceUpdates - 250000 normalcase 1.3015 ms/op 1.5821 ms/op 0.82
phase0 processEffectiveBalanceUpdates - 250000 worstcase 0.5 1.5056 ms/op 2.4292 ms/op 0.62
altair processInactivityUpdates - 250000 normalcase 18.468 ms/op 20.884 ms/op 0.88
altair processInactivityUpdates - 250000 worstcase 16.980 ms/op 21.510 ms/op 0.79
phase0 processRegistryUpdates - 250000 normalcase 8.0880 us/op 13.126 us/op 0.62
phase0 processRegistryUpdates - 250000 badcase_full_deposits 297.79 us/op 546.12 us/op 0.55
phase0 processRegistryUpdates - 250000 worstcase 0.5 142.90 ms/op 158.96 ms/op 0.90
altair processRewardsAndPenalties - 250000 normalcase 71.524 ms/op 70.029 ms/op 1.02
altair processRewardsAndPenalties - 250000 worstcase 68.360 ms/op 62.254 ms/op 1.10
phase0 getAttestationDeltas - 250000 normalcase 8.2803 ms/op 8.8690 ms/op 0.93
phase0 getAttestationDeltas - 250000 worstcase 9.3338 ms/op 8.2829 ms/op 1.13
phase0 processSlashings - 250000 worstcase 2.5223 ms/op 2.4391 ms/op 1.03
altair processSyncCommitteeUpdates - 250000 174.00 ms/op 159.36 ms/op 1.09
BeaconState.hashTreeRoot - No change 425.00 ns/op 424.00 ns/op 1.00
BeaconState.hashTreeRoot - 1 full validator 141.38 us/op 153.59 us/op 0.92
BeaconState.hashTreeRoot - 32 full validator 1.4809 ms/op 1.8222 ms/op 0.81
BeaconState.hashTreeRoot - 512 full validator 18.514 ms/op 22.362 ms/op 0.83
BeaconState.hashTreeRoot - 1 validator.effectiveBalance 181.55 us/op 216.66 us/op 0.84
BeaconState.hashTreeRoot - 32 validator.effectiveBalance 2.4212 ms/op 3.1224 ms/op 0.78
BeaconState.hashTreeRoot - 512 validator.effectiveBalance 31.783 ms/op 38.033 ms/op 0.84
BeaconState.hashTreeRoot - 1 balances 173.71 us/op 158.78 us/op 1.09
BeaconState.hashTreeRoot - 32 balances 1.2659 ms/op 1.3442 ms/op 0.94
BeaconState.hashTreeRoot - 512 balances 12.612 ms/op 16.065 ms/op 0.79
BeaconState.hashTreeRoot - 250000 balances 193.09 ms/op 261.81 ms/op 0.74
aggregationBits - 2048 els - zipIndexesInBitList 19.797 us/op 30.411 us/op 0.65
regular array get 100000 times 40.340 us/op 49.429 us/op 0.82
wrappedArray get 100000 times 49.638 us/op 47.572 us/op 1.04
arrayWithProxy get 100000 times 16.427 ms/op 19.213 ms/op 0.85
ssz.Root.equals 250.00 ns/op 278.00 ns/op 0.90
byteArrayEquals 236.00 ns/op 247.00 ns/op 0.96
shuffle list - 16384 els 7.4892 ms/op 7.3171 ms/op 1.02
shuffle list - 250000 els 110.69 ms/op 106.68 ms/op 1.04
processSlot - 1 slots 16.738 us/op 21.223 us/op 0.79
processSlot - 32 slots 3.1298 ms/op 3.8207 ms/op 0.82
getEffectiveBalanceIncrementsZeroInactive - 250000 vs - 7PWei 60.551 ms/op 58.246 ms/op 1.04
getCommitteeAssignments - req 1 vs - 250000 vc 2.9581 ms/op 2.7829 ms/op 1.06
getCommitteeAssignments - req 100 vs - 250000 vc 4.4811 ms/op 4.0574 ms/op 1.10
getCommitteeAssignments - req 1000 vs - 250000 vc 4.7566 ms/op 4.4738 ms/op 1.06
RootCache.getBlockRootAtSlot - 250000 vs - 7PWei 5.8200 ns/op 5.9800 ns/op 0.97
state getBlockRootAtSlot - 250000 vs - 7PWei 791.86 ns/op 713.89 ns/op 1.11
computeProposers - vc 250000 11.572 ms/op 10.185 ms/op 1.14
computeEpochShuffling - vc 250000 138.19 ms/op 122.74 ms/op 1.13
getNextSyncCommittee - vc 250000 189.49 ms/op 189.36 ms/op 1.00
computeSigningRoot for AttestationData 31.791 us/op 36.477 us/op 0.87
hash AttestationData serialized data then Buffer.toString(base64) 3.0238 us/op 2.7955 us/op 1.08
toHexString serialized data 1.7286 us/op 1.9669 us/op 0.88
Buffer.toString(base64) 316.45 ns/op 354.01 ns/op 0.89

by benchmarkbot/action

@nflaig nflaig added this to the v1.12.0 milestone Oct 1, 2023
/**
* Create a validator store with initial signers
*/
static async init(
Copy link
Member Author

Choose a reason for hiding this comment

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

Validator store initialization is now async, see #5856 (comment)

packages/validator/src/validator.ts Show resolved Hide resolved
@nflaig nflaig marked this pull request as ready for review October 1, 2023 18:19
@nflaig nflaig requested a review from a team as a code owner October 1, 2023 18:19
@nflaig nflaig force-pushed the nflaig/zero-downtime-doppelganger branch from e5b9887 to 79a89a2 Compare October 1, 2023 18:38
@nflaig nflaig force-pushed the nflaig/zero-downtime-doppelganger branch from 79a89a2 to d40f1cd Compare October 1, 2023 20:32
@nflaig nflaig force-pushed the nflaig/zero-downtime-doppelganger branch from b6c3016 to 0fa1682 Compare October 2, 2023 08:59
previousEpoch
);

if (attestedInPreviousEpoch) {
Copy link
Member Author

@nflaig nflaig Oct 2, 2023

Choose a reason for hiding this comment

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

There is an edge case when importing a validator via keymanager API, it is possible to also import the slashing protection interchange file. This will create an attestation record in the database and could cause doppelganger protection to be skipped if import happens within in the next epoch.

I don't see this as a huge risk because exporting the slashing protection interchange from a running client is only possible while also deleting the key from that client, there is no risk of getting slashing due to doppelganger.
It also assumes slashing protection was exported / imported within short time period, likely in an automated setup which aims to achieve no downtime when switching clients and therefore doppelganger protection would not be enabled anyways.

Considering this, I think there is no risk in the currently used approach and it is safe to skip doppelganger in any scenario if an attestation from previous epoch exists in the slashing protection db.

Copy link
Contributor

Choose a reason for hiding this comment

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

consider committing this explanation into the code

Copy link
Member Author

@nflaig nflaig Oct 12, 2023

Choose a reason for hiding this comment

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

I mostly added this here to get a second opinion on this if my reasoning is sound. But might be a good idea to add this to the issue description for better visibility instead of here.

The issue is already referenced in the code

if (attestedInPreviousEpoch) {
// It is safe to skip doppelganger detection
// https://github.com/ChainSafe/lodestar/issues/5856

Will refine the issue description a bit

@nflaig nflaig changed the title feat: zero downtime doppelganger protection feat: restart aware doppelganger protection Oct 3, 2023
@wemeetagain wemeetagain self-requested a review October 10, 2023 14:13
@@ -149,7 +149,7 @@ export class KeymanagerApi implements Api {

decryptKeystores.queue(
{keystoreStr, password},
(secretKeyBytes: Uint8Array) => {
async (secretKeyBytes: Uint8Array) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

decryptKeystores.queue does no handle promise rejections. Why not decrypt all keystores first, accumulate the result of this callbacks to the queue, then on the main function body run the code below that can throw / reject?

Copy link
Member Author

@nflaig nflaig Oct 12, 2023

Choose a reason for hiding this comment

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

decryptKeystores.queue does no handle promise rejections.

That's not an issue due to how promise chaining works. In any case sync or async this will be handled by onError handler

I was more concerned about the success case, i.e. does await decryptKeystores.completed(); properly wait for all promises to be resolved but this is the case as well. I tested both those cases manually, also existing tests should cover that.

Why not decrypt all keystores first, accumulate the result of this callbacks to the queue

Don't we lose a lot of concurrency by doing that? Decrypt keystores is CPU heavy while write keystores and add signers are pretty lightweight I/O operations, I think it is good that we run that in parallel.

Also if we assume an import of 100+ keys it potentially takes a few minutes, best to add signers to validator store asap.

previousEpoch
);

if (attestedInPreviousEpoch) {
Copy link
Contributor

Choose a reason for hiding this comment

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

consider committing this explanation into the code

packages/validator/src/validator.ts Show resolved Hide resolved
packages/validator/src/validator.ts Show resolved Hide resolved
@nflaig nflaig requested a review from dapplion October 16, 2023 14:10
Copy link
Contributor

@dapplion dapplion left a comment

Choose a reason for hiding this comment

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

Async flow looks good

@nflaig nflaig merged commit 3a6702e into unstable Oct 17, 2023
16 checks passed
@nflaig nflaig deleted the nflaig/zero-downtime-doppelganger branch October 17, 2023 08:51
@wemeetagain
Copy link
Member

🎉 This PR is included in v1.12.0 🎉

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.

Restart aware doppelganger protection
4 participants