From ecb781297bfc891f4ff26bdf3fda362744bbb3e3 Mon Sep 17 00:00:00 2001
From: Martin Holst Swende <martin@swende.se>
Date: Thu, 24 Jan 2019 11:36:30 +0100
Subject: [PATCH] core, cmd/puppeth: implement constantinople fix, disable
 EIP-1283 (#18486)

This PR adds a new fork which disables EIP-1283. Internally it's called Petersburg,
but the genesis/config field is ConstantinopleFix.

The block numbers are:

    7280000 for Constantinople on Mainnet
    7280000 for ConstantinopleFix on Mainnet
    4939394 for ConstantinopleFix on Ropsten
    9999999 for ConstantinopleFix on Rinkeby (real number decided later)

This PR also defaults to using the same ConstantinopleFix number as whatever
Constantinople is set to. That is, it will default to mainnet behaviour if ConstantinopleFix
is not set.This means that for private networks which have already transitioned
to Constantinople, this PR will break the network unless ConstantinopleFix is
explicitly set!
---
 cmd/puppeth/genesis.go          | 54 +++++++++++++++++++--------------
 cmd/puppeth/module_dashboard.go | 49 +++++++++++++++---------------
 cmd/puppeth/wizard_genesis.go   |  4 +++
 core/genesis.go                 |  1 +
 core/vm/gas_table.go            |  4 ++-
 core/vm/logger_json.go          |  6 +++-
 params/config.go                | 32 ++++++++++++++-----
 tests/init.go                   | 12 ++++++++
 tests/rlp_test_util.go          | 15 ++++++++-
 tests/state_test.go             | 21 ++++++++-----
 tests/testdata                  |  2 +-
 11 files changed, 134 insertions(+), 66 deletions(-)

diff --git a/cmd/puppeth/genesis.go b/cmd/puppeth/genesis.go
index c95c81a6d..ae7675cd9 100644
--- a/cmd/puppeth/genesis.go
+++ b/cmd/puppeth/genesis.go
@@ -223,28 +223,29 @@ type parityChainSpec struct {
 	} `json:"engine"`
 
 	Params struct {
-		AccountStartNonce     hexutil.Uint64       `json:"accountStartNonce"`
-		MaximumExtraDataSize  hexutil.Uint64       `json:"maximumExtraDataSize"`
-		MinGasLimit           hexutil.Uint64       `json:"minGasLimit"`
-		GasLimitBoundDivisor  math2.HexOrDecimal64 `json:"gasLimitBoundDivisor"`
-		NetworkID             hexutil.Uint64       `json:"networkID"`
-		ChainID               hexutil.Uint64       `json:"chainID"`
-		MaxCodeSize           hexutil.Uint64       `json:"maxCodeSize"`
-		MaxCodeSizeTransition hexutil.Uint64       `json:"maxCodeSizeTransition"`
-		EIP98Transition       hexutil.Uint64       `json:"eip98Transition"`
-		EIP150Transition      hexutil.Uint64       `json:"eip150Transition"`
-		EIP160Transition      hexutil.Uint64       `json:"eip160Transition"`
-		EIP161abcTransition   hexutil.Uint64       `json:"eip161abcTransition"`
-		EIP161dTransition     hexutil.Uint64       `json:"eip161dTransition"`
-		EIP155Transition      hexutil.Uint64       `json:"eip155Transition"`
-		EIP140Transition      hexutil.Uint64       `json:"eip140Transition"`
-		EIP211Transition      hexutil.Uint64       `json:"eip211Transition"`
-		EIP214Transition      hexutil.Uint64       `json:"eip214Transition"`
-		EIP658Transition      hexutil.Uint64       `json:"eip658Transition"`
-		EIP145Transition      hexutil.Uint64       `json:"eip145Transition"`
-		EIP1014Transition     hexutil.Uint64       `json:"eip1014Transition"`
-		EIP1052Transition     hexutil.Uint64       `json:"eip1052Transition"`
-		EIP1283Transition     hexutil.Uint64       `json:"eip1283Transition"`
+		AccountStartNonce        hexutil.Uint64       `json:"accountStartNonce"`
+		MaximumExtraDataSize     hexutil.Uint64       `json:"maximumExtraDataSize"`
+		MinGasLimit              hexutil.Uint64       `json:"minGasLimit"`
+		GasLimitBoundDivisor     math2.HexOrDecimal64 `json:"gasLimitBoundDivisor"`
+		NetworkID                hexutil.Uint64       `json:"networkID"`
+		ChainID                  hexutil.Uint64       `json:"chainID"`
+		MaxCodeSize              hexutil.Uint64       `json:"maxCodeSize"`
+		MaxCodeSizeTransition    hexutil.Uint64       `json:"maxCodeSizeTransition"`
+		EIP98Transition          hexutil.Uint64       `json:"eip98Transition"`
+		EIP150Transition         hexutil.Uint64       `json:"eip150Transition"`
+		EIP160Transition         hexutil.Uint64       `json:"eip160Transition"`
+		EIP161abcTransition      hexutil.Uint64       `json:"eip161abcTransition"`
+		EIP161dTransition        hexutil.Uint64       `json:"eip161dTransition"`
+		EIP155Transition         hexutil.Uint64       `json:"eip155Transition"`
+		EIP140Transition         hexutil.Uint64       `json:"eip140Transition"`
+		EIP211Transition         hexutil.Uint64       `json:"eip211Transition"`
+		EIP214Transition         hexutil.Uint64       `json:"eip214Transition"`
+		EIP658Transition         hexutil.Uint64       `json:"eip658Transition"`
+		EIP145Transition         hexutil.Uint64       `json:"eip145Transition"`
+		EIP1014Transition        hexutil.Uint64       `json:"eip1014Transition"`
+		EIP1052Transition        hexutil.Uint64       `json:"eip1052Transition"`
+		EIP1283Transition        hexutil.Uint64       `json:"eip1283Transition"`
+		EIP1283DisableTransition hexutil.Uint64       `json:"eip1283DisableTransition"`
 	} `json:"params"`
 
 	Genesis struct {
@@ -347,6 +348,11 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
 	if num := genesis.Config.ConstantinopleBlock; num != nil {
 		spec.setConstantinople(num)
 	}
+	// ConstantinopleFix (remove eip-1283)
+	if num := genesis.Config.PetersburgBlock; num != nil {
+		spec.setConstantinopleFix(num)
+	}
+
 	spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
 	spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
 	spec.Params.GasLimitBoundDivisor = (math2.HexOrDecimal64)(params.GasLimitBoundDivisor)
@@ -441,6 +447,10 @@ func (spec *parityChainSpec) setConstantinople(num *big.Int) {
 	spec.Params.EIP1283Transition = n
 }
 
+func (spec *parityChainSpec) setConstantinopleFix(num *big.Int) {
+	spec.Params.EIP1283DisableTransition = hexutil.Uint64(num.Uint64())
+}
+
 // pyEthereumGenesisSpec represents the genesis specification format used by the
 // Python Ethereum implementation.
 type pyEthereumGenesisSpec struct {
diff --git a/cmd/puppeth/module_dashboard.go b/cmd/puppeth/module_dashboard.go
index cb3ed6e71..9a77587b4 100644
--- a/cmd/puppeth/module_dashboard.go
+++ b/cmd/puppeth/module_dashboard.go
@@ -608,30 +608,31 @@ func deployDashboard(client *sshClient, network string, conf *config, config *da
 		bootPython[i] = "'" + boot + "'"
 	}
 	template.Must(template.New("").Parse(dashboardContent)).Execute(indexfile, map[string]interface{}{
-		"Network":          network,
-		"NetworkID":        conf.Genesis.Config.ChainID,
-		"NetworkTitle":     strings.Title(network),
-		"EthstatsPage":     config.ethstats,
-		"ExplorerPage":     config.explorer,
-		"WalletPage":       config.wallet,
-		"FaucetPage":       config.faucet,
-		"GethGenesis":      network + ".json",
-		"Bootnodes":        conf.bootnodes,
-		"BootnodesFlat":    strings.Join(conf.bootnodes, ","),
-		"Ethstats":         statsLogin,
-		"Ethash":           conf.Genesis.Config.Ethash != nil,
-		"CppGenesis":       network + "-cpp.json",
-		"CppBootnodes":     strings.Join(bootCpp, " "),
-		"HarmonyGenesis":   network + "-harmony.json",
-		"HarmonyBootnodes": strings.Join(bootHarmony, " "),
-		"ParityGenesis":    network + "-parity.json",
-		"PythonGenesis":    network + "-python.json",
-		"PythonBootnodes":  strings.Join(bootPython, ","),
-		"Homestead":        conf.Genesis.Config.HomesteadBlock,
-		"Tangerine":        conf.Genesis.Config.EIP150Block,
-		"Spurious":         conf.Genesis.Config.EIP155Block,
-		"Byzantium":        conf.Genesis.Config.ByzantiumBlock,
-		"Constantinople":   conf.Genesis.Config.ConstantinopleBlock,
+		"Network":           network,
+		"NetworkID":         conf.Genesis.Config.ChainID,
+		"NetworkTitle":      strings.Title(network),
+		"EthstatsPage":      config.ethstats,
+		"ExplorerPage":      config.explorer,
+		"WalletPage":        config.wallet,
+		"FaucetPage":        config.faucet,
+		"GethGenesis":       network + ".json",
+		"Bootnodes":         conf.bootnodes,
+		"BootnodesFlat":     strings.Join(conf.bootnodes, ","),
+		"Ethstats":          statsLogin,
+		"Ethash":            conf.Genesis.Config.Ethash != nil,
+		"CppGenesis":        network + "-cpp.json",
+		"CppBootnodes":      strings.Join(bootCpp, " "),
+		"HarmonyGenesis":    network + "-harmony.json",
+		"HarmonyBootnodes":  strings.Join(bootHarmony, " "),
+		"ParityGenesis":     network + "-parity.json",
+		"PythonGenesis":     network + "-python.json",
+		"PythonBootnodes":   strings.Join(bootPython, ","),
+		"Homestead":         conf.Genesis.Config.HomesteadBlock,
+		"Tangerine":         conf.Genesis.Config.EIP150Block,
+		"Spurious":          conf.Genesis.Config.EIP155Block,
+		"Byzantium":         conf.Genesis.Config.ByzantiumBlock,
+		"Constantinople":    conf.Genesis.Config.ConstantinopleBlock,
+		"ConstantinopleFix": conf.Genesis.Config.PetersburgBlock,
 	})
 	files[filepath.Join(workdir, "index.html")] = indexfile.Bytes()
 
diff --git a/cmd/puppeth/wizard_genesis.go b/cmd/puppeth/wizard_genesis.go
index 95da5bd4f..8abfe7c41 100644
--- a/cmd/puppeth/wizard_genesis.go
+++ b/cmd/puppeth/wizard_genesis.go
@@ -223,6 +223,10 @@ func (w *wizard) manageGenesis() {
 		fmt.Printf("Which block should Constantinople come into effect? (default = %v)\n", w.conf.Genesis.Config.ConstantinopleBlock)
 		w.conf.Genesis.Config.ConstantinopleBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ConstantinopleBlock)
 
+		fmt.Println()
+		fmt.Printf("Which block should Constantinople-Fix (remove EIP-1283) come into effect? (default = %v)\n", w.conf.Genesis.Config.ConstantinopleBlock)
+		w.conf.Genesis.Config.PetersburgBlock = w.readDefaultBigInt(w.conf.Genesis.Config.ConstantinopleBlock)
+
 		out, _ := json.MarshalIndent(w.conf.Genesis.Config, "", "  ")
 		fmt.Printf("Chain configuration updated:\n\n%s\n", out)
 
diff --git a/core/genesis.go b/core/genesis.go
index c96cb17a3..62cde87b5 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -183,6 +183,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, constant
 	newcfg := genesis.configOrDefault(stored)
 	if constantinopleOverride != nil {
 		newcfg.ConstantinopleBlock = constantinopleOverride
+		newcfg.PetersburgBlock = constantinopleOverride
 	}
 	storedcfg := rawdb.ReadChainConfig(db, stored)
 	if storedcfg == nil {
diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go
index df79f86ec..9203e10a7 100644
--- a/core/vm/gas_table.go
+++ b/core/vm/gas_table.go
@@ -121,7 +121,9 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
 		current = evm.StateDB.GetState(contract.Address(), common.BigToHash(x))
 	)
 	// The legacy gas metering only takes into consideration the current state
-	if !evm.chainRules.IsConstantinople {
+	// Legacy rules should be applied if we are in Petersburg (removal of EIP-1283)
+	// OR Constantinople is not active
+	if evm.chainRules.IsPetersburg || !evm.chainRules.IsConstantinople {
 		// This checks for 3 scenario's and calculates gas accordingly:
 		//
 		// 1. From a zero-value address to a non-zero value         (NEW VALUE)
diff --git a/core/vm/logger_json.go b/core/vm/logger_json.go
index ac3c40759..ff379a4ef 100644
--- a/core/vm/logger_json.go
+++ b/core/vm/logger_json.go
@@ -34,7 +34,11 @@ type JSONLogger struct {
 // NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
 // into the provided stream.
 func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger {
-	return &JSONLogger{json.NewEncoder(writer), cfg}
+	l := &JSONLogger{json.NewEncoder(writer), cfg}
+	if l.cfg == nil {
+		l.cfg = &LogConfig{}
+	}
+	return l
 }
 
 func (l *JSONLogger) CaptureStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) error {
diff --git a/params/config.go b/params/config.go
index fefc16106..cadf4e933 100644
--- a/params/config.go
+++ b/params/config.go
@@ -42,7 +42,8 @@ var (
 		EIP155Block:         big.NewInt(2675000),
 		EIP158Block:         big.NewInt(2675000),
 		ByzantiumBlock:      big.NewInt(4370000),
-		ConstantinopleBlock: nil,
+		ConstantinopleBlock: big.NewInt(7280000),
+		PetersburgBlock:     big.NewInt(7280000),
 		Ethash:              new(EthashConfig),
 	}
 
@@ -67,6 +68,7 @@ var (
 		EIP158Block:         big.NewInt(10),
 		ByzantiumBlock:      big.NewInt(1700000),
 		ConstantinopleBlock: big.NewInt(4230000),
+		PetersburgBlock:     big.NewInt(4939394),
 		Ethash:              new(EthashConfig),
 	}
 
@@ -91,6 +93,7 @@ var (
 		EIP158Block:         big.NewInt(3),
 		ByzantiumBlock:      big.NewInt(1035301),
 		ConstantinopleBlock: big.NewInt(3660663),
+		PetersburgBlock:     big.NewInt(9999999), //TODO! Insert Rinkeby block number
 		Clique: &CliqueConfig{
 			Period: 15,
 			Epoch:  30000,
@@ -111,16 +114,16 @@ var (
 	//
 	// This configuration is intentionally not using keyed fields to force anyone
 	// adding flags to the config to also have to set these fields.
-	AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
+	AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
 
 	// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
 	// and accepted by the Ethereum core developers into the Clique consensus.
 	//
 	// This configuration is intentionally not using keyed fields to force anyone
 	// adding flags to the config to also have to set these fields.
-	AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
+	AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
 
-	TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
+	TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil}
 	TestRules       = TestChainConfig.Rules(new(big.Int))
 )
 
@@ -158,6 +161,7 @@ type ChainConfig struct {
 
 	ByzantiumBlock      *big.Int `json:"byzantiumBlock,omitempty"`      // Byzantium switch block (nil = no fork, 0 = already on byzantium)
 	ConstantinopleBlock *big.Int `json:"constantinopleBlock,omitempty"` // Constantinople switch block (nil = no fork, 0 = already activated)
+	PetersburgBlock     *big.Int `json:"petersburgBlock,omitempty"`     // Petersburg switch block (nil = same as Constantinople)
 	EWASMBlock          *big.Int `json:"ewasmBlock,omitempty"`          // EWASM switch block (nil = no fork, 0 = already activated)
 
 	// Various consensus engines
@@ -195,7 +199,7 @@ func (c *ChainConfig) String() string {
 	default:
 		engine = "unknown"
 	}
-	return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Engine: %v}",
+	return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v  ConstantinopleFix: %v Engine: %v}",
 		c.ChainID,
 		c.HomesteadBlock,
 		c.DAOForkBlock,
@@ -205,6 +209,7 @@ func (c *ChainConfig) String() string {
 		c.EIP158Block,
 		c.ByzantiumBlock,
 		c.ConstantinopleBlock,
+		c.PetersburgBlock,
 		engine,
 	)
 }
@@ -244,6 +249,13 @@ func (c *ChainConfig) IsConstantinople(num *big.Int) bool {
 	return isForked(c.ConstantinopleBlock, num)
 }
 
+// IsPetersburg returns whether num is either
+// - equal to or greater than the PetersburgBlock fork block,
+// - OR is nil, and Constantinople is active
+func (c *ChainConfig) IsPetersburg(num *big.Int) bool {
+	return isForked(c.PetersburgBlock, num) || c.PetersburgBlock == nil && isForked(c.ConstantinopleBlock, num)
+}
+
 // IsEWASM returns whether num represents a block number after the EWASM fork
 func (c *ChainConfig) IsEWASM(num *big.Int) bool {
 	return isForked(c.EWASMBlock, num)
@@ -314,6 +326,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
 	if isForkIncompatible(c.ConstantinopleBlock, newcfg.ConstantinopleBlock, head) {
 		return newCompatError("Constantinople fork block", c.ConstantinopleBlock, newcfg.ConstantinopleBlock)
 	}
+	if isForkIncompatible(c.PetersburgBlock, newcfg.PetersburgBlock, head) {
+		return newCompatError("ConstantinopleFix fork block", c.PetersburgBlock, newcfg.PetersburgBlock)
+	}
 	if isForkIncompatible(c.EWASMBlock, newcfg.EWASMBlock, head) {
 		return newCompatError("ewasm fork block", c.EWASMBlock, newcfg.EWASMBlock)
 	}
@@ -381,9 +396,9 @@ func (err *ConfigCompatError) Error() string {
 // Rules is a one time interface meaning that it shouldn't be used in between transition
 // phases.
 type Rules struct {
-	ChainID                                   *big.Int
-	IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
-	IsByzantium, IsConstantinople             bool
+	ChainID                                     *big.Int
+	IsHomestead, IsEIP150, IsEIP155, IsEIP158   bool
+	IsByzantium, IsConstantinople, IsPetersburg bool
 }
 
 // Rules ensures c's ChainID is not nil.
@@ -400,5 +415,6 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
 		IsEIP158:         c.IsEIP158(num),
 		IsByzantium:      c.IsByzantium(num),
 		IsConstantinople: c.IsConstantinople(num),
+		IsPetersburg:     c.IsPetersburg(num),
 	}
 }
diff --git a/tests/init.go b/tests/init.go
index db0457b6d..188cdffe9 100644
--- a/tests/init.go
+++ b/tests/init.go
@@ -62,6 +62,18 @@ var Forks = map[string]*params.ChainConfig{
 		DAOForkBlock:        big.NewInt(0),
 		ByzantiumBlock:      big.NewInt(0),
 		ConstantinopleBlock: big.NewInt(0),
+		PetersburgBlock:     big.NewInt(10000000),
+	},
+	"ConstantinopleFix": {
+		ChainID:             big.NewInt(1),
+		HomesteadBlock:      big.NewInt(0),
+		EIP150Block:         big.NewInt(0),
+		EIP155Block:         big.NewInt(0),
+		EIP158Block:         big.NewInt(0),
+		DAOForkBlock:        big.NewInt(0),
+		ByzantiumBlock:      big.NewInt(0),
+		ConstantinopleBlock: big.NewInt(0),
+		PetersburgBlock:     big.NewInt(0),
 	},
 	"FrontierToHomesteadAt5": {
 		ChainID:        big.NewInt(1),
diff --git a/tests/rlp_test_util.go b/tests/rlp_test_util.go
index 58ef8a642..9069ec55a 100644
--- a/tests/rlp_test_util.go
+++ b/tests/rlp_test_util.go
@@ -42,9 +42,22 @@ type RLPTest struct {
 	Out string
 }
 
+// FromHex returns the bytes represented by the hexadecimal string s.
+// s may be prefixed with "0x".
+// This is copy-pasted from bytes.go, which does not return the error
+func FromHex(s string) ([]byte, error) {
+	if len(s) > 1 && (s[0:2] == "0x" || s[0:2] == "0X") {
+		s = s[2:]
+	}
+	if len(s)%2 == 1 {
+		s = "0" + s
+	}
+	return hex.DecodeString(s)
+}
+
 // Run executes the test.
 func (t *RLPTest) Run() error {
-	outb, err := hex.DecodeString(t.Out)
+	outb, err := FromHex(t.Out)
 	if err != nil {
 		return fmt.Errorf("invalid hex in Out")
 	}
diff --git a/tests/state_test.go b/tests/state_test.go
index 964405382..8b69da91f 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -17,6 +17,7 @@
 package tests
 
 import (
+	"bufio"
 	"bytes"
 	"flag"
 	"fmt"
@@ -45,9 +46,12 @@ func TestState(t *testing.T) {
 	st.skipLoad(`^stTransactionTest/OverflowGasRequire\.json`) // gasLimit > 256 bits
 	st.skipLoad(`^stTransactionTest/zeroSigTransa[^/]*\.json`) // EIP-86 is not supported yet
 	// Expected failures:
-	st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/EIP158`, "bug in test")
-	st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test")
-	st.fails(`^stRevertTest/RevertPrecompiledTouch.json/Constantinople`, "bug in test")
+	st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/0`, "bug in test")
+	st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/3`, "bug in test")
+	st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Constantinople/0`, "bug in test")
+	st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Constantinople/3`, "bug in test")
+	st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/ConstantinopleFix/0`, "bug in test")
+	st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/ConstantinopleFix/3`, "bug in test")
 
 	st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) {
 		for _, subtest := range test.Subtests() {
@@ -86,18 +90,19 @@ func withTrace(t *testing.T, gasLimit uint64, test func(vm.Config) error) {
 		t.Log("gas limit too high for EVM trace")
 		return
 	}
-	tracer := vm.NewStructLogger(nil)
+	buf := new(bytes.Buffer)
+	w := bufio.NewWriter(buf)
+	tracer := vm.NewJSONLogger(&vm.LogConfig{DisableMemory: true}, w)
 	err2 := test(vm.Config{Debug: true, Tracer: tracer})
 	if !reflect.DeepEqual(err, err2) {
 		t.Errorf("different error for second run: %v", err2)
 	}
-	buf := new(bytes.Buffer)
-	vm.WriteTrace(buf, tracer.StructLogs())
+	w.Flush()
 	if buf.Len() == 0 {
 		t.Log("no EVM operation logs generated")
 	} else {
 		t.Log("EVM operation log:\n" + buf.String())
 	}
-	t.Logf("EVM output: 0x%x", tracer.Output())
-	t.Logf("EVM error: %v", tracer.Error())
+	//t.Logf("EVM output: 0x%x", tracer.Output())
+	//t.Logf("EVM error: %v", tracer.Error())
 }
diff --git a/tests/testdata b/tests/testdata
index c02a2a17c..6b85703b5 160000
--- a/tests/testdata
+++ b/tests/testdata
@@ -1 +1 @@
-Subproject commit c02a2a17c0288a255572b37dc7ec1fcb838b9dbf
+Subproject commit 6b85703b568f4456582a00665d8a3e5c3b20b484
-- 
GitLab