Skip to content

Commit

Permalink
cmd, core, eth, miner, params, tests: finalize the DAO fork
Browse files Browse the repository at this point in the history
  • Loading branch information
karalabe committed Jul 14, 2016
1 parent 22914b6 commit 2b400c8
Show file tree
Hide file tree
Showing 11 changed files with 1,541 additions and 334 deletions.
6 changes: 3 additions & 3 deletions cmd/geth/dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ var daoGenesisForkBlock = big.NewInt(314)
// Tests that the DAO hard-fork number and the nodes support/opposition is correctly
// set in the database after various initialization procedures and invocations.
func TestDAODefaultMainnet(t *testing.T) {
testDAOForkBlockNewChain(t, false, "", [][2]bool{{false, false}}, params.MainNetDAOForkBlock, false)
testDAOForkBlockNewChain(t, false, "", [][2]bool{{false, false}}, params.MainNetDAOForkBlock, true)
}
func TestDAOSupportMainnet(t *testing.T) {
testDAOForkBlockNewChain(t, false, "", [][2]bool{{true, false}}, params.MainNetDAOForkBlock, true)
Expand All @@ -98,7 +98,7 @@ func TestDAOSwitchToOpposeMainnet(t *testing.T) {
testDAOForkBlockNewChain(t, false, "", [][2]bool{{true, false}, {false, true}}, params.MainNetDAOForkBlock, false)
}
func TestDAODefaultTestnet(t *testing.T) {
testDAOForkBlockNewChain(t, true, "", [][2]bool{{false, false}}, params.TestNetDAOForkBlock, false)
testDAOForkBlockNewChain(t, true, "", [][2]bool{{false, false}}, params.TestNetDAOForkBlock, true)
}
func TestDAOSupportTestnet(t *testing.T) {
testDAOForkBlockNewChain(t, true, "", [][2]bool{{true, false}}, params.TestNetDAOForkBlock, true)
Expand All @@ -116,7 +116,7 @@ func TestDAOInitOldPrivnet(t *testing.T) {
testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{}, nil, false)
}
func TestDAODefaultOldPrivnet(t *testing.T) {
testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{false, false}}, params.MainNetDAOForkBlock, false)
testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{false, false}}, params.MainNetDAOForkBlock, true)
}
func TestDAOSupportOldPrivnet(t *testing.T) {
testDAOForkBlockNewChain(t, false, daoOldGenesis, [][2]bool{{true, false}}, params.MainNetDAOForkBlock, true)
Expand Down
9 changes: 5 additions & 4 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -814,17 +814,18 @@ func MustMakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainC
// Set any missing fields due to them being unset or system upgrade
if config.HomesteadBlock == nil {
if ctx.GlobalBool(TestNetFlag.Name) {
config.HomesteadBlock = new(big.Int).Set(params.TestNetHomesteadBlock)
config.HomesteadBlock = params.TestNetHomesteadBlock
} else {
config.HomesteadBlock = new(big.Int).Set(params.MainNetHomesteadBlock)
config.HomesteadBlock = params.MainNetHomesteadBlock
}
}
if config.DAOForkBlock == nil {
if ctx.GlobalBool(TestNetFlag.Name) {
config.DAOForkBlock = new(big.Int).Set(params.TestNetDAOForkBlock)
config.DAOForkBlock = params.TestNetDAOForkBlock
} else {
config.DAOForkBlock = new(big.Int).Set(params.MainNetDAOForkBlock)
config.DAOForkBlock = params.MainNetDAOForkBlock
}
config.DAOForkSupport = true
}
// Force override any existing configs if explicitly requested
switch {
Expand Down
29 changes: 1 addition & 28 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package core

import (
"bytes"
"fmt"
"math/big"
"time"
Expand Down Expand Up @@ -249,33 +248,7 @@ func ValidateHeader(config *ChainConfig, pow pow.PoW, header *types.Header, pare
}
}
// If all checks passed, validate the extra-data field for hard forks
return ValidateHeaderExtraData(config, header)
}

// ValidateHeaderExtraData validates the extra-data field of a block header to
// ensure it conforms to hard-fork rules.
func ValidateHeaderExtraData(config *ChainConfig, header *types.Header) error {
// DAO hard-fork extension to the header validity: a) if the node is no-fork,
// do not accept blocks in the [fork, fork+10) range with the fork specific
// extra-data set; b) if the node is pro-fork, require blocks in the specific
// range to have the unique extra-data set.
if daoBlock := config.DAOForkBlock; daoBlock != nil {
// Check whether the block is among the fork extra-override range
limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
if daoBlock.Cmp(header.Number) <= 0 && header.Number.Cmp(limit) < 0 {
// Depending whether we support or oppose the fork, verrift the extra-data contents
if config.DAOForkSupport {
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) != 0 {
return ValidationError("DAO pro-fork bad block extra-data: 0x%x", header.Extra)
}
} else {
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) == 0 {
return ValidationError("DAO no-fork bad block extra-data: 0x%x", header.Extra)
}
}
}
}
return nil
return ValidateDAOHeaderExtraData(config, header)
}

// CalcDifficulty is the difficulty adjustment algorithm. It returns
Expand Down
74 changes: 74 additions & 0 deletions core/dao.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package core

import (
"bytes"
"math/big"

"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)

// ValidateDAOHeaderExtraData validates the extra-data field of a block header to
// ensure it conforms to DAO hard-fork rules.
//
// DAO hard-fork extension to the header validity:
// a) if the node is no-fork, do not accept blocks in the [fork, fork+10) range
// with the fork specific extra-data set
// b) if the node is pro-fork, require blocks in the specific range to have the
// unique extra-data set.
func ValidateDAOHeaderExtraData(config *ChainConfig, header *types.Header) error {
// Short circuit validation if the node doesn't care about the DAO fork
if config.DAOForkBlock == nil {
return nil
}
// Make sure the block is within the fork's modified extra-data range
limit := new(big.Int).Add(config.DAOForkBlock, params.DAOForkExtraRange)
if header.Number.Cmp(config.DAOForkBlock) < 0 || header.Number.Cmp(limit) >= 0 {
return nil
}
// Depending whether we support or oppose the fork, validate the extra-data contents
if config.DAOForkSupport {
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) != 0 {
return ValidationError("DAO pro-fork bad block extra-data: 0x%x", header.Extra)
}
} else {
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) == 0 {
return ValidationError("DAO no-fork bad block extra-data: 0x%x", header.Extra)
}
}
// All ok, header has the same extra-data we expect
return nil
}

// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
// rules, transferring all balances of a set of DAO accounts to a single refund
// contract.
func ApplyDAOHardFork(statedb *state.StateDB) {
// Retrieve the contract to refund balances into
refund := statedb.GetOrNewStateObject(params.DAORefundContract)

// Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList {
if account := statedb.GetStateObject(addr); account != nil {
refund.AddBalance(account.Balance())
account.SetBalance(new(big.Int))
}
}
}
17 changes: 0 additions & 17 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
)

var (
Expand Down Expand Up @@ -134,19 +133,3 @@ func AccumulateRewards(statedb *state.StateDB, header *types.Header, uncles []*t
}
statedb.AddBalance(header.Coinbase, reward)
}

// ApplyDAOHardFork modifies the state database according to the DAO hard-fork
// rules, transferring all balances of a set of DAO accounts to a single refund
// contract.
func ApplyDAOHardFork(statedb *state.StateDB) {
// Retrieve the contract to refund balances into
refund := statedb.GetOrNewStateObject(params.DAORefundContract)

// Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList {
if account := statedb.GetStateObject(addr); account != nil {
refund.AddBalance(account.Balance())
account.SetBalance(new(big.Int))
}
}
}
8 changes: 4 additions & 4 deletions eth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
// If we're seemingly on the same chain, disable the drop timer
if verifyDAO {
glog.V(logger.Info).Infof("%v: seems to be on the same side of the DAO fork", p)
glog.V(logger.Debug).Infof("%v: seems to be on the same side of the DAO fork", p)
p.forkDrop.Stop()
p.forkDrop = nil
return nil
Expand All @@ -529,11 +529,11 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
p.forkDrop = nil

// Validate the header and either drop the peer or continue
if err := core.ValidateHeaderExtraData(pm.chainconfig, headers[0]); err != nil {
glog.V(logger.Info).Infof("%v: verified to be on the other side of the DAO fork, dropping", p)
if err := core.ValidateDAOHeaderExtraData(pm.chainconfig, headers[0]); err != nil {
glog.V(logger.Debug).Infof("%v: verified to be on the other side of the DAO fork, dropping", p)
return err
}
glog.V(logger.Info).Infof("%v: verified to be on the same side of the DAO fork", p)
glog.V(logger.Debug).Infof("%v: verified to be on the same side of the DAO fork", p)
}
// Irrelevant of the fork checks, send the header to the fetcher just in case
headers = pm.fetcher.FilterHeaders(headers, time.Now())
Expand Down
2 changes: 1 addition & 1 deletion miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ func (self *worker) commitNewWork() {
if daoBlock := self.config.DAOForkBlock; daoBlock != nil {
// Check whether the block is among the fork extra-override range
limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
if daoBlock.Cmp(header.Number) <= 0 && header.Number.Cmp(limit) < 0 {
if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 {
// Depending whether we support or oppose the fork, override differently
if self.config.DAOForkSupport {
header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
Expand Down
Loading

0 comments on commit 2b400c8

Please sign in to comment.