diff --git a/cmd/evm/main.go b/cmd/evm/main.go
index 3f44e0f3c0e162d216b5abc0fa11b4b97d4b4e9a..09ade1577dab0fdaf27835fe2c06476d9aaa0d3d 100644
--- a/cmd/evm/main.go
+++ b/cmd/evm/main.go
@@ -30,6 +30,7 @@ import (
 	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/ethereum/go-ethereum/core/vm"
+	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/logger/glog"
 	"gopkg.in/urfave/cli.v1"
@@ -146,7 +147,9 @@ func run(ctx *cli.Context) error {
 		)
 	} else {
 		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(
 			sender,
 			receiver.Address(),
diff --git a/core/execution.go b/core/execution.go
index 82143443c79a1cc4730deff41ca3db0baa2f0cab..1bc02f7fb2512150ef994a7f7058fbaf078d99a6 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -27,14 +27,14 @@ import (
 
 // 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) {
-	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
 }
 
 // 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) {
 	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
 }
 
@@ -43,13 +43,13 @@ func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address
 	callerAddr := caller.Address()
 	originAddr := env.Origin()
 	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
 }
 
 // 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) {
-	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,
 	// See: https://github.com/ethereum/yellowpaper/pull/131
 	// 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
 }
 
-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()
 	// Depth check execution. Fail if we're trying to execute above the
 	// 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
 	// only.
 	contract := vm.NewContract(caller, to, value, gas, gasPrice)
-	contract.SetCallCode(codeAddr, code)
+	contract.SetCallCode(codeAddr, codeHash, code)
 	defer contract.Finalise()
 
 	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
 }
 
-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()
 	// Depth check execution. Fail if we're trying to execute above the
 	// 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
 	contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
-	contract.SetCallCode(codeAddr, code)
+	contract.SetCallCode(codeAddr, codeHash, code)
 	defer contract.Finalise()
 
 	ret, err = evm.Run(contract, input)
diff --git a/core/state/state_object.go b/core/state/state_object.go
index a54620d5551790afc3af02930837dcba9d54052f..121a2ec5c3fa6351e4433190c42675f04e8d776d 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -273,9 +273,9 @@ func (self *StateObject) Code(db trie.Database) []byte {
 	return code
 }
 
-func (self *StateObject) SetCode(code []byte) {
+func (self *StateObject) SetCode(codeHash common.Hash, code []byte) {
 	self.code = code
-	self.data.CodeHash = crypto.Keccak256(code)
+	self.data.CodeHash = codeHash[:]
 	self.dirtyCode = true
 	if self.onDirty != nil {
 		self.onDirty(self.Address())
diff --git a/core/state/state_test.go b/core/state/state_test.go
index fcdc3858844d44d3a4b21945f1c6e27b867a4737..5fe98939ba25b3eb06f8219991cee9e9bb33eb3e 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -24,6 +24,7 @@ import (
 	checker "gopkg.in/check.v1"
 
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/crypto"
 	"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.AddBalance(big.NewInt(22))
 	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.SetBalance(big.NewInt(44))
 
@@ -148,7 +149,7 @@ func TestSnapshot2(t *testing.T) {
 	so0 := state.GetStateObject(stateobjaddr0)
 	so0.SetBalance(big.NewInt(42))
 	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.deleted = false
 	state.SetStateObject(so0)
@@ -160,7 +161,7 @@ func TestSnapshot2(t *testing.T) {
 	so1 := state.GetStateObject(stateobjaddr1)
 	so1.SetBalance(big.NewInt(52))
 	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.deleted = true
 	state.SetStateObject(so1)
diff --git a/core/state/statedb.go b/core/state/statedb.go
index 5c51e3b59b2126e36dbbb55d06eadc8f1a15c4fb..4204c456e014f728c1103c647c5145a350ccb5dd 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -24,6 +24,7 @@ import (
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/vm"
+	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/logger/glog"
@@ -246,6 +247,14 @@ func (self *StateDB) GetCodeSize(addr common.Address) int {
 	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 {
 	stateObject := self.GetStateObject(a)
 	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) {
 	stateObject := self.GetOrNewStateObject(addr)
 	if stateObject != nil {
-		stateObject.SetCode(code)
+		stateObject.SetCode(crypto.Keccak256Hash(code), code)
 	}
 }
 
diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go
index 92833345976920d89e31c836f1d6484a80f9fa4a..7930b620d4e601203cd0b4c5fdf016a083bcd71d 100644
--- a/core/state/statedb_test.go
+++ b/core/state/statedb_test.go
@@ -21,6 +21,7 @@ import (
 	"testing"
 
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/crypto"
 	"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}))
 		}
 		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)
 	}
@@ -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}))
 		}
 		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)
 
@@ -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}))
 		}
 		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)
 
@@ -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}))
 		}
 		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)
 	}
diff --git a/core/state/sync_test.go b/core/state/sync_test.go
index c768781a472a3ae51fef43da336abc27facab646..670e1fb1bf113e02e2350b419adafad687bf7abd 100644
--- a/core/state/sync_test.go
+++ b/core/state/sync_test.go
@@ -54,7 +54,7 @@ func makeTestState() (ethdb.Database, common.Hash, []*testAccount) {
 		acc.nonce = uint64(42 * i)
 
 		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}
 		}
 		state.UpdateStateObject(obj)
diff --git a/core/vm/contract.go b/core/vm/contract.go
index 844d3f328ee54897329ae184b5eebfcf3c85c033..70455a4c23e83ee4f37f300caf1084083c342bc8 100644
--- a/core/vm/contract.go
+++ b/core/vm/contract.go
@@ -27,7 +27,7 @@ type ContractRef interface {
 	ReturnGas(*big.Int, *big.Int)
 	Address() common.Address
 	Value() *big.Int
-	SetCode([]byte)
+	SetCode(common.Hash, []byte)
 	ForEachStorage(callback func(key, value common.Hash) bool)
 }
 
@@ -44,8 +44,9 @@ type Contract struct {
 	jumpdests destinations // result of JUMPDEST analysis.
 
 	Code     []byte
-	Input    []byte
+	CodeHash common.Hash
 	CodeAddr *common.Address
+	Input    []byte
 
 	value, Gas, UsedGas, Price *big.Int
 
@@ -143,14 +144,16 @@ func (c *Contract) Value() *big.Int {
 }
 
 // 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.CodeHash = hash
 }
 
 // SetCallCode sets the code of the contract and address of the backing data
 // 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.CodeHash = hash
 	self.CodeAddr = addr
 }
 
diff --git a/core/vm/environment.go b/core/vm/environment.go
index 4bd03de7eb164ec5de8cc021663f0e641e7db21f..daf6fb90d52fb5695e6fbd91cd26b55380adc19b 100644
--- a/core/vm/environment.go
+++ b/core/vm/environment.go
@@ -94,6 +94,7 @@ type Database interface {
 	GetNonce(common.Address) uint64
 	SetNonce(common.Address, uint64)
 
+	GetCodeHash(common.Address) common.Hash
 	GetCodeSize(common.Address) int
 	GetCode(common.Address) []byte
 	SetCode(common.Address, []byte)
@@ -118,7 +119,7 @@ type Account interface {
 	Balance() *big.Int
 	Address() common.Address
 	ReturnGas(*big.Int, *big.Int)
-	SetCode([]byte)
+	SetCode(common.Hash, []byte)
 	ForEachStorage(cb func(key, value common.Hash) bool)
 	Value() *big.Int
 }
diff --git a/core/vm/jit_test.go b/core/vm/jit_test.go
index 809abfea976f5ebdb0d9bafa19696eb3aa513219..e6922aeb74208637d64642feb62844b89ee294e5 100644
--- a/core/vm/jit_test.go
+++ b/core/vm/jit_test.go
@@ -135,7 +135,7 @@ func (account) SetNonce(uint64)                                     {}
 func (account) Balance() *big.Int                                   { return nil }
 func (account) Address() common.Address                             { return common.Address{} }
 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 runVmBench(test vmBench, b *testing.B) {
diff --git a/core/vm/logger_test.go b/core/vm/logger_test.go
index e85bca227717cd607fe52d6e4f28014a1d018a7e..d4d164eb6f39be2d840f2c2d6d5305cad82a2678 100644
--- a/core/vm/logger_test.go
+++ b/core/vm/logger_test.go
@@ -30,7 +30,7 @@ type dummyContractRef struct {
 func (dummyContractRef) ReturnGas(*big.Int, *big.Int) {}
 func (dummyContractRef) Address() common.Address      { return common.Address{} }
 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) {
 	d.calledForEach = true
 }
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index 309d508c3d6d4babb7ffa48ceee722c5c856ce96..6d980cb327ae9fad70eeb0c7882f701c714dffcb 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -104,7 +104,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
 		receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
 	)
 	// 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.
 	ret, err := vmenv.Call(
diff --git a/core/vm/vm.go b/core/vm/vm.go
index 9d7b550587ab907a7ba5af3a449517166d208253..5d78b4a2ad51f373d4ac28ecc13baf0fadbd66bf 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -71,10 +71,11 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
 		return nil, nil
 	}
 
-	var (
-		codehash = crypto.Keccak256Hash(contract.Code) // codehash is used when doing jump dest caching
-		program  *Program
-	)
+	codehash := contract.CodeHash // codehash is used when doing jump dest caching
+	if codehash == (common.Hash{}) {
+		codehash = crypto.Keccak256Hash(contract.Code)
+	}
+	var program *Program
 	if evm.cfg.EnableJit {
 		// If the JIT is enabled check the status of the JIT program,
 		// if it doesn't exist compile a new program in a separate
diff --git a/internal/ethapi/tracer_test.go b/internal/ethapi/tracer_test.go
index 301ff48404b5b4bdd8c87fd8d5865cd248443946..7c831d29903612483202c6fe03a76325fab4c374 100644
--- a/internal/ethapi/tracer_test.go
+++ b/internal/ethapi/tracer_test.go
@@ -93,7 +93,7 @@ func (account) SetNonce(uint64)                                     {}
 func (account) Balance() *big.Int                                   { return nil }
 func (account) Address() common.Address                             { return common.Address{} }
 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 runTrace(tracer *JavascriptTracer) (interface{}, error) {
diff --git a/light/state_test.go b/light/state_test.go
index d7014a2dcc88079a98d5c448b6b767c9e68fffe5..d4fe9502298b96fd727d1f2565ca892d9679a76b 100644
--- a/light/state_test.go
+++ b/light/state_test.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/state"
+	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
 	"github.com/ethereum/go-ethereum/trie"
 	"golang.org/x/net/context"
@@ -60,7 +61,7 @@ func makeTestState() (common.Hash, ethdb.Database) {
 			so.SetNonce(100)
 		}
 		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)
 		st.UpdateStateObject(so)
 	}
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index 7da15cebe3a15d68b298ca658dacbe355b820309..7096b866d497043d0ddf3f966d281747cdebec28 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -31,6 +31,7 @@ import (
 	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/core/state"
 	"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/logger/glog"
@@ -219,7 +220,7 @@ func (t *BlockTest) InsertPreState(db ethdb.Database) (*state.StateDB, error) {
 			return nil, err
 		}
 		obj := statedb.CreateAccount(common.HexToAddress(addrString))
-		obj.SetCode(code)
+		obj.SetCode(crypto.Keccak256Hash(code), code)
 		obj.SetBalance(balance)
 		obj.SetNonce(nonce)
 		for k, v := range acct.Storage {
diff --git a/tests/util.go b/tests/util.go
index 08fac2dd1b6920b32047f0a4c1a00b51cf37a94a..ffbcb9d56d690811afbe2a02f0821cdfb979823c 100644
--- a/tests/util.go
+++ b/tests/util.go
@@ -108,12 +108,13 @@ func StateObjectFromAccount(db ethdb.Database, addr string, account Account, onD
 		account.Code = account.Code[2:]
 	}
 	code := common.Hex2Bytes(account.Code)
+	codeHash := crypto.Keccak256Hash(code)
 	obj := state.NewObject(common.HexToAddress(addr), state.Account{
 		Balance:  common.Big(account.Balance),
-		CodeHash: crypto.Keccak256(code),
+		CodeHash: codeHash[:],
 		Nonce:    common.Big(account.Nonce).Uint64(),
 	}, onDirty)
-	obj.SetCode(code)
+	obj.SetCode(codeHash, code)
 	return obj
 }