forked from cerc-io/plugeth
359 lines
68 KiB
Go
359 lines
68 KiB
Go
|
// 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("606060405261339c806100126000396000f3606060405260e060020a6000350463e2faf0448114601a575b005b6097600435602435604435606435600084308585853360606132e8806100b48339018087600160a060020a0316815260200186600160a060020a0316815260200185815260200184815260200183815260200182600160a060020a031681526020019650505050505050604051809103906000f095945050505050565b60408051600160a060020a03929092168252519081900360200190f3606060405260405160c0806132e88339610120604052905160805160a051925160e0516101005193949293828282600f829055601083905560118054610100830261010060a860020a031990911617905560405130906001906101bc806103378339600160a060020a039390931692019182526020820152604080519182900301906000f060128054600160a060020a031916919091179055505060038054600160a060020a03199081168917909155600e80549091168717905550600c84905560405130906000906101bc806104f38339018083600160a060020a0316815260200182815260200192505050604051809103906000f060405160078054600160a060020a0319169290921790915530906000906101bc806106af8339018083600160a060020a0316815260200182815260200192505050604051809103906000f060088054600160a060020a031916919091179055600754600160a060020a0316600014156101c357610002565b50505030600160a060020a03908116600090815260046020526040808220805460ff19908116600190811790925560035490941683529120805490921617905550505050505050612a7d8061086b6000396000f35b600854600160a060020a0316600014156101dc57610002565b4260025560056001908155600080548282558290801582901161016e57600e0281600e02836000526020600020918201910161016e919061023e565b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b80821115610333578054600160a060020a03191681556000600182810182905560028381018054848255909281161561010002600019011604601f81901061030557505b506000600383018190556004838101805461ffff19169055600584018290556006840182905560078401805460ff191690556008840180548382559083526020909220610218929091028101905b808211156103335760008082556001820181815560028301919091556003919091018054600160a060020a03191690556102d0565b601f01602090049060005260206000209081019061028291905b80821115610333576000815560010161031f565b50905660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a8114610
|
||
|
|
||
|
// EVM deploy bytecode of the DAO to simulate blocking.
|
||
|
var daoDeployCode = common.FromHex("606060405260405160c0806132c88339610120604052905160805160a051925160e0516101005193949293828282600f829055601083905560118054610100830261010060a860020a031990911617905560405130906001906101bc8061033e8339600160a060020a03909316908301526101408201526040519081900361016001906000f060128054600160a060020a031916919091179055505060038054600160a060020a03199081168917909155600e80549091168717905550600c84905560405130906000906101bc806104fa8339018083600160a060020a0316815260200182815260200192505050604051809103906000f0600760006101000a815481600160a060020a03021916908302179055503060006040516101bc806106b68339018083600160a060020a0316815260200182815260200192505050604051809103906000f060088054600160a060020a031916919091179055600754600160a060020a03166000141561017557610002565b600854600160a060020a03166000141561018e57610002565b426002556005600190815560008054828255829080158290116101ca57600e0281600e0283600052602060002091820191016101ca9190610245565b50505030600160a060020a03908116600090815260046020526040808220805460ff19908116600190811790925560035490941683529120805490921617905550505050505050612a56806108726000396000f35b5050600060098201819055600a820155600d81018054600160a060020a03191690556001015b8082111561033a578054600160a060020a03191681556000600182810182905560028381018054848255909281161561010002600019011604601f81901061030c57505b506000600383018190556004838101805461ffff19169055600584018290556006840182905560078401805460ff19169055600884018054838255908352602090922061021f929091028101905b8082111561033a5760008082556001820181815560028301919091556003919091018054600160a060020a03191690556102d7565b601f01602090049060005260206000209081019061028991905b8082111561033a5760008155600101610326565b50905660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b60408051918252519081900360200190f35b6060908152602090f35b600160a060020a0383168260608381818185876185025a03f1925050501561015c57604080518381529051600160a060020a038516917f9735b0cb909f3d21d5c16bbcccd272d85fa11446f6d679f6ecb170d2dabfecfc919081900360200190a25060015b929150505660606040818152806101bc833960a090525160805160008054600160a060020a03191690921760a060020a60ff0219167401000000000000000000000000000000000000000090910217815561016290819061005a90396000f3606060405236156100405760e060020a60003504630221038a811461004d57806318bdc79a146100aa5780638da5cb5b146100be578063d2cc718f146100d0575b6100d96001805434019055565b6100db6004356024356000805433600160a060020a0390811691161415806100755750600034115b806100a05750805460a060020a900460ff1680156100a057508054600160a060020a03848116911614155b156100f757610002565b6100db60005460ff60a060020a9091041681565b6100ed600054600160a060020a031681565b6100db60015481565b005b604
|
||
|
|
||
|
// 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))
|
||
|
}
|
||
|
}
|