diff --git a/core/state/database_test.go b/core/state/database_test.go
index 811a7b1bdf84e226e30b63b87cb7a99e9bbbc905..3fbe6c941a3366e8faf4100fe284f1ec8eb1d580 100644
--- a/core/state/database_test.go
+++ b/core/state/database_test.go
@@ -484,3 +484,93 @@ func TestReproduceCrash(t *testing.T) {
 		t.Errorf("Expected empty list of prunables, got:\n %s", prunables)
 	}
 }
+func TestEip2200Gas(t *testing.T) {
+	// Configure and generate a sample block chain
+	var (
+		db      = ethdb.NewMemDatabase()
+		key, _  = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+		address = crypto.PubkeyToAddress(key.PublicKey)
+		funds   = big.NewInt(1000000000)
+		gspec   = &core.Genesis{
+			Config: &params.ChainConfig{
+				ChainID:             big.NewInt(1),
+				HomesteadBlock:      new(big.Int),
+				EIP150Block:         new(big.Int),
+				EIP155Block:         new(big.Int),
+				EIP158Block:         big.NewInt(1),
+				ByzantiumBlock:      big.NewInt(1),
+				PetersburgBlock:     big.NewInt(1),
+				ConstantinopleBlock: big.NewInt(1),
+				IstanbulBlock:       big.NewInt(1),
+			},
+			Alloc: core.GenesisAlloc{
+				address: {Balance: funds},
+			},
+		}
+		genesis = gspec.MustCommit(db)
+	)
+
+	engine := ethash.NewFaker()
+	blockchain, err := core.NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	blockchain.EnableReceipts(true)
+
+	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
+	transactOpts := bind.NewKeyedTransactor(key)
+	transactOpts.GasLimit = 1000000
+
+	var contractAddress common.Address
+	var selfDestruct *contracts.Selfdestruct
+
+	ctx := blockchain.WithContext(context.Background(), big.NewInt(genesis.Number().Int64()+1))
+	// Here we generate 1 block with 2 transactions, first creates a contract with some initial values in the
+	// It activates the SSTORE pricing rules specific to EIP-2200 (istanbul)
+	blocks, _ := core.GenerateChain(ctx, gspec.Config, genesis, engine, db.MemCopy(), 3, func(i int, block *core.BlockGen) {
+		var tx *types.Transaction
+
+		switch i {
+		case 0:
+			contractAddress, tx, selfDestruct, err = contracts.DeploySelfdestruct(transactOpts, contractBackend)
+			if err != nil {
+				t.Fatal(err)
+			}
+			block.AddTx(tx)
+
+			transactOpts.GasPrice = big.NewInt(1)
+			tx, err = selfDestruct.Change(transactOpts)
+			if err != nil {
+				t.Fatal(err)
+			}
+			block.AddTx(tx)
+		}
+		contractBackend.Commit()
+	})
+
+	st, _, _ := blockchain.State()
+	if !st.Exist(address) {
+		t.Error("expected account to exist")
+	}
+	if st.Exist(contractAddress) {
+		t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
+	}
+	balanceBefore := st.GetBalance(address)
+
+	// BLOCK 1
+	if _, err = blockchain.InsertChain(types.Blocks{blocks[0]}); err != nil {
+		t.Fatal(err)
+	}
+
+	st, _, _ = blockchain.State()
+	if !st.Exist(contractAddress) {
+		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+	}
+	balanceAfter := st.GetBalance(address)
+	gasSpent := big.NewInt(0).Sub(balanceBefore, balanceAfter)
+	expectedGasSpent := big.NewInt(192245) // In the incorrect version, it is 179645
+	if gasSpent.Cmp(expectedGasSpent) != 0 {
+		t.Errorf("Expected gas spent: %d, got %d", expectedGasSpent, gasSpent)
+	}
+}
diff --git a/core/state/state_object.go b/core/state/state_object.go
index e88c962c087f8cdad916009bcdeb6094c7e2682f..019fc0e2f1fb3f51831c27881b496b3350409627 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -81,7 +81,6 @@ type stateObject struct {
 	code Code // contract bytecode, which gets set when code is loaded
 
 	originStorage      Storage // Storage cache of original entries to dedup rewrites
-	pendingStorage     Storage // Storage entries that need to be flushed to disk, at the end of an entire block
 	blockOriginStorage Storage
 	dirtyStorage       Storage // Storage entries that need to be flushed to disk
 	fakeStorage        Storage // Fake storage which constructed by caller for debugging purpose.
@@ -109,7 +108,6 @@ func newObject(db *IntraBlockState, address common.Address, data, original *acco
 		db:                 db,
 		address:            address,
 		originStorage:      make(Storage),
-		pendingStorage:     make(Storage),
 		blockOriginStorage: make(Storage),
 		dirtyStorage:       make(Storage),
 	}
@@ -168,9 +166,6 @@ func (so *stateObject) GetState(key common.Hash) common.Hash {
 
 // GetCommittedState retrieves a value from the committed account storage trie.
 func (so *stateObject) GetCommittedState(key common.Hash) common.Hash {
-	if so.created {
-		return common.Hash{}
-	}
 	// If we have the original value cached, return that
 	{
 		value, cached := so.originStorage[key]
@@ -178,6 +173,9 @@ func (so *stateObject) GetCommittedState(key common.Hash) common.Hash {
 			return value
 		}
 	}
+	if so.created {
+		return common.Hash{}
+	}
 	// Load from DB in case it is missing.
 	enc, err := so.db.stateReader.ReadAccountStorage(so.address, so.data.GetIncarnation(), &key)
 	if err != nil {
@@ -231,17 +229,6 @@ func (so *stateObject) setState(key, value common.Hash) {
 	so.dirtyStorage[key] = value
 }
 
-// finalise moves all dirty storage slots into the pending area to be hashed or
-// committed later. It is invoked at the end of every transaction.
-func (so *stateObject) finalise() {
-	for key, value := range so.dirtyStorage {
-		so.pendingStorage[key] = value
-	}
-	if len(so.dirtyStorage) > 0 {
-		so.dirtyStorage = make(Storage)
-	}
-}
-
 // updateTrie writes cached storage modifications into the object's storage trie.
 func (so *stateObject) updateTrie(ctx context.Context, stateWriter StateWriter) error {
 	for key, value := range so.dirtyStorage {
diff --git a/core/state_processor.go b/core/state_processor.go
index 4cf4d81be0b53e7ffea07aed6c141e7757300c0c..0acb49ad5928a867beabd0e94674d52a5b42d5ec 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -17,9 +17,9 @@
 package core
 
 import (
-	//"os"
-	//"encoding/json"
-	//"bytes"
+	"bytes"
+	"encoding/json"
+	"os"
 
 	"fmt"
 
@@ -41,9 +41,10 @@ import (
 //
 // StateProcessor implements Processor.
 type StateProcessor struct {
-	config *params.ChainConfig // Chain configuration options
-	bc     *BlockChain         // Canonical block chain
-	engine consensus.Engine    // Consensus engine used for block rewards
+	config      *params.ChainConfig // Chain configuration options
+	bc          *BlockChain         // Canonical block chain
+	engine      consensus.Engine    // Consensus engine used for block rewards
+	txTraceHash []byte              // Hash of the transaction to trace (or nil if there nothing to trace)
 }
 
 // NewStateProcessor initialises a new StateProcessor.
@@ -55,6 +56,11 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen
 	}
 }
 
+// SetTxTraceHash allows setting the hash of the transaction to trace
+func (p *StateProcessor) SetTxTraceHash(txTraceHash common.Hash) {
+	p.txTraceHash = txTraceHash[:]
+}
+
 // StructLogRes stores a structured log emitted by the EVM while replaying a
 // transaction in debug mode
 type StructLogRes struct {
@@ -69,7 +75,7 @@ type StructLogRes struct {
 	Storage *map[string]string `json:"storage,omitempty"`
 }
 
-// formatLogs formats EVM returned structured logs for json output
+// FormatLogs formats EVM returned structured logs for json output
 func FormatLogs(logs []vm.StructLog) []StructLogRes {
 	formatted := make([]StructLogRes, len(logs))
 	for index, trace := range logs {
@@ -128,8 +134,39 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.IntraBlockSt
 	// Iterate over and process the individual transactions
 	tds.StartNewBuffer()
 	for i, tx := range block.Transactions() {
-		statedb.Prepare(tx.Hash(), block.Hash(), i)
+		txHash := tx.Hash()
+		statedb.Prepare(txHash, block.Hash(), i)
+		writeTrace := false
+		if !cfg.Debug && p.txTraceHash != nil && bytes.Equal(p.txTraceHash, txHash[:]) {
+			// This code is useful when debugging a certain transaction. If uncommented, together with the code
+			// at the end of this function, after the execution of transaction with given hash, the file
+			// structlogs.txt will contain full trace of the transactin in JSON format. This can be compared
+			// to another trace, obtained from the correct version of the turbo-geth or go-ethereum
+			cfg.Tracer = vm.NewStructLogger(&vm.LogConfig{})
+			cfg.Debug = true
+			writeTrace = true
+		}
 		receipt, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, tds.TrieStateWriter(), header, tx, usedGas, cfg)
+		// This code is useful when debugging a certain transaction. If uncommented, together with the code
+		// at the end of this function, after the execution of transaction with given hash, the file
+		// structlogs.txt will contain full trace of the transactin in JSON format. This can be compared
+		// to another trace, obtained from the correct version of the turbo-geth or go-ethereum
+		if writeTrace {
+			w, err1 := os.Create(fmt.Sprintf("txtrace_%x.txt", p.txTraceHash))
+			if err1 != nil {
+				panic(err1)
+			}
+			encoder := json.NewEncoder(w)
+			logs := FormatLogs(cfg.Tracer.(*vm.StructLogger).StructLogs())
+			if err2 := encoder.Encode(logs); err2 != nil {
+				panic(err2)
+			}
+			if err2 := w.Close(); err2 != nil {
+				panic(err2)
+			}
+			cfg.Debug = false
+			cfg.Tracer = nil
+		}
 		if err != nil {
 			return nil, nil, 0, err
 		}
@@ -163,17 +200,6 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.IntraBlockSt
 // for the transaction, gas used and an error if the transaction failed,
 // indicating the block was invalid.
 func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.IntraBlockState, stateWriter state.StateWriter, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) {
-	/*
-		// This code is useful when debugging a certain transaction. If uncommented, together with the code
-		// at the end of this function, after the execution of transaction with given hash, the file
-		// structlogs.txt will contain full trace of the transactin in JSON format. This can be compared
-		// to another trace, obtained from the correct version of the turbo-geth or go-ethereum
-		var h common.Hash = tx.Hash()
-		if bytes.Equal(h[:], common.FromHex("0x340acfd967a744646ebdcfa2cab9b457a1d42224598d33051047ededdd24caa1")) {
-			cfg.Tracer = vm.NewStructLogger(&vm.LogConfig{})
-			cfg.Debug = true
-		}
-	*/
 	msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
 	if err != nil {
 		return nil, err
@@ -186,28 +212,6 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
 	vmenv := vm.NewEVM(context, statedb, config, cfg)
 	// Apply the transaction to the current state (included in the env)
 	_, gas, failed, err := ApplyMessage(vmenv, msg, gp)
-	/*
-		// This code is useful when debugging a certain transaction. If uncommented, together with the code
-		// at the end of this function, after the execution of transaction with given hash, the file
-		// structlogs.txt will contain full trace of the transactin in JSON format. This can be compared
-		// to another trace, obtained from the correct version of the turbo-geth or go-ethereum
-		if cfg.Tracer != nil {
-			w, err := os.Create("structlogs.txt")
-			if err != nil {
-				panic(err)
-			}
-			encoder := json.NewEncoder(w)
-			logs := FormatLogs(cfg.Tracer.(*vm.StructLogger).StructLogs())
-			if err := encoder.Encode(logs); err != nil {
-				panic(err)
-			}
-			if err := w.Close(); err != nil {
-				panic(err)
-			}
-			cfg.Debug = false
-			cfg.Tracer = nil
-		}
-	*/
 	if err != nil {
 		return nil, err
 	}