Skip to content

Commit 3dd46bc

Browse files
committed
[release/1.4.10] cmd, core, eth, params: implement flags to control dao fork blocks
(cherry picked from commit 6060e09)
1 parent e44d50f commit 3dd46bc

File tree

7 files changed

+354
-46
lines changed

7 files changed

+354
-46
lines changed

cmd/geth/dao_test.go

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
// Copyright 2016 The go-ethereum Authors
2+
// This file is part of go-ethereum.
3+
//
4+
// go-ethereum is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// go-ethereum is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package main
18+
19+
import (
20+
"io/ioutil"
21+
"math/big"
22+
"os"
23+
"path/filepath"
24+
"testing"
25+
26+
"github.com/ethereum/go-ethereum/common"
27+
"github.com/ethereum/go-ethereum/core"
28+
"github.com/ethereum/go-ethereum/ethdb"
29+
"github.com/ethereum/go-ethereum/params"
30+
)
31+
32+
var daoNoForkGenesis = `{
33+
"alloc" : {},
34+
"coinbase" : "0x0000000000000000000000000000000000000000",
35+
"difficulty" : "0x20000",
36+
"extraData" : "",
37+
"gasLimit" : "0x2fefd8",
38+
"nonce" : "0x0000000000000042",
39+
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
40+
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
41+
"timestamp" : "0x00"
42+
}`
43+
var daoNoForkGenesisHash = common.HexToHash("5e1fc79cb4ffa4739177b5408045cd5d51c6cf766133f23f7cd72ee1f8d790e0")
44+
45+
var daoProForkGenesis = `{
46+
"alloc" : {},
47+
"coinbase" : "0x0000000000000000000000000000000000000000",
48+
"difficulty" : "0x20000",
49+
"extraData" : "",
50+
"gasLimit" : "0x2fefd8",
51+
"nonce" : "0x0000000000000043",
52+
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
53+
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
54+
"timestamp" : "0x00",
55+
"config" : {
56+
"daoForkBlock": 314
57+
}
58+
}`
59+
var daoProForkGenesisHash = common.HexToHash("c80f3c1c3d81ae6d8ea59edf35d3e4b723e4c8684ec71fdb6d4715e3f8add237")
60+
var daoProForkBlock = big.NewInt(314)
61+
62+
// Tests that creating a new node to with or without the DAO fork flag will correctly
63+
// set the genesis block but with DAO support explicitly set or unset in the chain
64+
// config in the database.
65+
func TestDAOSupportMainnet(t *testing.T) {
66+
testDAOForkBlockNewChain(t, false, "", true, params.MainNetDAOForkBlock)
67+
}
68+
func TestDAOSupportTestnet(t *testing.T) {
69+
testDAOForkBlockNewChain(t, true, "", true, params.TestNetDAOForkBlock)
70+
}
71+
func TestDAOSupportPrivnet(t *testing.T) {
72+
testDAOForkBlockNewChain(t, false, daoProForkGenesis, false, daoProForkBlock)
73+
}
74+
func TestDAONoSupportMainnet(t *testing.T) {
75+
testDAOForkBlockNewChain(t, false, "", false, nil)
76+
}
77+
func TestDAONoSupportTestnet(t *testing.T) {
78+
testDAOForkBlockNewChain(t, true, "", false, nil)
79+
}
80+
func TestDAONoSupportPrivnet(t *testing.T) {
81+
testDAOForkBlockNewChain(t, false, daoNoForkGenesis, false, nil)
82+
}
83+
84+
func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, fork bool, expect *big.Int) {
85+
// Create a temporary data directory to use and inspect later
86+
datadir := tmpdir(t)
87+
defer os.RemoveAll(datadir)
88+
89+
// Start a Geth instance with the requested flags set and immediately terminate
90+
if genesis != "" {
91+
json := filepath.Join(datadir, "genesis.json")
92+
if err := ioutil.WriteFile(json, []byte(genesis), 0600); err != nil {
93+
t.Fatalf("failed to write genesis file: %v", err)
94+
}
95+
runGeth(t, "--datadir", datadir, "init", json).cmd.Wait()
96+
}
97+
execDAOGeth(t, datadir, testnet, fork, false)
98+
99+
// Retrieve the DAO config flag from the database
100+
path := filepath.Join(datadir, "chaindata")
101+
if testnet {
102+
path = filepath.Join(datadir, "testnet", "chaindata")
103+
}
104+
db, err := ethdb.NewLDBDatabase(path, 0, 0)
105+
if err != nil {
106+
t.Fatalf("failed to open test database: %v", err)
107+
}
108+
defer db.Close()
109+
110+
genesisHash := common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
111+
if testnet {
112+
genesisHash = common.HexToHash("0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303")
113+
} else if genesis == daoNoForkGenesis {
114+
genesisHash = daoNoForkGenesisHash
115+
} else if genesis == daoProForkGenesis {
116+
genesisHash = daoProForkGenesisHash
117+
}
118+
config, err := core.GetChainConfig(db, genesisHash)
119+
if err != nil {
120+
t.Fatalf("failed to retrieve chain config: %v", err)
121+
}
122+
// Validate the DAO hard-fork block number against the expected value
123+
if config.DAOForkBlock == nil {
124+
if expect != nil {
125+
t.Fatalf("dao hard-fork block mismatch: have nil, want %v", expect)
126+
}
127+
} else if config.DAOForkBlock.Cmp(expect) != 0 {
128+
t.Fatalf("dao hard-fork block mismatch: have %v, want %v", config.DAOForkBlock, expect)
129+
}
130+
}
131+
132+
// Tests that starting up an already existing node with various DAO fork override
133+
// flags correctly changes the chain configs in the database.
134+
func TestDAODefaultMainnet(t *testing.T) {
135+
testDAOForkBlockOldChain(t, false, "", false, false, false, false, nil)
136+
}
137+
func TestDAOStartSupportMainnet(t *testing.T) {
138+
testDAOForkBlockOldChain(t, false, "", false, true, false, false, params.MainNetDAOForkBlock)
139+
}
140+
func TestDAOContinueExplicitSupportMainnet(t *testing.T) {
141+
testDAOForkBlockOldChain(t, false, "", true, true, false, false, params.MainNetDAOForkBlock)
142+
}
143+
func TestDAOContinueImplicitSupportMainnet(t *testing.T) {
144+
testDAOForkBlockOldChain(t, false, "", true, false, false, false, params.MainNetDAOForkBlock)
145+
}
146+
func TestDAOSwitchSupportMainnet(t *testing.T) {
147+
testDAOForkBlockOldChain(t, false, "", false, true, true, false, params.MainNetDAOForkBlock)
148+
}
149+
func TestDAOStartOpposeMainnet(t *testing.T) {
150+
testDAOForkBlockOldChain(t, false, "", false, false, false, true, nil)
151+
}
152+
func TestDAOContinueExplicitOpposeMainnet(t *testing.T) {
153+
testDAOForkBlockOldChain(t, false, "", false, false, true, true, nil)
154+
}
155+
func TestDAOContinueImplicitOpposeMainnet(t *testing.T) {
156+
testDAOForkBlockOldChain(t, false, "", false, false, true, false, nil)
157+
}
158+
func TestDAOSwitchOpposeMainnet(t *testing.T) {
159+
testDAOForkBlockOldChain(t, false, "", true, false, false, true, nil)
160+
}
161+
func TestDAODefaultTestnet(t *testing.T) {
162+
testDAOForkBlockOldChain(t, true, "", false, false, false, false, nil)
163+
}
164+
func TestDAOStartSupportTestnet(t *testing.T) {
165+
testDAOForkBlockOldChain(t, true, "", false, true, false, false, params.TestNetDAOForkBlock)
166+
}
167+
func TestDAOContinueExplicitSupportTestnet(t *testing.T) {
168+
testDAOForkBlockOldChain(t, true, "", true, true, false, false, params.TestNetDAOForkBlock)
169+
}
170+
func TestDAOContinueImplicitSupportTestnet(t *testing.T) {
171+
testDAOForkBlockOldChain(t, true, "", true, false, false, false, params.TestNetDAOForkBlock)
172+
}
173+
func TestDAOSwitchSupportTestnet(t *testing.T) {
174+
testDAOForkBlockOldChain(t, true, "", false, true, true, false, params.TestNetDAOForkBlock)
175+
}
176+
func TestDAOStartOpposeTestnet(t *testing.T) {
177+
testDAOForkBlockOldChain(t, true, "", false, false, false, true, nil)
178+
}
179+
func TestDAOContinueExplicitOpposeTestnet(t *testing.T) {
180+
testDAOForkBlockOldChain(t, true, "", false, false, true, true, nil)
181+
}
182+
func TestDAOContinueImplicitOpposeTestnet(t *testing.T) {
183+
testDAOForkBlockOldChain(t, true, "", false, false, true, false, nil)
184+
}
185+
func TestDAOSwitchOpposeTestnet(t *testing.T) {
186+
testDAOForkBlockOldChain(t, true, "", true, false, false, true, nil)
187+
}
188+
func TestDAODefaultPrivnet(t *testing.T) {
189+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, false, false, false, false, nil)
190+
}
191+
func TestDAOStartSupportConPrivnet(t *testing.T) {
192+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, false, true, false, false, params.MainNetDAOForkBlock)
193+
}
194+
func TestDAOContinueExplicitSupportConPrivnet(t *testing.T) {
195+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, true, true, false, false, params.MainNetDAOForkBlock)
196+
}
197+
func TestDAOContinueImplicitSupportConPrivnet(t *testing.T) {
198+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, true, false, false, false, params.MainNetDAOForkBlock)
199+
}
200+
func TestDAOSwitchSupportConPrivnet(t *testing.T) {
201+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, false, true, true, false, params.MainNetDAOForkBlock)
202+
}
203+
func TestDAOStartOpposeConPrivnet(t *testing.T) {
204+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, false, false, false, true, nil)
205+
}
206+
func TestDAOContinueExplicitOpposeConPrivnet(t *testing.T) {
207+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, false, false, true, true, nil)
208+
}
209+
func TestDAOContinueImplicitOpposeConPrivnet(t *testing.T) {
210+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, false, false, true, false, nil)
211+
}
212+
func TestDAOSwitchOpposeConPrivnet(t *testing.T) {
213+
testDAOForkBlockOldChain(t, false, daoNoForkGenesis, true, false, false, true, nil)
214+
}
215+
func TestDAODefaultProPrivnet(t *testing.T) {
216+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, false, false, false, false, daoProForkBlock)
217+
}
218+
func TestDAOStartSupportProPrivnet(t *testing.T) {
219+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, false, true, false, false, daoProForkBlock)
220+
}
221+
func TestDAOContinueExplicitSupportProPrivnet(t *testing.T) {
222+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, true, true, false, false, daoProForkBlock)
223+
}
224+
func TestDAOContinueImplicitSupportProPrivnet(t *testing.T) {
225+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, true, false, false, false, daoProForkBlock)
226+
}
227+
func TestDAOSwitchSupportProPrivnet(t *testing.T) {
228+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, false, true, true, false, params.MainNetDAOForkBlock)
229+
}
230+
func TestDAOStartOpposeProPrivnet(t *testing.T) {
231+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, false, false, false, true, nil)
232+
}
233+
func TestDAOContinueExplicitOpposeProPrivnet(t *testing.T) {
234+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, false, false, true, true, nil)
235+
}
236+
func TestDAOContinueImplicitOpposeProPrivnet(t *testing.T) {
237+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, false, false, true, false, nil)
238+
}
239+
func TestDAOSwitchOpposeProPrivnet(t *testing.T) {
240+
testDAOForkBlockOldChain(t, false, daoProForkGenesis, true, false, false, true, nil)
241+
}
242+
243+
func testDAOForkBlockOldChain(t *testing.T, testnet bool, genesis string, oldSupport, newSupport, oldOppose, newOppose bool, expect *big.Int) {
244+
// Create a temporary data directory to use and inspect later
245+
datadir := tmpdir(t)
246+
defer os.RemoveAll(datadir)
247+
248+
// Cycle two Geth instances, possibly changing fork support in between
249+
if genesis != "" {
250+
json := filepath.Join(datadir, "genesis.json")
251+
if err := ioutil.WriteFile(json, []byte(genesis), 0600); err != nil {
252+
t.Fatalf("failed to write genesis file: %v", err)
253+
}
254+
runGeth(t, "--datadir", datadir, "init", json).cmd.Wait()
255+
}
256+
execDAOGeth(t, datadir, testnet, oldSupport, oldOppose)
257+
execDAOGeth(t, datadir, testnet, newSupport, newOppose)
258+
259+
// Retrieve the DAO config flag from the database
260+
path := filepath.Join(datadir, "chaindata")
261+
if testnet {
262+
path = filepath.Join(datadir, "testnet", "chaindata")
263+
}
264+
db, err := ethdb.NewLDBDatabase(path, 0, 0)
265+
if err != nil {
266+
t.Fatalf("failed to open test database: %v", err)
267+
}
268+
defer db.Close()
269+
270+
genesisHash := common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
271+
if testnet {
272+
genesisHash = common.HexToHash("0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303")
273+
} else if genesis == daoNoForkGenesis {
274+
genesisHash = daoNoForkGenesisHash
275+
} else if genesis == daoProForkGenesis {
276+
genesisHash = daoProForkGenesisHash
277+
}
278+
config, err := core.GetChainConfig(db, genesisHash)
279+
if err != nil {
280+
t.Fatalf("failed to retrieve chain config: %v", err)
281+
}
282+
// Validate the DAO hard-fork block number against the expected value
283+
if config.DAOForkBlock == nil {
284+
if expect != nil {
285+
t.Fatalf("dao hard-fork block mismatch: have nil, want %v", expect)
286+
}
287+
} else if config.DAOForkBlock.Cmp(expect) != 0 {
288+
t.Fatalf("dao hard-fork block mismatch: have %v, want %v", config.DAOForkBlock, expect)
289+
}
290+
}
291+
292+
// execDAOGeth starts a Geth instance with some DAO forks set and terminates.
293+
func execDAOGeth(t *testing.T, datadir string, testnet bool, supportFork bool, opposeFork bool) {
294+
args := []string{"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir}
295+
if testnet {
296+
args = append(args, "--testnet")
297+
}
298+
if supportFork {
299+
args = append(args, "--support-dao-fork")
300+
}
301+
if opposeFork {
302+
args = append(args, "--oppose-dao-fork")
303+
}
304+
geth := runGeth(t, append(args, []string{"--exec", "2+2", "console"}...)...)
305+
geth.cmd.Wait()
306+
}

cmd/geth/main.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ participating.
149149
utils.IdentityFlag,
150150
utils.UnlockedAccountFlag,
151151
utils.PasswordFileFlag,
152-
utils.GenesisFileFlag,
153152
utils.BootnodesFlag,
154153
utils.DataDirFlag,
155154
utils.KeyStoreDirFlag,
@@ -164,6 +163,8 @@ participating.
164163
utils.MaxPendingPeersFlag,
165164
utils.EtherbaseFlag,
166165
utils.GasPriceFlag,
166+
utils.SupportDAOFork,
167+
utils.OpposeDAOFork,
167168
utils.MinerThreadsFlag,
168169
utils.MiningEnabledFlag,
169170
utils.MiningGPUFlag,
@@ -224,12 +225,6 @@ participating.
224225
eth.EnableBadBlockReporting = true
225226

226227
utils.SetupNetwork(ctx)
227-
228-
// Deprecation warning.
229-
if ctx.GlobalIsSet(utils.GenesisFileFlag.Name) {
230-
common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'")
231-
}
232-
233228
return nil
234229
}
235230

cmd/geth/usage.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ var AppHelpFlagGroups = []flagGroup{
6868
utils.OlympicFlag,
6969
utils.TestNetFlag,
7070
utils.DevModeFlag,
71-
utils.GenesisFileFlag,
7271
utils.IdentityFlag,
7372
utils.FastSyncFlag,
7473
utils.LightKDFFlag,

0 commit comments

Comments
 (0)