-
Notifications
You must be signed in to change notification settings - Fork 2
/
unfork-merge.sh
executable file
·205 lines (187 loc) · 5.44 KB
/
unfork-merge.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/bin/bash
# unfork.sh
#
# A little script to (attempt) to unfork (get off) a forked blockchain
#
# Copyright (c) 2019 Mark Brooker <[email protected]>
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/MIT
#
# Usage:
# unfork.sh [fix]
#
# If run without the "fix" option the script will simply produce a
# sitrep comparing this node's position with the explorer.
# The fix option will cause it to attempt to resolve a fork if one is
# detected.
#
# Method:
# - check if we actually forked, if so:
# - use binary chop to find the fork height
# - invalidateblock the fork point
# - shutdown the daemon
# - remove peers.dat
# - start the daemon
#
# Requirements:
# - an explorer which provides getblockcount and getblockhash functions
# (an Iquidus explorer is ideal, Cryptoid is also known to work)
#
# Donations:
# If you find it useful, feel free to sling some crypto my way!
# - BTC: 36TBpGyBaNm4UpETLuvs7RHNfoiAuz7mxD
# - LTC: MVMU2YikpetyFB4mUKt9rSzhUQhw87hjgV
# - CRW: CRWFdMDPdi5uuzBZRi9kBi8pfDCbP6ZE2kYG
# - BLOCK: BVbpLYh8kCq8vXxLAa726azu3EZfXFkjRh
#
# set colors
RED='\033[1;31m'
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
PURPLE='\033[1;35m'
CYAN='\033[1;36m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color
# Customise these to suit your environment
COIN="merge"
DATADIR="$HOME/.merge"
CONFIG="$DATADIR/merge.conf"
#
EXPLORER="https://explorer.projectmerge.org/api/"
#
PREFIX="/usr/local/bin" # path to executables
#
DAEMON="${COIN}d"
DAEMONCMD="${PREFIX}/${DAEMON} -conf=${CONFIG} -datadir=${DATADIR} "
CLIENT="${COIN}-cli"
CLIENTCMD="${PREFIX}/${CLIENT} -conf=${CONFIG} -datadir=${DATADIR}"
# We do this more than once and it's a friction point so make it a function
get_explorer_hash() {
CHAINHASH=`curl --silent "${EXPLORER}getblockhash?index=$*" 2>/dev/null`
echo ${CHAINHASH}
}
# Tell the user what's happening (useful if run from cron with redirection)
echo "${0##*/} checking ${COIN} blockchain at $(date)"
# Start off by looking for running daemon.
PID=$(pidof ${DAEMON})
# If it's not running we're done.
if [[ $? -eq 1 ]]; then
echo -e "${RED}${DAEMON} not running. Please start it and try again${NC}"
exit 4
fi
#echo "${DAEMON} PID is ${PID}"
echo
# Find our current blockheight.
OURHIGH=`${CLIENTCMD} getblockcount`
echo "Our latest block is ${OURHIGH}"
OURHASH=`${CLIENTCMD} getblockhash ${OURHIGH}`
#echo "with blockhash ${OURHASH}"
#echo
# Find the current explorer blockheight.
CHAINHIGH=`curl --silent ${EXPLORER}getblockcount 2>/dev/null`
echo "Latest block at the explorer is ${CHAINHIGH}"
CHAINHASH=$(get_explorer_hash ${CHAINHIGH})
#echo "with blockhash ${CHAINHASH}"
echo
BLOCKDIFF=$((${OURHIGH} - ${CHAINHIGH}))
if [[ ${BLOCKDIFF} -lt 0 ]]; then
ABSDIFF=$(( -${BLOCKDIFF} ))
else
ABSDIFF=${BLOCKDIFF}
fi
if [[ ${ABSDIFF} -ge 3 ]]; then
COLOUR=${RED}
elif [[ ${ABSDIFF} -ge 1 ]]; then
COLOUR=${YELLOW}
else
COLOUR=${NC}
fi
# Give the user a sitrep.
if [[ ${OURHIGH} -gt ${CHAINHIGH} ]]; then
echo -e "${COLOUR}We are ${ABSDIFF} blocks ahead of the explorer${NC}"
OURHASH=`${CLIENTCMD} getblockhash ${CHAINHIGH}`
if [[ ${OURHASH} == ${CHAINHASH} ]]; then
echo "but on the same chain. Nothing to do here!"
exit 0
fi
HIGH=${CHAINHIGH}
elif [[ ${OURHIGH} -eq ${CHAINHIGH} ]]; then
echo "We are level with the explorer"
if [[ ${OURHASH} == ${CHAINHASH} ]]; then
echo "and on the same chain. Nothing to do here!"
exit 0
fi
HIGH=${OURHIGH}
else
echo -e "${COLOUR}We are ${ABSDIFF} blocks behind the explorer${NC}"
CHAINHASH=$(get_explorer_hash ${OURHIGH})
if [[ ${OURHASH} == ${CHAINHASH} ]]; then
echo "but on the same chain. Nothing to do here!"
exit 0
fi
HIGH=${OURHIGH}
fi
# We have work to do. Binary chop to find the fork height.
echo
echo "Searching for the fork point..."
LAST=0
LOW=1
while true; do
BLOCK=$(($((${LOW}+${HIGH}))/2))
#echo "Low=${LOW} High=${HIGH} Checking ${BLOCK}"
OURHASH=`${CLIENTCMD} getblockhash ${BLOCK}`
#echo "Our hash is ${OURHASH}"
CHAINHASH=$(get_explorer_hash ${BLOCK})
#echo "Explorer hash is ${CHAINHASH}"
if [[ ${OURHASH} == ${CHAINHASH} ]]; then
# go right
LOW=${BLOCK}
else
# go left
HIGH=${BLOCK}
fi
if [[ ${LOW} == ${HIGH} ]]; then # found it
break
elif [[ ${BLOCK} == ${LAST} ]]; then # nudge
LOW=${HIGH}
fi
LAST=${BLOCK}
done
echo "We forked at ${BLOCK}"
echo "Our hash is ${OURHASH}"
echo "Explorer has ${CHAINHASH}"
echo
if [[ $1 != "fix" ]]; then
echo -e "${YELLOW}Run with unfork.sh fix to actually fix the fork${NC}"
exit
fi
# Invalidate the block.
echo "Invalidating the fork point"
${CLIENTCMD} invalidateblock ${OURHASH}
# Shutdown.
echo "Shutting down the daemon"
${CLIENTCMD} stop
# Allow up to 10 minutes for it to shutdown gracefully.
for ((i=0; i<60; i++)); do
echo "...waiting..."
sleep 10
if [[ $(ps -p ${PID} | wc -l) -lt 2 ]]; then
break
fi
done
# If it still hasn't shutdown, terminate with extreme prejudice.
if [[ ${i} -eq 60 ]]; then
echo -e "${RED}Shutdown still incomplete, killing the daemon.${NC}"
kill -9 ${PID}
sleep 10
rm -f ${DATADIR}/${DAEMON}.pid ${DATADIR}/.lock
fi
# Remove peers.dat and restart it.
rm -f ${DATADIR}/peers.dat
echo "Re-starting the daemon"
${DAEMONCMD} -daemon
echo "Use the command"
echo " ${CLIENT} getblockcount"
echo "to monitor the chain and make sure the daemon is resyncing."
echo -e "${YELLOW}You have at least $((${CHAINHIGH} - ${BLOCK} + 1)) blocks to catch up.${NC}"