Merge pull request #2752 from karalabe/revert-soft-fork

Revert faulty DAO soft-fork
This commit is contained in:
Péter Szilágyi authored and GitHub committed 2016-06-29 12:17:18 +03:00
commit fd4e161497
14 files changed
+9 -473

No files matched your search

-1
View File
@@ -220,7 +220,6 @@ type ruleSet struct{}
func (ruleSet) IsHomestead(*big.Int) bool { return true }
func (self *VMEnv) MarkCodeHash(common.Hash) {}
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Db() vm.Database { return self.state }
-1
View File
@@ -169,7 +169,6 @@ participating.
utils.MiningGPUFlag,
utils.AutoDAGFlag,
utils.TargetGasLimitFlag,
utils.DAOSoftForkFlag,
utils.NATFlag,
utils.NatspecEnabledFlag,
utils.NoDiscoverFlag,
-1
View File
@@ -128,7 +128,6 @@ var AppHelpFlagGroups = []flagGroup{
utils.TargetGasLimitFlag,
utils.GasPriceFlag,
utils.ExtraDataFlag,
utils.DAOSoftForkFlag,
},
},
{
-7
View File
@@ -181,10 +181,6 @@ var (
Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
Value: params.GenesisGasLimit.String(),
}
DAOSoftForkFlag = cli.BoolFlag{
Name: "dao-soft-fork",
Usage: "Vote for the DAO soft-fork, temporarilly decreasing the gas limits",
}
AutoDAGFlag = cli.BoolFlag{
Name: "autodag",
Usage: "Enable automatic DAG pregeneration",
@@ -681,9 +677,6 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
// Configure the Ethereum service
accman := MakeAccountManager(ctx)
// Handle some miner strategies arrising from the DAO fiasco
core.DAOSoftFork = ctx.GlobalBool(DAOSoftForkFlag.Name)
// initialise new random number generator
rand := rand.New(rand.NewSource(time.Now().UnixNano()))
// get enabled jit flag
-5
View File
@@ -371,10 +371,5 @@ func CalcGasLimit(parent *types.Block) *big.Int {
gl.Add(parent.GasLimit(), decay)
gl.Set(common.BigMin(gl, params.TargetGasLimit))
}
// Temporary special case: if DAO rupture is requested, cap the gas limit
if DAOSoftFork && parent.NumberU64() <= ruptureBlock && gl.Cmp(ruptureTarget) > 0 {
gl.Sub(parent.GasLimit(), decay)
gl.Set(common.BigMax(gl, ruptureTarget))
}
return gl
}
-358
View File
@@ -1,358 +0,0 @@
// 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 (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
)
// Some weird dependency for deploying a DAO instance.
var creatorDeployCode = common.FromHex("606060405261339c806100126000396000f3606060405260e060020a6000350463e2faf0448114601a575b005b6097600435602435604435606435600084308585853360606132e8806100b48339018087600160a060020a0316815260200186600160a060020a0316815260200185815260200184815260200183815260200182600160a060020a031681526020019650505050505050604051809103906000f095945050505050565b60408051600160a060020a03929092168252519081900360200190f3606060405260405160c0806132e88339610120604052905160805160a051925160e0516101005193949293828282600f829055601083905560118054610100830261010060a860020a031990911617905560405130906001906101bc806103378339600160a060020a039390931692019182526020820152604080519182900301906000f060128054600160a060020a031916919091179055505060038054600160a060020a03199081168917909155600e80549091168717905550600c84905560405130906000906101bc806104f38339018083600160a060020a0316815260200182815260200192505050604051809103906000f060405160078054600160a060020a0319169290921790915530906000906101bc806106af8339018083600160a060020a0316815260200182815260200192505050604051809103906000f060088054600160a060020a031916919091179055600754600160a060020a0316600014156101c357610002565b50505030600160a060020a03908116600090815260046020526040808220805460ff19908116600190811790925560035490941683529120805490921617905550505050505050612a7d8061086b6000396000f35b600854600160a060020a0316600014156101dc57610002565b4260025560056001908155600080548282558290801582901161016e57600e0281600e02836000526020600020918201910161016e919061023e565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b80821115610333578054600160a060020a03191681556000600182810182905560028381018054848255909281161561010002600019011604601f81901061030557505b506000600383018190556004838101805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220610218929091028101905b808211156103335760008082556001820181815560028301919091556003919091018054600160a060020a03191690556102d0565b601f01602090049060005260206000209081019061028291905b80821115610333576000815560010161031f565b50905660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b92915050566060604052361561020e5760e060020a6000350463013cf08b811461022c578063095ea7b3146103ea5780630c3b7b961461045e5780630e70820314610467578063149acf9a1461047957806318160ddd1461048b5780631f2dc5ef1461049457806321b5b8dd146104b4578063234693d3146104c6578063237e9492146Line truncated
// EVM deploy bytecode of the DAO to simulate blocking.
var daoDeployCode = common.FromHex("606060405260405160c0806132c88339610120604052905160805160a051925160e0516101005193949293828282600f829055601083905560118054610100830261010060a860020a031990911617905560405130906001906101bc8061033e8339600160a060020a03909316908301526101408201526040519081900361016001906000f060128054600160a060020a031916919091179055505060038054600160a060020a03199081168917909155600e80549091168717905550600c84905560405130906000906101bc806104fa8339018083600160a060020a0316815260200182815260200192505050604051809103906000f0600760006101000a815481600160a060020a03021916908302179055503060006040516101bc806106b68339018083600160a060020a0316815260200182815260200192505050604051809103906000f060088054600160a060020a031916919091179055600754600160a060020a03166000141561017557610002565b600854600160a060020a03166000141561018e57610002565b426002556005600190815560008054828255829080158290116101ca57600e0281600e0283600052602060002091820191016101ca9190610245565b50505030600160a060020a03908116600090815260046020526040808220805460ff19908116600190811790925560035490941683529120805490921617905550505050505050612a56806108726000396000f35b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561033a578054600160a060020a03191681556000600182810182905560028381018054848255909281161561010002600019011604601f81901061030c57505b506000600383018190556004838101805461ffff19169055600584018290556006840182905560078401805460ff19169055600884018054838255908352602090922061021f929091028101905b8082111561033a5760008082556001820181815560028301919091556003919091018054600160a060020a03191690556102d7565b601f01602090049060005260206000209081019061028991905b8082111561033a5760008155600101610326565b50905660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b92915050566060604052361561020e5760e060020a6000350463013cf08b8114610247578063095ea7b3146102d05780630c3b7b96146103455780630e7082031461034e578063149acf9a1461036057806318160ddd146103725780631f2dc5ef1461037b57806321b5b8dd1461039b578063237e9492146103ad57806323b872dd1461040e5780632632bf2014610441578063341458081461047257806339d1f9081461047b5780634b6753bc146104935780634df6d6cc1461049c5780634e10c3ee146104b7578063590e1ae3146104ca578063612e45a3146104db578063643f7cdd1461057a578063674ed066146105925780636837ff1e1461059b57806370a08231146105e5578063749f98891461060b57806378524b2e1461062457806381f03fcb1461067e57806382661dc41461069657806382bf6464146106b75780638Line truncated
// Proxy contract to whitelist interaction with:
//
// contract Proxy {
// address _dao;
//
// function Proxy(address dao) {
// _dao = dao;
// }
// function() {
// if (msg.value > 0) {
// _dao.call.value(msg.value)();
// } else {
// _dao.call(bytes4(sha3("refund()")));
// }
// }
// }
var proxyDeployCode = common.FromHex("606060405260405160208060dd83395060806040525160008054600160a060020a031916821790555060a98060346000396000f360606040523615600a575b60486000341115604a576000805473ffffffffffffffffffffffffffffffffffffffff1690349060609081818185876185025a03f1925050505060a7565b005b600080547f590e1ae300000000000000000000000000000000000000000000000000000000606090815273ffffffffffffffffffffffffffffffffffffffff9091169163590e1ae3916064919060048183876161da5a03f1505050505b56")
// Tests that unannimous votes are handled correctly (i.e. the simple case).
func TestDAOForkUnanimousFail(t *testing.T) { testDAOUnanimousFork(t, false) }
func TestDAOForkUnanimousPass(t *testing.T) { testDAOUnanimousFork(t, true) }
func testDAOUnanimousFork(t *testing.T, pass bool) {
// Reduce the test size to avoid wasting too much time
defer func(old uint64) { ruptureBlock = old }(ruptureBlock)
ruptureBlock = 128
defer func(old int) { ruptureCacheLimit = old }(ruptureCacheLimit)
ruptureCacheLimit = 256
// Depending on the tested outcome, set a high or a low gas limit
defer func(old *big.Int) { params.GenesisGasLimit = old }(params.GenesisGasLimit)
defer func(old *big.Int) { params.TargetGasLimit = old }(params.TargetGasLimit)
if pass {
params.GenesisGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(-10))
params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(-10))
} else {
params.GenesisGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(10))
params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(10))
}
// Create a test chain with a DAO instance deployed and attempt to transact with it
var (
slockit, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
black, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
white, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
slockitAddr = crypto.PubkeyToAddress(slockit.PublicKey)
blackAddr = crypto.PubkeyToAddress(black.PublicKey)
whiteAddr = crypto.PubkeyToAddress(white.PublicKey)
creatorAddr common.Address
daoAddr common.Address
blackProxy common.Address
whiteProxy common.Address
db, _ = ethdb.NewMemDatabase()
)
genesis := WriteGenesisBlockForTesting(db,
GenesisAccount{slockitAddr, big.NewInt(1000000)},
GenesisAccount{blackAddr, big.NewInt(1000000)},
GenesisAccount{whiteAddr, big.NewInt(1000000)},
)
length := int(ruptureBlock) + 2*ruptureCacheLimit
chain, _ := GenerateChain(genesis, db, length, func(i int, gen *BlockGen) {
switch i {
case 0:
// Deploy the DAO creator in the first block
tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(1), params.GenesisGasLimit, new(big.Int), creatorDeployCode).SignECDSA(slockit)
gen.AddTx(tx)
creatorAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
case 1:
// Deploy the DAO in the second block
var args []byte
args = append(args, common.LeftPadBytes(slockitAddr.Bytes(), 32)...) // curator
args = append(args, common.LeftPadBytes(creatorAddr.Bytes(), 32)...) // daoCreator
args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // proposalDeposit
args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // minTokensToCreate
args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // closingTime
args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // privateCreation
tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(0), params.GenesisGasLimit, new(big.Int), append(daoDeployCode, args...)).SignECDSA(slockit)
gen.AddTx(tx)
daoAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
case 2:
// Deploy the black and white hat proxy contracts
tx, _ := types.NewContractCreation(gen.TxNonce(blackAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(black)
gen.AddTx(tx)
blackProxy = crypto.CreateAddress(blackAddr, tx.Nonce())
tx, _ = types.NewContractCreation(gen.TxNonce(whiteAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(white)
gen.AddTx(tx)
whiteProxy = crypto.CreateAddress(whiteAddr, tx.Nonce())
ruptureWhitelist[whiteProxy] = true
case 3:
// Fund the DAO with some funds, but not enough for successful creation
tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(white)
gen.AddTx(tx)
tx, _ = types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(black)
gen.AddTx(tx)
case length - 2:
// DAO creation failed by this time and forks are in effect; try retrieving whitelisted funds
tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(white)
gen.AddTx(tx)
case length - 1:
// DAO creation failed by this time and forks are in effect; try retrieving blacklisted funds
tx, _ := types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(black)
gen.AddTx(tx)
}
})
defer delete(ruptureWhitelist, whiteProxy) // This can't be done in the aboge generator sadly
// Import the chain. This runs all block validation rules.
bc, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, new(event.TypeMux))
n, err := bc.InsertChain(chain)
// The chain should either succeed (no votes), or fail on the black address
if !pass {
if err != nil {
t.Errorf("block %d rejected on non forked chain: %v", n, err)
}
} else {
if n != length-1 || err != blockedCodeHashErr {
t.Errorf("failure mismatch: have %d:%v, want %d:%v", n, err, length-1, blockedCodeHashErr)
}
}
// Verify account balances to make sure transactions executd properly, not just the test is bugged
state, _ := bc.State()
if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
}
if !pass {
if state.GetBalance(blackProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund (fork refused)
t.Errorf("black proxy balance mismatch: have %v, want 3", state.GetBalance(blackProxy))
}
if state.GetBalance(daoAddr).Cmp(big.NewInt(0)) != 0 { // all refunded (fork refused)
t.Errorf("dao balance mismatch: have %v, want 0", state.GetBalance(daoAddr))
}
} else {
if state.GetBalance(blackProxy).Cmp(big.NewInt(1)) != 0 { // 1 init (refund refused due to fork)
t.Errorf("black proxy balance mismatch: have %v, want 1", state.GetBalance(blackProxy))
}
if state.GetBalance(daoAddr).Cmp(big.NewInt(2)) != 0 { // 2 from black (refund refused due to fork)
t.Errorf("dao balance mismatch: have %v, want 2", state.GetBalance(daoAddr))
}
}
}
// Tests the unique corner case where miners don't cleanly decide on the outcome
// of the vote, rather
func TestDAOForkRaceyResolution(t *testing.T) {
// Reduce the test size to avoid wasting too much time
defer func(old uint64) { ruptureBlock = old }(ruptureBlock)
ruptureBlock = 128
defer func(old int) { ruptureCacheLimit = old }(ruptureCacheLimit)
ruptureCacheLimit = 256
// Set up the parameters of the test chain
var (
slockit, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
black, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
white, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
slockitAddr = crypto.PubkeyToAddress(slockit.PublicKey)
blackAddr = crypto.PubkeyToAddress(black.PublicKey)
whiteAddr = crypto.PubkeyToAddress(white.PublicKey)
creatorAddr common.Address
daoAddr common.Address
blackProxy common.Address
whiteProxy common.Address
db, _ = ethdb.NewMemDatabase()
)
defer func(old *big.Int) { params.GenesisGasLimit = old }(params.GenesisGasLimit)
params.GenesisGasLimit = ruptureThreshold
genesis := WriteGenesisBlockForTesting(db,
GenesisAccount{slockitAddr, big.NewInt(1000000)},
GenesisAccount{blackAddr, big.NewInt(1000000)},
GenesisAccount{whiteAddr, big.NewInt(1000000)},
)
// Generate a chain where the outcome for the fork proposal is pass
defer func(old *big.Int) { params.TargetGasLimit = old }(params.TargetGasLimit)
params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(-10))
length := int(ruptureBlock) + 2*ruptureCacheLimit
chainPass, _ := GenerateChain(genesis, db, length, func(i int, gen *BlockGen) {
switch i {
case 0:
// Deploy the DAO creator in the first block
tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(1), big.NewInt(3999980), new(big.Int), creatorDeployCode).SignECDSA(slockit)
gen.AddTx(tx)
creatorAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
case 1:
// Deploy the DAO in the second block
var args []byte
args = append(args, common.LeftPadBytes(slockitAddr.Bytes(), 32)...) // curator
args = append(args, common.LeftPadBytes(creatorAddr.Bytes(), 32)...) // daoCreator
args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // proposalDeposit
args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // minTokensToCreate
args = append(args, common.LeftPadBytes([]byte{100}, 32)...) // closingTime
args = append(args, common.LeftPadBytes([]byte{0}, 32)...) // privateCreation
tx, _ := types.NewContractCreation(gen.TxNonce(slockitAddr), big.NewInt(0), big.NewInt(3999980), new(big.Int), append(daoDeployCode, args...)).SignECDSA(slockit)
gen.AddTx(tx)
daoAddr = crypto.CreateAddress(slockitAddr, tx.Nonce())
case 2:
// Deploy the black and white hat proxy contracts
tx, _ := types.NewContractCreation(gen.TxNonce(blackAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(black)
gen.AddTx(tx)
blackProxy = crypto.CreateAddress(blackAddr, tx.Nonce())
tx, _ = types.NewContractCreation(gen.TxNonce(whiteAddr), big.NewInt(1), big.NewInt(1000000), new(big.Int), append(proxyDeployCode, common.LeftPadBytes(daoAddr.Bytes(), 32)...)).SignECDSA(white)
gen.AddTx(tx)
whiteProxy = crypto.CreateAddress(whiteAddr, tx.Nonce())
ruptureWhitelist[whiteProxy] = true
case 3:
// Fund the DAO with some funds, but not enough for successful creation
tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(white)
gen.AddTx(tx)
tx, _ = types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(2), big.NewInt(1000000), nil, nil).SignECDSA(black)
gen.AddTx(tx)
case length - 2:
// DAO creation failed by this time and forks are in effect; try retrieving whitelisted funds
tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(white)
gen.AddTx(tx)
case length - 1:
// DAO creation failed by this time and forks are in effect; try retrieving blacklisted funds
tx, _ := types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(black)
gen.AddTx(tx)
}
})
// Generate a chain to work around the last bad block above
chainPassCont, _ := GenerateChain(chainPass[len(chainPass)-2], db, 3, func(i int, gen *BlockGen) {})
// Generate a fork of the chain where the outcome of the fork proposal is fail
params.TargetGasLimit = new(big.Int).Add(ruptureThreshold, big.NewInt(10))
chainFail, _ := GenerateChain(chainPass[4], db, length-4, func(i int, gen *BlockGen) { // Start fro block #4 to reuse previous creation code
switch i {
case length - 4 - 2:
// DAO creation failed by this time and forks are in effect; try retrieving whitelisted funds
tx, _ := types.NewTransaction(gen.TxNonce(whiteAddr), whiteProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(white)
gen.AddTx(tx)
case length - 4 - 1:
// DAO creation failed by this time and forks are in effect; try retrieving blacklisted funds
tx, _ := types.NewTransaction(gen.TxNonce(blackAddr), blackProxy, big.NewInt(0), big.NewInt(1000000), nil, nil).SignECDSA(black)
gen.AddTx(tx)
}
})
defer delete(ruptureWhitelist, whiteProxy) // This can't be done in the aboge generator sadly
// Import the chain where the vote passed
bc, _ := NewBlockChain(db, MakeChainConfig(), FakePow{}, new(event.TypeMux))
if n, err := bc.InsertChain(chainPass); n != length-1 || err != blockedCodeHashErr {
t.Fatalf("forked chain error mismatch: have %v/%v, want %v/%v", n, err, length-1, blockedCodeHashErr)
}
state, _ := bc.State()
if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
}
if state.GetBalance(blackProxy).Cmp(big.NewInt(1)) != 0 { // 1 init (no refund on the passing chain)
t.Errorf("black proxy balance mismatch: have %v, want 1", state.GetBalance(blackProxy))
}
if state.GetBalance(daoAddr).Cmp(big.NewInt(2)) != 0 { // 2 from black (refund refused due to fork)
t.Errorf("dao balance mismatch: have %v, want 2", state.GetBalance(daoAddr))
}
// Import the chain where the vote failed (longer than the passing with 1 block (dropped from the passing))
if _, err := bc.InsertChain(chainFail); err != nil {
t.Fatalf("failed to import non-forked chain: %v", err)
}
state, _ = bc.State()
if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
}
if state.GetBalance(blackProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund (fork refused)
t.Errorf("black proxy balance mismatch: have %v, want 3", state.GetBalance(blackProxy))
}
if state.GetBalance(daoAddr).Cmp(big.NewInt(0)) != 0 { // all refunded (fork refused)
t.Errorf("dao balance mismatch: have %v, want 0", state.GetBalance(daoAddr))
}
// Try to import a bad block on theforked chain to make sure no cache screwes up
if _, err := bc.InsertChain(chainPass[len(chainPass)-2:]); err != blockedCodeHashErr {
t.Fatalf("forked chain error mismatch: have %v, want %v", err, blockedCodeHashErr)
}
// The balances must still be that of the failed chain
state, _ = bc.State()
if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
}
if state.GetBalance(blackProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund (fork refused)
t.Errorf("black proxy balance mismatch: have %v, want 3", state.GetBalance(blackProxy))
}
if state.GetBalance(daoAddr).Cmp(big.NewInt(0)) != 0 { // all refunded (fork refused)
t.Errorf("dao balance mismatch: have %v, want 0", state.GetBalance(daoAddr))
}
// Overrule the passing chain with fresh blocks
if _, err := bc.InsertChain(chainPassCont); err != nil {
t.Fatalf("failed to import forked chain continuation: %v", err)
}
// Balances must be switched over to the forked version
state, _ = bc.State()
if state.GetBalance(whiteProxy).Cmp(big.NewInt(3)) != 0 { // 1 init + 2 refund
t.Errorf("white proxy balance mismatch: have %v, want 3", state.GetBalance(whiteProxy))
}
if state.GetBalance(blackProxy).Cmp(big.NewInt(1)) != 0 { // 1 init (no refund on the passing chain)
t.Errorf("black proxy balance mismatch: have %v, want 1", state.GetBalance(blackProxy))
}
if state.GetBalance(daoAddr).Cmp(big.NewInt(2)) != 0 { // 2 from black (refund refused due to fork)
t.Errorf("dao balance mismatch: have %v, want 2", state.GetBalance(daoAddr))
}
}
+2 -8
View File
@@ -84,10 +84,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
address = &addr
createAccount = true
}
// Mark all contracts doing outbound value transfers to allow DAO filtering.
if value.Cmp(common.Big0) > 0 {
env.MarkCodeHash(env.Db().GetCodeHash(caller.Address()))
}
snapshotPreTransfer := env.MakeSnapshot()
var (
from = env.Db().GetAccount(caller.Address())
@@ -146,10 +143,7 @@ func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toA
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, vm.DepthError
}
// Mark all contracts doing outbound value transfers to allow DAO filtering.
if value.Cmp(common.Big0) > 0 {
env.MarkCodeHash(env.Db().GetCodeHash(caller.Address()))
}
snapshot := env.MakeSnapshot()
var to vm.Account
-8
View File
@@ -161,14 +161,6 @@ func (self *StateDB) GetCode(addr common.Address) []byte {
return nil
}
func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
return common.BytesToHash(stateObject.codeHash)
}
return common.Hash{}
}
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
stateObject := self.GetStateObject(a)
if stateObject != nil {
+3 -67
View File
@@ -17,10 +17,8 @@
package core
import (
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -30,25 +28,8 @@ import (
)
var (
big8 = big.NewInt(8)
big32 = big.NewInt(32)
blockedCodeHashErr = errors.New("core: blocked code-hash found during execution")
// DAO attack chain rupture mechanism
DAOSoftFork bool // Flag whether to vote for DAO rupture
ruptureBlock = uint64(1800000) // Block number of the voted soft fork
ruptureTarget = big.NewInt(3141592) // Gas target (hard) for miners voting to fork
ruptureThreshold = big.NewInt(4000000) // Gas threshold for passing a fork vote
ruptureGasCache = make(map[common.Hash]*big.Int) // Amount of gas in the point of rupture
ruptureCodeHashes = map[common.Hash]struct{}{
common.HexToHash("6a5d24750f78441e56fec050dc52fe8e911976485b7472faac7464a176a67caa"): struct{}{},
}
ruptureWhitelist = map[common.Address]bool{
common.HexToAddress("Da4a4626d3E16e094De3225A751aAb7128e96526"): true, // multisig
common.HexToAddress("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334"): true, // attack contract
}
ruptureCacheLimit = 30000 // 1 epoch, 0.5 per possible fork
big8 = big.NewInt(8)
big32 = big.NewInt(32)
)
// StateProcessor is a basic Processor, which takes care of transitioning
@@ -105,56 +86,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// ApplyTransactions returns the generated receipts and vm logs during the
// execution of the state transition phase.
func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
env := NewEnv(statedb, config, bc, tx, header, cfg)
_, gas, err := ApplyMessage(env, tx, gp)
_, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), tx, gp)
if err != nil {
return nil, nil, nil, err
}
// Check whether the DAO needs to be blocked or not
if bc != nil { // Test chain maker uses nil to construct the potential chain
blockRuptureCodes := false
if number := header.Number.Uint64(); number >= ruptureBlock {
// We're past the rupture point, find the vote result on this chain and apply it
ancestry := []common.Hash{header.Hash(), header.ParentHash}
for _, ok := ruptureGasCache[ancestry[len(ancestry)-1]]; !ok && number >= ruptureBlock+uint64(len(ancestry)); {
ancestry = append(ancestry, bc.GetHeaderByHash(ancestry[len(ancestry)-1]).ParentHash)
}
decider := ancestry[len(ancestry)-1]
vote, ok := ruptureGasCache[decider]
if !ok {
// We've reached the rupture point, retrieve the vote
vote = bc.GetHeaderByHash(decider).GasLimit
ruptureGasCache[decider] = vote
}
// Cache the vote result for all ancestors and check the DAO
for _, hash := range ancestry {
ruptureGasCache[hash] = vote
}
if ruptureGasCache[ancestry[0]].Cmp(ruptureThreshold) <= 0 {
blockRuptureCodes = true
}
// Make sure we don't OOM long run due to too many votes caching up
for len(ruptureGasCache) > ruptureCacheLimit {
for hash, _ := range ruptureGasCache {
delete(ruptureGasCache, hash)
break
}
}
}
// Verify if the DAO soft fork kicks in
if blockRuptureCodes {
if recipient := tx.To(); recipient == nil || !ruptureWhitelist[*recipient] {
for hash, _ := range env.GetMarkedCodeHashes() {
if _, blocked := ruptureCodeHashes[hash]; blocked {
return nil, nil, nil, blockedCodeHashErr
}
}
}
}
}
// Update the state with pending changes
usedGas.Add(usedGas, gas)
receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas)
-3
View File
@@ -73,8 +73,6 @@ type Environment interface {
DelegateCall(me ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error)
// Create a new contract
Create(me ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error)
// Mark the code hash that was executed
MarkCodeHash(hash common.Hash)
}
// Vm is the basic interface for an implementation of the EVM.
@@ -98,7 +96,6 @@ type Database interface {
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
GetCodeHash(common.Address) common.Hash
AddRefund(*big.Int)
GetRefund() *big.Int
+4 -5
View File
@@ -175,11 +175,10 @@ func NewEnv(noJit, forceJit bool) *Env {
return env
}
func (self *Env) MarkCodeHash(common.Hash) {}
func (self *Env) RuleSet() RuleSet { return ruleSet{new(big.Int)} }
func (self *Env) Vm() Vm { return self.evm }
func (self *Env) Origin() common.Address { return common.Address{} }
func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
func (self *Env) RuleSet() RuleSet { return ruleSet{new(big.Int)} }
func (self *Env) Vm() Vm { return self.evm }
func (self *Env) Origin() common.Address { return common.Address{} }
func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
func (self *Env) AddStructLog(log StructLog) {
}
func (self *Env) StructLogs() []StructLog {
-2
View File
@@ -79,8 +79,6 @@ func (self *Env) AddStructLog(log vm.StructLog) {
self.logs = append(self.logs, log)
}
func (self *Env) MarkCodeHash(hash common.Hash) {}
func (self *Env) RuleSet() vm.RuleSet { return self.ruleSet }
func (self *Env) Vm() vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return self.origin }
-6
View File
@@ -47,8 +47,6 @@ type VMEnv struct {
depth int // Current execution depth
msg Message // Message appliod
codeHashes map[common.Hash]struct{} // code hashes collected during execution
header *types.Header // Header information
chain *BlockChain // Blockchain handle
logs []vm.StructLog // Logs for the custom structured logger
@@ -58,7 +56,6 @@ type VMEnv struct {
func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, msg Message, header *types.Header, cfg vm.Config) *VMEnv {
env := &VMEnv{
chainConfig: chainConfig,
codeHashes: make(map[common.Hash]struct{}),
chain: chain,
state: state,
header: header,
@@ -75,9 +72,6 @@ func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, m
return env
}
func (self *VMEnv) MarkCodeHash(hash common.Hash) { self.codeHashes[hash] = struct{}{} }
func (self *VMEnv) GetMarkedCodeHashes() map[common.Hash]struct{} { return self.codeHashes }
func (self *VMEnv) RuleSet() vm.RuleSet { return self.chainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
-1
View File
@@ -207,7 +207,6 @@ func NewEnvFromMap(ruleSet RuleSet, state *state.StateDB, envValues map[string]s
return env
}
func (self *Env) MarkCodeHash(common.Hash) {}
func (self *Env) RuleSet() vm.RuleSet { return self.ruleSet }
func (self *Env) Vm() vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return self.origin }