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:
dongsam
2020-08-27 06:57:36 +02:00
committed by GitHub
parent fbdf8b098e
commit e30b125725
15 changed files with 214 additions and 13 deletions

View File

@@ -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

View 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
View 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

View 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 ""

View File

@@ -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