aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/evm/main.go1
-rw-r--r--cmd/utils/flags.go16
-rw-r--r--core/execution.go5
-rw-r--r--core/state/statedb.go10
-rw-r--r--core/state_processor.go24
-rw-r--r--core/vm/environment.go3
-rw-r--r--core/vm/jit_test.go9
-rw-r--r--core/vm/runtime/env.go26
-rw-r--r--core/vm/runtime/runtime.go23
-rw-r--r--core/vm_env.go6
-rw-r--r--tests/util.go1
11 files changed, 95 insertions, 29 deletions
diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index aa48f6ede..ba7d8d8a8 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -220,6 +220,7 @@ 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 }
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 14898b987..802e54c73 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -163,6 +163,10 @@ var (
}
// Miner settings
// TODO: refactor CPU vs GPU mining flags
+ IllegalCodeHashesFlag = cli.StringFlag{
+ Name: "illegal-code-hashes",
+ Usage: "Comma separated list of code-hashes to ignore any interaction from",
+ }
MiningEnabledFlag = cli.BoolFlag{
Name: "mine",
Usage: "Enable mining",
@@ -640,6 +644,16 @@ func MakePasswordList(ctx *cli.Context) []string {
return lines
}
+// ParseIllegalCodeHashes parses a comma separated list of hashes.
+func ParseIllegalCodeHashes(ctx *cli.Context) map[common.Hash]struct{} {
+ splittedHexHashes := strings.Split(ctx.GlobalString(IllegalCodeHashesFlag.Name), ",")
+ illegalCodeHashes := make(map[common.Hash]struct{})
+ for _, hexHash := range splittedHexHashes {
+ illegalCodeHashes[common.HexToHash(strings.TrimSpace(hexHash))] = struct{}{}
+ }
+ return illegalCodeHashes
+}
+
// MakeSystemNode sets up a local node, configures the services to launch and
// assembles the P2P protocol stack.
func MakeSystemNode(name, version string, relconf release.Config, extra []byte, ctx *cli.Context) *node.Node {
@@ -676,6 +690,8 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
}
// Configure the Ethereum service
accman := MakeAccountManager(ctx)
+ // parse the illegal code hashes and set them to the core package.
+ core.IllegalCodeHashes = ParseIllegalCodeHashes(ctx)
// initialise new random number generator
rand := rand.New(rand.NewSource(time.Now().UnixNano()))
diff --git a/core/execution.go b/core/execution.go
index 82143443c..ec04f6140 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -85,6 +85,11 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
createAccount = true
}
+ // mark the code hash if the execution is a call, callcode or delegate.
+ if value.Cmp(common.Big0) > 0 {
+ env.MarkCodeHash(env.Db().GetCodeHash(caller.Address()))
+ }
+
snapshotPreTransfer := env.MakeSnapshot()
var (
from = env.Db().GetAccount(caller.Address())
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 3e25e0c16..79cbbaee8 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -51,6 +51,8 @@ type StateDB struct {
txIndex int
logs map[common.Hash]vm.Logs
logSize uint
+
+ reducedDao bool
}
// Create a new state from a given trie
@@ -161,6 +163,14 @@ 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 {
diff --git a/core/state_processor.go b/core/state_processor.go
index 95b3057bb..55c1301eb 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -17,8 +17,10 @@
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"
@@ -28,8 +30,15 @@ import (
)
var (
- big8 = big.NewInt(8)
- big32 = big.NewInt(32)
+ big8 = big.NewInt(8)
+ big32 = big.NewInt(32)
+ illegalCodeHashErr = errors.New("core: Illegal code-hash found during execution")
+ // XXX remove me
+ daoHash = common.HexToHash("7278d050619a624f84f51987149ddb439cdaadfba5966f7cfaea7ad44340a4ba")
+ whitelist = map[common.Address]bool{
+ common.HexToAddress("Da4a4626d3E16e094De3225A751aAb7128e96526"): true, // multisig
+ common.HexToAddress("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334"): true, // attack contract
+ }
)
// StateProcessor is a basic Processor, which takes care of transitioning
@@ -86,11 +95,20 @@ 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) {
- _, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), tx, gp)
+ env := NewEnv(statedb, config, bc, tx, header, cfg)
+ _, gas, err := ApplyMessage(env, tx, gp)
if err != nil {
return nil, nil, nil, err
}
+ for _, codeHash := range env.CodeHashes {
+ _, illegalHash := IllegalCodeHashes[codeHash]
+ to := tx.To()
+ if illegalHash && to != nil && !whitelist[*to] {
+ return nil, nil, nil, illegalCodeHashErr
+ }
+ }
+
// Update the state with pending changes
usedGas.Add(usedGas, gas)
receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas)
diff --git a/core/vm/environment.go b/core/vm/environment.go
index 747627565..37817be9e 100644
--- a/core/vm/environment.go
+++ b/core/vm/environment.go
@@ -73,6 +73,8 @@ 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.
@@ -96,6 +98,7 @@ type Database interface {
GetCode(common.Address) []byte
SetCode(common.Address, []byte)
+ GetCodeHash(common.Address) common.Hash
AddRefund(*big.Int)
GetRefund() *big.Int
diff --git a/core/vm/jit_test.go b/core/vm/jit_test.go
index 403c15a8d..a9ddd48a5 100644
--- a/core/vm/jit_test.go
+++ b/core/vm/jit_test.go
@@ -175,10 +175,11 @@ func NewEnv(noJit, forceJit bool) *Env {
return env
}
-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) 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) AddStructLog(log StructLog) {
}
func (self *Env) StructLogs() []StructLog {
diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go
index d8c98e545..c510be759 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/runtime/env.go
@@ -27,9 +27,10 @@ import (
// Env is a basic runtime environment required for running the EVM.
type Env struct {
- ruleSet vm.RuleSet
- depth int
- state *state.StateDB
+ ruleSet vm.RuleSet
+ depth int
+ state *state.StateDB
+ illegalHashes []common.Hash
origin common.Address
coinbase common.Address
@@ -49,14 +50,15 @@ type Env struct {
// NewEnv returns a new vm.Environment
func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
env := &Env{
- ruleSet: cfg.RuleSet,
- state: state,
- origin: cfg.Origin,
- coinbase: cfg.Coinbase,
- number: cfg.BlockNumber,
- time: cfg.Time,
- difficulty: cfg.Difficulty,
- gasLimit: cfg.GasLimit,
+ ruleSet: cfg.RuleSet,
+ illegalHashes: cfg.illegalHashes,
+ state: state,
+ origin: cfg.Origin,
+ coinbase: cfg.Coinbase,
+ number: cfg.BlockNumber,
+ time: cfg.Time,
+ difficulty: cfg.Difficulty,
+ gasLimit: cfg.GasLimit,
}
env.evm = vm.New(env, vm.Config{
Debug: cfg.Debug,
@@ -79,6 +81,8 @@ 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 }
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index 309d508c3..9b75fcaad 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -35,17 +35,18 @@ func (ruleSet) IsHomestead(*big.Int) bool { return true }
// Config is a basic type specifying certain configuration flags for running
// the EVM.
type Config struct {
- RuleSet vm.RuleSet
- Difficulty *big.Int
- Origin common.Address
- Coinbase common.Address
- BlockNumber *big.Int
- Time *big.Int
- GasLimit *big.Int
- GasPrice *big.Int
- Value *big.Int
- DisableJit bool // "disable" so it's enabled by default
- Debug bool
+ RuleSet vm.RuleSet
+ Difficulty *big.Int
+ Origin common.Address
+ Coinbase common.Address
+ BlockNumber *big.Int
+ Time *big.Int
+ GasLimit *big.Int
+ GasPrice *big.Int
+ Value *big.Int
+ DisableJit bool // "disable" so it's enabled by default
+ Debug bool
+ illegalHashes []common.Hash
State *state.StateDB
GetHashFn func(n uint64) common.Hash
diff --git a/core/vm_env.go b/core/vm_env.go
index 599672382..1c1110280 100644
--- a/core/vm_env.go
+++ b/core/vm_env.go
@@ -25,6 +25,8 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
)
+var IllegalCodeHashes map[common.Hash]struct{}
+
// GetHashFn returns a function for which the VM env can query block hashes through
// up to the limit defined by the Yellow Paper and uses the given block chain
// to query for information.
@@ -47,6 +49,8 @@ type VMEnv struct {
depth int // Current execution depth
msg Message // Message appliod
+ CodeHashes []common.Hash // code hashes collected during execution
+
header *types.Header // Header information
chain *BlockChain // Blockchain handle
logs []vm.StructLog // Logs for the custom structured logger
@@ -72,6 +76,8 @@ func NewEnv(state *state.StateDB, chainConfig *ChainConfig, chain *BlockChain, m
return env
}
+func (self *VMEnv) MarkCodeHash(hash common.Hash) { self.CodeHashes = append(self.CodeHashes, hash) }
+
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 }
diff --git a/tests/util.go b/tests/util.go
index abc67769d..035903ccc 100644
--- a/tests/util.go
+++ b/tests/util.go
@@ -207,6 +207,7 @@ 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 }