mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-02 16:21:42 +00:00
Doppelganger detection (#2230)
## Issue Addressed Resolves #2069 ## Proposed Changes - Adds a `--doppelganger-detection` flag - Adds a `lighthouse/seen_validators` endpoint, which will make it so the lighthouse VC is not interopable with other client beacon nodes if the `--doppelganger-detection` flag is used, but hopefully this will become standardized. Relevant Eth2 API repo issue: https://github.com/ethereum/eth2.0-APIs/issues/64 - If the `--doppelganger-detection` flag is used, the VC will wait until the beacon node is synced, and then wait an additional 2 epochs. The reason for this is to make sure the beacon node is able to subscribe to the subnets our validators should be attesting on. I think an alternative would be to have the beacon node subscribe to all subnets for 2+ epochs on startup by default. ## Additional Info I'd like to add tests and would appreciate feedback. TODO: handle validators started via the API, potentially make this default behavior Co-authored-by: realbigsean <seananderson33@gmail.com> Co-authored-by: Michael Sproul <michael@sigmaprime.io> Co-authored-by: Paul Hauner <paul@paulhauner.com>
This commit is contained in:
141
scripts/tests/doppelganger_protection.sh
Executable file
141
scripts/tests/doppelganger_protection.sh
Executable file
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Requires `lighthouse`, ``lcli`, `ganache-cli`, `curl`, `jq`
|
||||
|
||||
BEHAVIOR=$1
|
||||
|
||||
if [[ "$BEHAVIOR" != "success" ]] && [[ "$BEHAVIOR" != "failure" ]]; then
|
||||
echo "Usage: doppelganger_protection.sh [success|failure]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source ./vars.env
|
||||
|
||||
../local_testnet/clean.sh
|
||||
|
||||
echo "Starting ganache"
|
||||
|
||||
../local_testnet/ganache_test_node.sh &> /dev/null &
|
||||
GANACHE_PID=$!
|
||||
|
||||
# Wait for ganache to start
|
||||
sleep 5
|
||||
|
||||
echo "Setting up local testnet"
|
||||
|
||||
../local_testnet/setup.sh
|
||||
|
||||
# Duplicate this directory so slashing protection doesn't keep us from re-using validator keys
|
||||
cp -R $HOME/.lighthouse/local-testnet/node_1 $HOME/.lighthouse/local-testnet/node_1_doppelganger
|
||||
|
||||
echo "Starting bootnode"
|
||||
|
||||
../local_testnet/bootnode.sh &> /dev/null &
|
||||
BOOT_PID=$!
|
||||
|
||||
# wait for the bootnode to start
|
||||
sleep 10
|
||||
|
||||
echo "Starting local beacon nodes"
|
||||
|
||||
../local_testnet/beacon_node.sh $HOME/.lighthouse/local-testnet/node_1 9000 8000 &> /dev/null &
|
||||
BEACON_PID=$!
|
||||
../local_testnet/beacon_node.sh $HOME/.lighthouse/local-testnet/node_2 9100 8100 &> /dev/null &
|
||||
BEACON_PID2=$!
|
||||
../local_testnet/beacon_node.sh $HOME/.lighthouse/local-testnet/node_3 9200 8200 &> /dev/null &
|
||||
BEACON_PID3=$!
|
||||
|
||||
echo "Starting local validator clients"
|
||||
|
||||
../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_1 http://localhost:8000 &> /dev/null &
|
||||
VALIDATOR_1_PID=$!
|
||||
../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_2 http://localhost:8100 &> /dev/null &
|
||||
VALIDATOR_2_PID=$!
|
||||
../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_3 http://localhost:8200 &> /dev/null &
|
||||
VALIDATOR_3_PID=$!
|
||||
|
||||
echo "Waiting an epoch before starting the next validator client"
|
||||
sleep $(( $SECONDS_PER_SLOT * 32 ))
|
||||
|
||||
if [[ "$BEHAVIOR" == "failure" ]]; then
|
||||
|
||||
echo "Starting the doppelganger validator client"
|
||||
|
||||
# Use same keys as keys from VC1, but connect to BN2
|
||||
# This process should not last longer than 2 epochs
|
||||
timeout $(( $SECONDS_PER_SLOT * 32 * 2 )) ../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_1_doppelganger http://localhost:8100
|
||||
DOPPELGANGER_EXIT=$?
|
||||
|
||||
echo "Shutting down"
|
||||
|
||||
# Cleanup
|
||||
kill $BOOT_PID $BEACON_PID $BEACON_PID2 $BEACON_PID3 $GANACHE_PID $VALIDATOR_1_PID $VALIDATOR_2_PID $VALIDATOR_3_PID
|
||||
|
||||
echo "Done"
|
||||
|
||||
if [[ $DOPPELGANGER_EXIT -eq 124 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$BEHAVIOR" == "success" ]]; then
|
||||
|
||||
echo "Starting the last validator client"
|
||||
|
||||
../local_testnet/validator_client.sh $HOME/.lighthouse/local-testnet/node_4 http://localhost:8100 &
|
||||
VALIDATOR_4_PID=$!
|
||||
DOPPELGANGER_FAILURE=0
|
||||
|
||||
# Sleep three epochs, then make sure all validators were active in epoch 2. Use
|
||||
# `is_previous_epoch_target_attester` from epoch 3 for a complete view of epoch 2 inclusion.
|
||||
#
|
||||
# See: https://lighthouse-book.sigmaprime.io/validator-inclusion.html
|
||||
echo "Waiting three epochs..."
|
||||
sleep $(( $SECONDS_PER_SLOT * 32 * 3 ))
|
||||
|
||||
PREVIOUS_DIR=$(pwd)
|
||||
cd $HOME/.lighthouse/local-testnet/node_4/validators
|
||||
for val in 0x*; do
|
||||
[[ -e $val ]] || continue
|
||||
curl -s localhost:8100/lighthouse/validator_inclusion/3/$val | jq | grep -q '"is_previous_epoch_target_attester": false'
|
||||
IS_ATTESTER=$?
|
||||
if [[ $IS_ATTESTER -eq 0 ]]; then
|
||||
echo "$val did not attest in epoch 2."
|
||||
else
|
||||
echo "ERROR! $val did attest in epoch 2."
|
||||
DOPPELGANGER_FAILURE=1
|
||||
fi
|
||||
done
|
||||
|
||||
# Sleep two epochs, then make sure all validators were active in epoch 4. Use
|
||||
# `is_previous_epoch_target_attester` from epoch 5 for a complete view of epoch 4 inclusion.
|
||||
#
|
||||
# See: https://lighthouse-book.sigmaprime.io/validator-inclusion.html
|
||||
echo "Waiting two more epochs..."
|
||||
sleep $(( $SECONDS_PER_SLOT * 32 * 2 ))
|
||||
for val in 0x*; do
|
||||
[[ -e $val ]] || continue
|
||||
curl -s localhost:8100/lighthouse/validator_inclusion/5/$val | jq | grep -q '"is_previous_epoch_target_attester": true'
|
||||
IS_ATTESTER=$?
|
||||
if [[ $IS_ATTESTER -eq 0 ]]; then
|
||||
echo "$val attested in epoch 4."
|
||||
else
|
||||
echo "ERROR! $val did not attest in epoch 4."
|
||||
DOPPELGANGER_FAILURE=1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Shutting down"
|
||||
|
||||
# Cleanup
|
||||
cd $PREVIOUS_DIR
|
||||
kill $BOOT_PID $BEACON_PID $BEACON_PID2 $BEACON_PID3 $GANACHE_PID $VALIDATOR_1_PID $VALIDATOR_2_PID $VALIDATOR_3_PID $VALIDATOR_4_PID
|
||||
|
||||
echo "Done"
|
||||
|
||||
if [[ $DOPPELGANGER_FAILURE -eq 1 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
39
scripts/tests/vars.env
Normal file
39
scripts/tests/vars.env
Normal file
@@ -0,0 +1,39 @@
|
||||
# Base directories for the validator keys and secrets
|
||||
DATADIR=~/.lighthouse/local-testnet
|
||||
|
||||
# Directory for the eth2 config
|
||||
TESTNET_DIR=$DATADIR/testnet
|
||||
|
||||
# Mnemonic for the ganache test network
|
||||
ETH1_NETWORK_MNEMONIC="vast thought differ pull jewel broom cook wrist tribe word before omit"
|
||||
|
||||
# Hardcoded deposit contract based on ETH1_NETWORK_MNEMONIC
|
||||
DEPOSIT_CONTRACT_ADDRESS=8c594691c0e592ffa21f153a16ae41db5befcaaa
|
||||
|
||||
GENESIS_FORK_VERSION=0x42424242
|
||||
|
||||
VALIDATOR_COUNT=80
|
||||
GENESIS_VALIDATOR_COUNT=80
|
||||
|
||||
# Number of validator client instances that you intend to run
|
||||
NODE_COUNT=4
|
||||
|
||||
GENESIS_DELAY=0
|
||||
|
||||
# Port for P2P communication with bootnode
|
||||
BOOTNODE_PORT=4242
|
||||
|
||||
# Network ID and Chain ID of local eth1 test network
|
||||
NETWORK_ID=4242
|
||||
|
||||
# Hard fork configuration
|
||||
ALTAIR_FORK_EPOCH=18446744073709551615
|
||||
|
||||
# Seconds per Eth2 slot
|
||||
SECONDS_PER_SLOT=3
|
||||
|
||||
# Seconds per Eth1 block
|
||||
SECONDS_PER_ETH1_BLOCK=1
|
||||
|
||||
# Enable doppelganger detection
|
||||
VC_ARGS=" --enable-doppelganger-protection "
|
||||
Reference in New Issue
Block a user