mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 14:21:14 +00:00
consensus: double-sign risk reduction (ADR-51) (#5147)
Implementation spec of Double Signing Risk Reduction [ADR-51](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-051-double-signing-risk-reduction.md) by B-Harvest - Add `DoubleSignCheckHeight` config variable to ConsensusConfig for "How many blocks looks back to check existence of the node's consensus votes when before joining consensus" - Add `consensus.double_sign_check_height` to `config.toml` and `tendermint node` as flag for set `DoubleSignCheckHeight` - Set default `consensus.double_sign_check_height` to `0` ( it could be adjustable in this PR, disable when 0 ) Refs - [ADR-51](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-051-double-signing-risk-reduction.md) - [https://github.com/tendermint/tendermint/issues/4059](https://github.com/tendermint/tendermint/issues/4059) - [https://github.com/tendermint/tendermint/pull/4262](https://github.com/tendermint/tendermint/pull/4262)
This commit is contained in:
@@ -19,3 +19,4 @@ and run the following tests in docker containers:
|
||||
- send a tx on each node and ensure the state root is updated on all of them
|
||||
- crash and restart nodes one at a time and ensure they can sync back up (via fastsync)
|
||||
- crash and restart all nodes at once and ensure they can sync back up
|
||||
- restart each nodes with double_sign_check_height and ensure panic if the same consensus key was used to sign in double_sign_check_height blocks
|
||||
|
||||
64
test/p2p/dsrr/check_peer.sh
Normal file
64
test/p2p/dsrr/check_peer.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
#! /bin/bash
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
IPV=$1
|
||||
ID=$2
|
||||
ASSERT_CASE=$3
|
||||
ASSERT_NODE_UP=1
|
||||
ASSERT_NODE_DOWN=0
|
||||
MAX_TRY=10
|
||||
|
||||
|
||||
###########################################
|
||||
#
|
||||
# Wait for peer to catchup to other peers
|
||||
#
|
||||
###########################################
|
||||
|
||||
addr=$(test/p2p/address.sh $IPV $ID 26657)
|
||||
peerID=$(( $(($ID % 4)) + 1 )) # 1->2 ... 3->4 ... 4->1
|
||||
peer_addr=$(test/p2p/address.sh $IPV $peerID 26657)
|
||||
|
||||
# get another peer's height
|
||||
h1=`curl -s $peer_addr/status | jq .result.sync_info.latest_block_height | jq fromjson`
|
||||
|
||||
# get another peer's state
|
||||
root1=`curl -s $peer_addr/status | jq .result.sync_info.latest_app_hash`
|
||||
|
||||
echo "Other peer is on height $h1 with state $root1"
|
||||
echo "Waiting for peer $ID to catch up"
|
||||
|
||||
# wait for it to sync to past its previous height
|
||||
set +e
|
||||
set +o pipefail
|
||||
h2="0"
|
||||
COUNT=0
|
||||
while [[ "$h2" -lt "$(($h1+1))" ]]; do
|
||||
sleep 1
|
||||
h2=`curl -s $addr/status --connect-timeout 1 | jq .result.sync_info.latest_block_height | jq fromjson`
|
||||
COUNT=$((COUNT+1))
|
||||
echo "... $h2, try $COUNT"
|
||||
if [ "$COUNT" -ge "$MAX_TRY" ]; then
|
||||
if [ $ASSERT_CASE -eq $ASSERT_NODE_DOWN ]; then
|
||||
echo "double sign risk reduction operates normally as expected"
|
||||
fi
|
||||
if [ $ASSERT_CASE -eq $ASSERT_NODE_UP ]; then
|
||||
echo "double sign risk reduction fail"
|
||||
exit 1
|
||||
fi
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
if [ $ASSERT_CASE -eq $ASSERT_NODE_UP ]; then
|
||||
# check the app hash
|
||||
root2=`curl -s $addr/status | jq .result.sync_info.latest_app_hash`
|
||||
|
||||
if [[ "$root1" != "$root2" ]]; then
|
||||
echo "App hash after restart does not match. Got $root2; expected $root1"
|
||||
exit 1
|
||||
fi
|
||||
echo "... double sign risk reduction test passed"
|
||||
fi
|
||||
13
test/p2p/dsrr/test.sh
Normal file
13
test/p2p/dsrr/test.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#! /bin/bash
|
||||
set -eu
|
||||
|
||||
DOCKER_IMAGE=$1
|
||||
NETWORK_NAME=$2
|
||||
IPV=$3
|
||||
N=$4
|
||||
PROXY_APP=$5
|
||||
|
||||
# run it on each of them
|
||||
for i in `seq 1 $N`; do
|
||||
bash test/p2p/dsrr/test_peer.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $i $N $PROXY_APP
|
||||
done
|
||||
65
test/p2p/dsrr/test_peer.sh
Normal file
65
test/p2p/dsrr/test_peer.sh
Normal file
@@ -0,0 +1,65 @@
|
||||
#! /bin/bash
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
DOCKER_IMAGE=$1
|
||||
NETWORK_NAME=$2
|
||||
IPV=$3
|
||||
ID=$4
|
||||
N=$5
|
||||
PROXY_APP=$6
|
||||
ASSERT_NODE_UP=1
|
||||
ASSERT_NODE_DOWN=0
|
||||
|
||||
###########################s####################################
|
||||
# this runs on each peer:
|
||||
# kill peer
|
||||
# bring it back online with double_sign_check_height 10
|
||||
# wait node is not run by double sign risk reduction
|
||||
#
|
||||
# kill peer
|
||||
# bring it back online with double_sign_check_height 1
|
||||
# pass double sign risk reduction, wait for it to sync and check the app hash
|
||||
#
|
||||
# kill peer
|
||||
# bring it back online with double_sign_check_height 0
|
||||
# wait for it to sync and check the app hash
|
||||
###############################################################
|
||||
|
||||
echo "Testing double sign risk reduction on node $ID"
|
||||
|
||||
# kill peer
|
||||
set +e
|
||||
docker rm -vf local_testnet_$ID
|
||||
set -e
|
||||
PERSISTENT_PEERS="$(test/p2p/address.sh $IPV 1 26656 $DOCKER_IMAGE)"
|
||||
for j in `seq 2 $N`; do
|
||||
PERSISTENT_PEERS="$PERSISTENT_PEERS,$(test/p2p/address.sh $IPV $j 26656 $DOCKER_IMAGE)"
|
||||
done
|
||||
|
||||
# bring it back online with double_sign_check_height 10
|
||||
# wait node is not run by double sign risk reduction
|
||||
DSCH=10
|
||||
bash test/p2p/peer.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $ID $PROXY_APP "--p2p.persistent_peers $PERSISTENT_PEERS --p2p.pex --rpc.unsafe --consensus.double_sign_check_height $DSCH"
|
||||
bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $IPV fs_$ID "test/p2p/dsrr/check_peer.sh $IPV $ID $ASSERT_NODE_DOWN"
|
||||
|
||||
|
||||
docker stop local_testnet_$ID
|
||||
docker rm local_testnet_$ID
|
||||
# bring it back online with double_sign_check_height 1
|
||||
# pass double sign risk reduction, wait for it to sync and check the app hash
|
||||
DSCH=1
|
||||
bash test/p2p/peer.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $ID $PROXY_APP "--p2p.persistent_peers $PERSISTENT_PEERS --p2p.pex --rpc.unsafe --consensus.double_sign_check_height $DSCH"
|
||||
bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $IPV fs_$ID "test/p2p/dsrr/check_peer.sh $IPV $ID $ASSERT_NODE_UP"
|
||||
|
||||
docker stop local_testnet_$ID
|
||||
docker rm local_testnet_$ID
|
||||
DSCH=0
|
||||
# bring it back online with double_sign_check_height 0
|
||||
# double sign risk reduction is not activated, wait for it to sync and check the app hash
|
||||
bash test/p2p/peer.sh $DOCKER_IMAGE $NETWORK_NAME $IPV $ID $PROXY_APP "--p2p.persistent_peers $PERSISTENT_PEERS --p2p.pex --rpc.unsafe --consensus.double_sign_check_height $DSCH"
|
||||
bash test/p2p/client.sh $DOCKER_IMAGE $NETWORK_NAME $IPV fs_$ID "test/p2p/dsrr/check_peer.sh $IPV $ID $ASSERT_NODE_UP"
|
||||
|
||||
echo ""
|
||||
echo "PASS"
|
||||
echo ""
|
||||
@@ -35,6 +35,9 @@ bash test/p2p/client.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" ab "test/p2p/atom
|
||||
# for each node, kill it and readd via fast sync
|
||||
bash test/p2p/fast_sync/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" "$PROXY_APP"
|
||||
|
||||
# test double sign risk reduction for each node
|
||||
bash test/p2p/dsrr/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" "$PROXY_APP"
|
||||
|
||||
# test killing all peers 3 times
|
||||
bash test/p2p/kill_all/test.sh "$DOCKER_IMAGE" "$NETWORK_NAME" "$IPV" "$N" 3
|
||||
|
||||
|
||||
Reference in New Issue
Block a user