forked from ethereum-optimism/cannon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
challenge_simple.sh
executable file
·145 lines (110 loc) · 5.04 KB
/
challenge_simple.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
#!/usr/bin/env bash
# The following variables can be overridden as environment variables:
# * BLOCK (block whose transition will be challenged)
# * WRONG_BLOCK (block number used by challenger)
# * SKIP_NODE (skip forking a node, useful if you've already forked a node)
#
# Example usage:
# SKIP_NODE=1 BLOCK=13284469 WRONG_BLOCK=13284491 ./demo/challenge_simple.sh
# --- DOC ----------------------------------------------------------------------
# In this example, the challenger will challenge the transition from a block
# (`BLOCK`), but pretends that chain state before another block (`WRONG_BLOCK`)
# is the state before the challenged block. Consequently, the challenger will
# disagree with the defender on every single step of the challenge game, and the
# single step to execute will be the very first MIPS instruction executed. The
# reason is that the initial MIPS state Merkle root is stored on-chain, and
# immediately modified to reflect the fact that the input hash for the block is
# written at address 0x3000000.
#
# (The input hash is automatically validated against the blockhash, so note that
# in this demo the challenger has to provide the correct (`BLOCK`) input hash to
# the `initiateChallenge` function of `Challenge.sol`, but will execute as
# though the input hash was the one derived from `WRONG_BLOCK`.)
#
# Because the challenger uses the wrong inputs, it will assert a post-state
# (Merkle root) for the first MIPS instruction that has the wrong input hash at
# 0x3000000. Hence, the challenge will fail.
# --- SCRIPT SETUP -------------------------------------------------------------
shout() {
echo ""
echo "----------------------------------------"
echo "$1"
echo "----------------------------------------"
echo ""
}
# Exit if any command fails.
set -e
exit_trap() {
# Print an error if the last command failed
# (in which case the script is exiting because of set -e).
[[ $? == 0 ]] && return
echo "----------------------------------------"
echo "EARLY EXIT: SCRIPT FAILED"
echo "----------------------------------------"
# Kill (send SIGTERM) to the whole process group, also killing
# any background processes.
# I think the trap command resets SIGTERM before resending it to the whole
# group. (cf. https://stackoverflow.com/a/2173421)
trap - SIGTERM && kill -- -$$
}
trap "exit_trap" SIGINT SIGTERM EXIT
# --- BOOT MAINNET FORK --------------------------------------------------------
if [[ ! "$SKIP_NODE" ]]; then
NODE_LOG="challenge_simple_node.log"
shout "BOOTING MAINNET FORK NODE IN BACKGROUND (LOG: $NODE_LOG)"
# get directory containing this file
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
# run a hardhat mainnet fork node
"$SCRIPT_DIR/forked_node.sh" > "$NODE_LOG" 2>&1 &
# give the node some time to boot up
sleep 10
fi
# --- CHALLENGE SETUP ----------------------------------------------------------
# hardhat network to use
NETWORK=${NETWORK:-l1}
export NETWORK
# challenge ID, read by respond.js and assert.js
export ID=0
# block whose transition will be challenged
# this variable is read by challenge.js, respond.js and assert.js
BLOCK=${BLOCK:-13284469}
export BLOCK
# block whose pre-state is used by the challenger instead of the challenged block's pre-state
WRONG_BLOCK=${WRONG_BLOCK:-13284491}
# clear data from previous runs
mkdir -p /tmp/cannon /tmp/cannon_fault && rm -rf /tmp/cannon/* /tmp/cannon_fault/*
# stored in /tmp/cannon/golden.json
shout "GENERATING INITIAL MEMORY STATE CHECKPOINT"
mipsevm/mipsevm --outputGolden
shout "DEPLOYING CONTRACTS"
npx hardhat run scripts/deploy.js --network $NETWORK
# challenger will use same initial memory checkpoint and deployed contracts
cp /tmp/cannon/{golden,deployed}.json /tmp/cannon_fault/
shout "FETCHING PREIMAGES FOR REAL BLOCK"
minigeth/go-ethereum $BLOCK
shout "COMPUTING REAL MIPS FINAL MEMORY CHECKPOINT"
mipsevm/mipsevm --blockNumber=$BLOCK
shout "FETCHING PREIMAGES FOR WRONG BLOCK"
BASEDIR=/tmp/cannon_fault minigeth/go-ethereum $WRONG_BLOCK
shout "COMPUTING FAKE MIPS FINAL MEMORY CHECKPOINT"
BASEDIR=/tmp/cannon_fault mipsevm/mipsevm --blockNumber=$WRONG_BLOCK
# pretend the wrong block's input, checkpoints and preimages are the right block's
ln -s /tmp/cannon_fault/0_$WRONG_BLOCK /tmp/cannon_fault/0_$BLOCK
# --- BINARY SEARCH ------------------------------------------------------------
shout "STARTING CHALLENGE"
BASEDIR=/tmp/cannon_fault npx hardhat run scripts/challenge.js --network $NETWORK
shout "BINARY SEARCH"
for i in {1..23}; do
echo ""
echo "--- STEP $i / 23 ---"
echo ""
BASEDIR=/tmp/cannon_fault CHALLENGER=1 npx hardhat run scripts/respond.js --network $NETWORK
npx hardhat run scripts/respond.js --network $NETWORK
done
# --- SINGLE STEP EXECUTION ----------------------------------------------------
shout "ASSERTING AS CHALLENGER (should fail)"
set +e # this should fail!
BASEDIR=/tmp/cannon_fault CHALLENGER=1 npx hardhat run scripts/assert.js --network $NETWORK
set -e
shout "ASSERTING AS DEFENDER (should pass)"
npx hardhat run scripts/assert.js --network $NETWORK