Skip to content

Commit f1949f4

Browse files
committed
[release/1.4.15] cmd, core, internal, light, tests: avoid hashing the code in the VM
(cherry picked from commit cb84e3f)
1 parent 968ab8a commit f1949f4

File tree

16 files changed

+58
-36
lines changed

16 files changed

+58
-36
lines changed

cmd/evm/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/ethereum/go-ethereum/core/state"
3131
"github.com/ethereum/go-ethereum/core/types"
3232
"github.com/ethereum/go-ethereum/core/vm"
33+
"github.com/ethereum/go-ethereum/crypto"
3334
"github.com/ethereum/go-ethereum/ethdb"
3435
"github.com/ethereum/go-ethereum/logger/glog"
3536
"gopkg.in/urfave/cli.v1"
@@ -141,7 +142,9 @@ func run(ctx *cli.Context) error {
141142
)
142143
} else {
143144
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
144-
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
145+
146+
code := common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))
147+
receiver.SetCode(crypto.Keccak256Hash(code), code)
145148
ret, err = vmenv.Call(
146149
sender,
147150
receiver.Address(),

core/execution.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ import (
2727

2828
// Call executes within the given contract
2929
func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
30-
ret, _, err = exec(env, caller, &addr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
30+
ret, _, err = exec(env, caller, &addr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
3131
return ret, err
3232
}
3333

3434
// CallCode executes the given address' code as the given contract address
3535
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
3636
callerAddr := caller.Address()
37-
ret, _, err = exec(env, caller, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value)
37+
ret, _, err = exec(env, caller, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
3838
return ret, err
3939
}
4040

@@ -43,13 +43,13 @@ func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address
4343
callerAddr := caller.Address()
4444
originAddr := env.Origin()
4545
callerValue := caller.Value()
46-
ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
46+
ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
4747
return ret, err
4848
}
4949

5050
// Create creates a new contract with the given code
5151
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
52-
ret, address, err = exec(env, caller, nil, nil, nil, code, gas, gasPrice, value)
52+
ret, address, err = exec(env, caller, nil, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value)
5353
// Here we get an error if we run into maximum stack depth,
5454
// See: https://github.com/ethereum/yellowpaper/pull/131
5555
// and YP definitions for CREATE instruction
@@ -59,7 +59,7 @@ func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPric
5959
return ret, address, err
6060
}
6161

62-
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
62+
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
6363
evm := env.Vm()
6464
// Depth check execution. Fail if we're trying to execute above the
6565
// limit.
@@ -105,7 +105,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
105105
// EVM. The contract is a scoped environment for this execution context
106106
// only.
107107
contract := vm.NewContract(caller, to, value, gas, gasPrice)
108-
contract.SetCallCode(codeAddr, code)
108+
contract.SetCallCode(codeAddr, codeHash, code)
109109
defer contract.Finalise()
110110

111111
ret, err = evm.Run(contract, input)
@@ -135,7 +135,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
135135
return ret, addr, err
136136
}
137137

138-
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
138+
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
139139
evm := env.Vm()
140140
// Depth check execution. Fail if we're trying to execute above the
141141
// limit.
@@ -155,7 +155,7 @@ func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toA
155155

156156
// Iinitialise a new contract and make initialise the delegate values
157157
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
158-
contract.SetCallCode(codeAddr, code)
158+
contract.SetCallCode(codeAddr, codeHash, code)
159159
defer contract.Finalise()
160160

161161
ret, err = evm.Run(contract, input)

core/state/state_object.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ func (self *StateObject) Code(db trie.Database) []byte {
273273
return code
274274
}
275275

276-
func (self *StateObject) SetCode(code []byte) {
276+
func (self *StateObject) SetCode(codeHash common.Hash, code []byte) {
277277
self.code = code
278-
self.data.CodeHash = crypto.Keccak256(code)
278+
self.data.CodeHash = codeHash[:]
279279
self.dirtyCode = true
280280
if self.onDirty != nil {
281281
self.onDirty(self.Address())

core/state/state_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
checker "gopkg.in/check.v1"
2525

2626
"github.com/ethereum/go-ethereum/common"
27+
"github.com/ethereum/go-ethereum/crypto"
2728
"github.com/ethereum/go-ethereum/ethdb"
2829
)
2930

@@ -40,7 +41,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
4041
obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01}))
4142
obj1.AddBalance(big.NewInt(22))
4243
obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02}))
43-
obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3})
44+
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
4445
obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02}))
4546
obj3.SetBalance(big.NewInt(44))
4647

@@ -148,7 +149,7 @@ func TestSnapshot2(t *testing.T) {
148149
so0 := state.GetStateObject(stateobjaddr0)
149150
so0.SetBalance(big.NewInt(42))
150151
so0.SetNonce(43)
151-
so0.SetCode([]byte{'c', 'a', 'f', 'e'})
152+
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
152153
so0.remove = false
153154
so0.deleted = false
154155
state.SetStateObject(so0)
@@ -160,7 +161,7 @@ func TestSnapshot2(t *testing.T) {
160161
so1 := state.GetStateObject(stateobjaddr1)
161162
so1.SetBalance(big.NewInt(52))
162163
so1.SetNonce(53)
163-
so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'})
164+
so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
164165
so1.remove = true
165166
so1.deleted = true
166167
state.SetStateObject(so1)

core/state/statedb.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/ethereum/go-ethereum/common"
2626
"github.com/ethereum/go-ethereum/core/vm"
27+
"github.com/ethereum/go-ethereum/crypto"
2728
"github.com/ethereum/go-ethereum/ethdb"
2829
"github.com/ethereum/go-ethereum/logger"
2930
"github.com/ethereum/go-ethereum/logger/glog"
@@ -246,6 +247,14 @@ func (self *StateDB) GetCodeSize(addr common.Address) int {
246247
return size
247248
}
248249

250+
func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
251+
stateObject := self.GetStateObject(addr)
252+
if stateObject == nil {
253+
return common.Hash{}
254+
}
255+
return common.BytesToHash(stateObject.CodeHash())
256+
}
257+
249258
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
250259
stateObject := self.GetStateObject(a)
251260
if stateObject != nil {
@@ -283,7 +292,7 @@ func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
283292
func (self *StateDB) SetCode(addr common.Address, code []byte) {
284293
stateObject := self.GetOrNewStateObject(addr)
285294
if stateObject != nil {
286-
stateObject.SetCode(code)
295+
stateObject.SetCode(crypto.Keccak256Hash(code), code)
287296
}
288297
}
289298

core/state/statedb_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"testing"
2222

2323
"github.com/ethereum/go-ethereum/common"
24+
"github.com/ethereum/go-ethereum/crypto"
2425
"github.com/ethereum/go-ethereum/ethdb"
2526
)
2627

@@ -40,7 +41,7 @@ func TestUpdateLeaks(t *testing.T) {
4041
obj.SetState(common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
4142
}
4243
if i%3 == 0 {
43-
obj.SetCode([]byte{i, i, i, i, i})
44+
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
4445
}
4546
state.UpdateStateObject(obj)
4647
}
@@ -70,7 +71,7 @@ func TestIntermediateLeaks(t *testing.T) {
7071
obj.SetState(common.BytesToHash([]byte{i, i, i, 0}), common.BytesToHash([]byte{i, i, i, i, 0}))
7172
}
7273
if i%3 == 0 {
73-
obj.SetCode([]byte{i, i, i, i, i, 0})
74+
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 0}), []byte{i, i, i, i, i, 0})
7475
}
7576
transState.UpdateStateObject(obj)
7677

@@ -82,7 +83,7 @@ func TestIntermediateLeaks(t *testing.T) {
8283
obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1}))
8384
}
8485
if i%3 == 0 {
85-
obj.SetCode([]byte{i, i, i, i, i, 1})
86+
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 1}), []byte{i, i, i, i, i, 1})
8687
}
8788
transState.UpdateStateObject(obj)
8889

@@ -94,7 +95,7 @@ func TestIntermediateLeaks(t *testing.T) {
9495
obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1}))
9596
}
9697
if i%3 == 0 {
97-
obj.SetCode([]byte{i, i, i, i, i, 1})
98+
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 1}), []byte{i, i, i, i, i, 1})
9899
}
99100
finalState.UpdateStateObject(obj)
100101
}

core/state/sync_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func makeTestState() (ethdb.Database, common.Hash, []*testAccount) {
5454
acc.nonce = uint64(42 * i)
5555

5656
if i%3 == 0 {
57-
obj.SetCode([]byte{i, i, i, i, i})
57+
obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
5858
acc.code = []byte{i, i, i, i, i}
5959
}
6060
state.UpdateStateObject(obj)

core/vm/contract.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type ContractRef interface {
2727
ReturnGas(*big.Int, *big.Int)
2828
Address() common.Address
2929
Value() *big.Int
30-
SetCode([]byte)
30+
SetCode(common.Hash, []byte)
3131
ForEachStorage(callback func(key, value common.Hash) bool)
3232
}
3333

@@ -44,8 +44,9 @@ type Contract struct {
4444
jumpdests destinations // result of JUMPDEST analysis.
4545

4646
Code []byte
47-
Input []byte
47+
CodeHash common.Hash
4848
CodeAddr *common.Address
49+
Input []byte
4950

5051
value, Gas, UsedGas, Price *big.Int
5152

@@ -143,14 +144,16 @@ func (c *Contract) Value() *big.Int {
143144
}
144145

145146
// SetCode sets the code to the contract
146-
func (self *Contract) SetCode(code []byte) {
147+
func (self *Contract) SetCode(hash common.Hash, code []byte) {
147148
self.Code = code
149+
self.CodeHash = hash
148150
}
149151

150152
// SetCallCode sets the code of the contract and address of the backing data
151153
// object
152-
func (self *Contract) SetCallCode(addr *common.Address, code []byte) {
154+
func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
153155
self.Code = code
156+
self.CodeHash = hash
154157
self.CodeAddr = addr
155158
}
156159

core/vm/environment.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ type Database interface {
9494
GetNonce(common.Address) uint64
9595
SetNonce(common.Address, uint64)
9696

97+
GetCodeHash(common.Address) common.Hash
9798
GetCodeSize(common.Address) int
9899
GetCode(common.Address) []byte
99100
SetCode(common.Address, []byte)
@@ -118,7 +119,7 @@ type Account interface {
118119
Balance() *big.Int
119120
Address() common.Address
120121
ReturnGas(*big.Int, *big.Int)
121-
SetCode([]byte)
122+
SetCode(common.Hash, []byte)
122123
ForEachStorage(cb func(key, value common.Hash) bool)
123124
Value() *big.Int
124125
}

core/vm/jit_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ func (account) SetNonce(uint64) {}
135135
func (account) Balance() *big.Int { return nil }
136136
func (account) Address() common.Address { return common.Address{} }
137137
func (account) ReturnGas(*big.Int, *big.Int) {}
138-
func (account) SetCode([]byte) {}
138+
func (account) SetCode(common.Hash, []byte) {}
139139
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
140140

141141
func runVmBench(test vmBench, b *testing.B) {

0 commit comments

Comments
 (0)