Merge pull request #3067 from karalabe/vm-avoid-hashing

cmd, core, internal, light, tests: avoid hashing the code in the VM
This commit is contained in:
Péter Szilágyi 2016-10-01 16:58:49 +03:00 committed by GitHub
commit 0731b44809
17 changed files with 59 additions and 37 deletions

View File

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
@ -146,7 +147,9 @@ func run(ctx *cli.Context) error {
) )
} else { } else {
receiver := statedb.CreateAccount(common.StringToAddress("receiver")) receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
code := common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))
receiver.SetCode(crypto.Keccak256Hash(code), code)
ret, err = vmenv.Call( ret, err = vmenv.Call(
sender, sender,
receiver.Address(), receiver.Address(),

View File

@ -27,14 +27,14 @@ import (
// Call executes within the given contract // Call executes within the given contract
func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) { func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
ret, _, err = exec(env, caller, &addr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value) ret, _, err = exec(env, caller, &addr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err return ret, err
} }
// CallCode executes the given address' code as the given contract address // CallCode executes the given address' code as the given contract address
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) { func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
callerAddr := caller.Address() callerAddr := caller.Address()
ret, _, err = exec(env, caller, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value) ret, _, err = exec(env, caller, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err return ret, err
} }
@ -43,13 +43,13 @@ func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address
callerAddr := caller.Address() callerAddr := caller.Address()
originAddr := env.Origin() originAddr := env.Origin()
callerValue := caller.Value() callerValue := caller.Value()
ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, callerValue) ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
return ret, err return ret, err
} }
// Create creates a new contract with the given code // Create creates a new contract with the given code
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) { func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
ret, address, err = exec(env, caller, nil, nil, nil, code, gas, gasPrice, value) ret, address, err = exec(env, caller, nil, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value)
// Here we get an error if we run into maximum stack depth, // Here we get an error if we run into maximum stack depth,
// See: https://github.com/ethereum/yellowpaper/pull/131 // See: https://github.com/ethereum/yellowpaper/pull/131
// and YP definitions for CREATE instruction // and YP definitions for CREATE instruction
@ -59,7 +59,7 @@ func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPric
return ret, address, err return ret, address, err
} }
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) { 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) {
evm := env.Vm() evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the // Depth check execution. Fail if we're trying to execute above the
// limit. // limit.
@ -105,7 +105,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
// EVM. The contract is a scoped environment for this execution context // EVM. The contract is a scoped environment for this execution context
// only. // only.
contract := vm.NewContract(caller, to, value, gas, gasPrice) contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(codeAddr, code) contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise() defer contract.Finalise()
ret, err = evm.Run(contract, input) ret, err = evm.Run(contract, input)
@ -135,7 +135,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
return ret, addr, err return ret, addr, err
} }
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) { 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) {
evm := env.Vm() evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the // Depth check execution. Fail if we're trying to execute above the
// limit. // limit.
@ -155,7 +155,7 @@ func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toA
// Iinitialise a new contract and make initialise the delegate values // Iinitialise a new contract and make initialise the delegate values
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate() contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
contract.SetCallCode(codeAddr, code) contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise() defer contract.Finalise()
ret, err = evm.Run(contract, input) ret, err = evm.Run(contract, input)

View File

@ -273,9 +273,9 @@ func (self *StateObject) Code(db trie.Database) []byte {
return code return code
} }
func (self *StateObject) SetCode(code []byte) { func (self *StateObject) SetCode(codeHash common.Hash, code []byte) {
self.code = code self.code = code
self.data.CodeHash = crypto.Keccak256(code) self.data.CodeHash = codeHash[:]
self.dirtyCode = true self.dirtyCode = true
if self.onDirty != nil { if self.onDirty != nil {
self.onDirty(self.Address()) self.onDirty(self.Address())

View File

@ -24,6 +24,7 @@ import (
checker "gopkg.in/check.v1" checker "gopkg.in/check.v1"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
) )
@ -40,7 +41,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01})) obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01}))
obj1.AddBalance(big.NewInt(22)) obj1.AddBalance(big.NewInt(22))
obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02}))
obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3}) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02})) obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02}))
obj3.SetBalance(big.NewInt(44)) obj3.SetBalance(big.NewInt(44))
@ -148,7 +149,7 @@ func TestSnapshot2(t *testing.T) {
so0 := state.GetStateObject(stateobjaddr0) so0 := state.GetStateObject(stateobjaddr0)
so0.SetBalance(big.NewInt(42)) so0.SetBalance(big.NewInt(42))
so0.SetNonce(43) so0.SetNonce(43)
so0.SetCode([]byte{'c', 'a', 'f', 'e'}) so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
so0.remove = false so0.remove = false
so0.deleted = false so0.deleted = false
state.SetStateObject(so0) state.SetStateObject(so0)
@ -160,7 +161,7 @@ func TestSnapshot2(t *testing.T) {
so1 := state.GetStateObject(stateobjaddr1) so1 := state.GetStateObject(stateobjaddr1)
so1.SetBalance(big.NewInt(52)) so1.SetBalance(big.NewInt(52))
so1.SetNonce(53) so1.SetNonce(53)
so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'}) so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
so1.remove = true so1.remove = true
so1.deleted = true so1.deleted = true
state.SetStateObject(so1) state.SetStateObject(so1)

View File

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
@ -246,6 +247,14 @@ func (self *StateDB) GetCodeSize(addr common.Address) int {
return size return size
} }
func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
stateObject := self.GetStateObject(addr)
if stateObject == nil {
return common.Hash{}
}
return common.BytesToHash(stateObject.CodeHash())
}
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
stateObject := self.GetStateObject(a) stateObject := self.GetStateObject(a)
if stateObject != nil { if stateObject != nil {
@ -283,7 +292,7 @@ func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
func (self *StateDB) SetCode(addr common.Address, code []byte) { func (self *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetCode(code) stateObject.SetCode(crypto.Keccak256Hash(code), code)
} }
} }

View File

@ -21,6 +21,7 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
) )
@ -40,7 +41,7 @@ func TestUpdateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) obj.SetState(common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
} }
state.UpdateStateObject(obj) state.UpdateStateObject(obj)
} }
@ -70,7 +71,7 @@ func TestIntermediateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i, 0}), common.BytesToHash([]byte{i, i, i, i, 0})) obj.SetState(common.BytesToHash([]byte{i, i, i, 0}), common.BytesToHash([]byte{i, i, i, i, 0}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i, 0}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 0}), []byte{i, i, i, i, i, 0})
} }
transState.UpdateStateObject(obj) transState.UpdateStateObject(obj)
@ -82,7 +83,7 @@ func TestIntermediateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1})) obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i, 1}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 1}), []byte{i, i, i, i, i, 1})
} }
transState.UpdateStateObject(obj) transState.UpdateStateObject(obj)
@ -94,7 +95,7 @@ func TestIntermediateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1})) obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i, 1}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 1}), []byte{i, i, i, i, i, 1})
} }
finalState.UpdateStateObject(obj) finalState.UpdateStateObject(obj)
} }

View File

@ -54,7 +54,7 @@ func makeTestState() (ethdb.Database, common.Hash, []*testAccount) {
acc.nonce = uint64(42 * i) acc.nonce = uint64(42 * i)
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
acc.code = []byte{i, i, i, i, i} acc.code = []byte{i, i, i, i, i}
} }
state.UpdateStateObject(obj) state.UpdateStateObject(obj)

View File

@ -27,7 +27,7 @@ type ContractRef interface {
ReturnGas(*big.Int, *big.Int) ReturnGas(*big.Int, *big.Int)
Address() common.Address Address() common.Address
Value() *big.Int Value() *big.Int
SetCode([]byte) SetCode(common.Hash, []byte)
ForEachStorage(callback func(key, value common.Hash) bool) ForEachStorage(callback func(key, value common.Hash) bool)
} }
@ -44,8 +44,9 @@ type Contract struct {
jumpdests destinations // result of JUMPDEST analysis. jumpdests destinations // result of JUMPDEST analysis.
Code []byte Code []byte
Input []byte CodeHash common.Hash
CodeAddr *common.Address CodeAddr *common.Address
Input []byte
value, Gas, UsedGas, Price *big.Int value, Gas, UsedGas, Price *big.Int
@ -143,14 +144,16 @@ func (c *Contract) Value() *big.Int {
} }
// SetCode sets the code to the contract // SetCode sets the code to the contract
func (self *Contract) SetCode(code []byte) { func (self *Contract) SetCode(hash common.Hash, code []byte) {
self.Code = code self.Code = code
self.CodeHash = hash
} }
// SetCallCode sets the code of the contract and address of the backing data // SetCallCode sets the code of the contract and address of the backing data
// object // object
func (self *Contract) SetCallCode(addr *common.Address, code []byte) { func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
self.Code = code self.Code = code
self.CodeHash = hash
self.CodeAddr = addr self.CodeAddr = addr
} }

View File

@ -94,6 +94,7 @@ type Database interface {
GetNonce(common.Address) uint64 GetNonce(common.Address) uint64
SetNonce(common.Address, uint64) SetNonce(common.Address, uint64)
GetCodeHash(common.Address) common.Hash
GetCodeSize(common.Address) int GetCodeSize(common.Address) int
GetCode(common.Address) []byte GetCode(common.Address) []byte
SetCode(common.Address, []byte) SetCode(common.Address, []byte)
@ -118,7 +119,7 @@ type Account interface {
Balance() *big.Int Balance() *big.Int
Address() common.Address Address() common.Address
ReturnGas(*big.Int, *big.Int) ReturnGas(*big.Int, *big.Int)
SetCode([]byte) SetCode(common.Hash, []byte)
ForEachStorage(cb func(key, value common.Hash) bool) ForEachStorage(cb func(key, value common.Hash) bool)
Value() *big.Int Value() *big.Int
} }

View File

@ -135,7 +135,7 @@ func (account) SetNonce(uint64) {}
func (account) Balance() *big.Int { return nil } func (account) Balance() *big.Int { return nil }
func (account) Address() common.Address { return common.Address{} } func (account) Address() common.Address { return common.Address{} }
func (account) ReturnGas(*big.Int, *big.Int) {} func (account) ReturnGas(*big.Int, *big.Int) {}
func (account) SetCode([]byte) {} func (account) SetCode(common.Hash, []byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
func runVmBench(test vmBench, b *testing.B) { func runVmBench(test vmBench, b *testing.B) {

View File

@ -30,7 +30,7 @@ type dummyContractRef struct {
func (dummyContractRef) ReturnGas(*big.Int, *big.Int) {} func (dummyContractRef) ReturnGas(*big.Int, *big.Int) {}
func (dummyContractRef) Address() common.Address { return common.Address{} } func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) } func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode([]byte) {} func (dummyContractRef) SetCode(common.Hash, []byte) {}
func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) { func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) {
d.calledForEach = true d.calledForEach = true
} }

View File

@ -104,7 +104,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
receiver = cfg.State.CreateAccount(common.StringToAddress("contract")) receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
) )
// set the receiver's (the executing contract) code for execution. // set the receiver's (the executing contract) code for execution.
receiver.SetCode(code) receiver.SetCode(crypto.Keccak256Hash(code), code)
// Call the code with the given configuration. // Call the code with the given configuration.
ret, err := vmenv.Call( ret, err := vmenv.Call(

View File

@ -71,10 +71,11 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
return nil, nil return nil, nil
} }
var ( codehash := contract.CodeHash // codehash is used when doing jump dest caching
codehash = crypto.Keccak256Hash(contract.Code) // codehash is used when doing jump dest caching if codehash == (common.Hash{}) {
program *Program codehash = crypto.Keccak256Hash(contract.Code)
) }
var program *Program
if evm.cfg.EnableJit { if evm.cfg.EnableJit {
// If the JIT is enabled check the status of the JIT program, // If the JIT is enabled check the status of the JIT program,
// if it doesn't exist compile a new program in a separate // if it doesn't exist compile a new program in a separate

View File

@ -93,7 +93,7 @@ func (account) SetNonce(uint64) {}
func (account) Balance() *big.Int { return nil } func (account) Balance() *big.Int { return nil }
func (account) Address() common.Address { return common.Address{} } func (account) Address() common.Address { return common.Address{} }
func (account) ReturnGas(*big.Int, *big.Int) {} func (account) ReturnGas(*big.Int, *big.Int) {}
func (account) SetCode([]byte) {} func (account) SetCode(common.Hash, []byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
func runTrace(tracer *JavascriptTracer) (interface{}, error) { func runTrace(tracer *JavascriptTracer) (interface{}, error) {

View File

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -60,7 +61,7 @@ func makeTestState() (common.Hash, ethdb.Database) {
so.SetNonce(100) so.SetNonce(100)
} }
so.AddBalance(big.NewInt(int64(i))) so.AddBalance(big.NewInt(int64(i)))
so.SetCode([]byte{i, i, i}) so.SetCode(crypto.Keccak256Hash([]byte{i, i, i}), []byte{i, i, i})
so.UpdateRoot(sdb) so.UpdateRoot(sdb)
st.UpdateStateObject(so) st.UpdateStateObject(so)
} }

View File

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
@ -219,7 +220,7 @@ func (t *BlockTest) InsertPreState(db ethdb.Database) (*state.StateDB, error) {
return nil, err return nil, err
} }
obj := statedb.CreateAccount(common.HexToAddress(addrString)) obj := statedb.CreateAccount(common.HexToAddress(addrString))
obj.SetCode(code) obj.SetCode(crypto.Keccak256Hash(code), code)
obj.SetBalance(balance) obj.SetBalance(balance)
obj.SetNonce(nonce) obj.SetNonce(nonce)
for k, v := range acct.Storage { for k, v := range acct.Storage {

View File

@ -108,12 +108,13 @@ func StateObjectFromAccount(db ethdb.Database, addr string, account Account, onD
account.Code = account.Code[2:] account.Code = account.Code[2:]
} }
code := common.Hex2Bytes(account.Code) code := common.Hex2Bytes(account.Code)
codeHash := crypto.Keccak256Hash(code)
obj := state.NewObject(common.HexToAddress(addr), state.Account{ obj := state.NewObject(common.HexToAddress(addr), state.Account{
Balance: common.Big(account.Balance), Balance: common.Big(account.Balance),
CodeHash: crypto.Keccak256(code), CodeHash: codeHash[:],
Nonce: common.Big(account.Nonce).Uint64(), Nonce: common.Big(account.Nonce).Uint64(),
}, onDirty) }, onDirty)
obj.SetCode(code) obj.SetCode(codeHash, code)
return obj return obj
} }