From a660685746db17a41cd67b05c614cdb29e49340c Mon Sep 17 00:00:00 2001
From: Martin Holst Swende <martin@swende.se>
Date: Wed, 27 Sep 2017 15:30:41 +0200
Subject: [PATCH] tests: add ethash difficulty tests (#15191)

---
 tests/difficulty_test.go      | 87 +++++++++++++++++++++++++++++++++++
 tests/difficulty_test_util.go | 70 ++++++++++++++++++++++++++++
 tests/gen_difficultytest.go   | 66 ++++++++++++++++++++++++++
 tests/init_test.go            |  1 +
 tests/state_test.go           | 18 ++++----
 tests/testdata                |  2 +-
 6 files changed, 235 insertions(+), 9 deletions(-)
 create mode 100644 tests/difficulty_test.go
 create mode 100644 tests/difficulty_test_util.go
 create mode 100644 tests/gen_difficultytest.go

diff --git a/tests/difficulty_test.go b/tests/difficulty_test.go
new file mode 100644
index 000000000..a449b1cfa
--- /dev/null
+++ b/tests/difficulty_test.go
@@ -0,0 +1,87 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+//
+
+package tests
+
+import (
+	"testing"
+
+	"math/big"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/params"
+)
+
+var (
+	mainnetChainConfig = params.ChainConfig{
+		ChainId:        big.NewInt(1),
+		HomesteadBlock: big.NewInt(1150000),
+		DAOForkBlock:   big.NewInt(1920000),
+		DAOForkSupport: true,
+		EIP150Block:    big.NewInt(2463000),
+		EIP150Hash:     common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
+		EIP155Block:    big.NewInt(2675000),
+		EIP158Block:    big.NewInt(2675000),
+		ByzantiumBlock: big.NewInt(4370000),
+	}
+)
+
+func TestDifficulty(t *testing.T) {
+	t.Parallel()
+
+	dt := new(testMatcher)
+	// Not difficulty-tests
+	dt.skipLoad("hexencodetest.*")
+	dt.skipLoad("crypto.*")
+	dt.skipLoad("blockgenesistest\\.json")
+	dt.skipLoad("genesishashestest\\.json")
+	dt.skipLoad("keyaddrtest\\.json")
+	dt.skipLoad("txtest\\.json")
+
+	// files are 2 years old, contains strange values
+	dt.skipLoad("difficultyCustomHomestead\\.json")
+	dt.skipLoad("difficultyMorden\\.json")
+	dt.skipLoad("difficultyOlimpic\\.json")
+
+	dt.config("Ropsten", *params.TestnetChainConfig)
+	dt.config("Morden", *params.TestnetChainConfig)
+	dt.config("Frontier", params.ChainConfig{})
+
+	dt.config("Homestead", params.ChainConfig{
+		HomesteadBlock: big.NewInt(0),
+	})
+
+	dt.config("Byzantium", params.ChainConfig{
+		ByzantiumBlock: big.NewInt(0),
+	})
+
+	dt.config("Frontier", *params.TestnetChainConfig)
+	dt.config("MainNetwork", mainnetChainConfig)
+	dt.config("CustomMainNetwork", mainnetChainConfig)
+	dt.config("difficulty.json", mainnetChainConfig)
+
+	dt.walk(t, difficultyTestDir, func(t *testing.T, name string, test *DifficultyTest) {
+		cfg := dt.findConfig(name)
+		if test.ParentDifficulty.Cmp(params.MinimumDifficulty) < 0 {
+			t.Skip("difficulty below minimum")
+			return
+		}
+		if err := dt.checkFailure(t, name, test.Run(cfg)); err != nil {
+			t.Error(err)
+		}
+	})
+}
diff --git a/tests/difficulty_test_util.go b/tests/difficulty_test_util.go
new file mode 100644
index 000000000..754147793
--- /dev/null
+++ b/tests/difficulty_test_util.go
@@ -0,0 +1,70 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+//
+
+package tests
+
+import (
+	"fmt"
+	"math/big"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/math"
+	"github.com/ethereum/go-ethereum/consensus/ethash"
+	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/params"
+)
+
+//go:generate gencodec -type DifficultyTest -field-override difficultyTestMarshaling -out gen_difficultytest.go
+
+type DifficultyTest struct {
+	ParentTimestamp    *big.Int    `json:"parentTimestamp"`
+	ParentDifficulty   *big.Int    `json:"parentDifficulty"`
+	UncleHash          common.Hash `json:"parentUncles"`
+	CurrentTimestamp   *big.Int    `json:"currentTimestamp"`
+	CurrentBlockNumber uint64      `json:"currentBlockNumber"`
+	CurrentDifficulty  *big.Int    `json:"currentDifficulty"`
+}
+
+type difficultyTestMarshaling struct {
+	ParentTimestamp    *math.HexOrDecimal256
+	ParentDifficulty   *math.HexOrDecimal256
+	CurrentTimestamp   *math.HexOrDecimal256
+	CurrentDifficulty  *math.HexOrDecimal256
+	UncleHash          common.Hash
+	CurrentBlockNumber math.HexOrDecimal64
+}
+
+func (test *DifficultyTest) Run(config *params.ChainConfig) error {
+	parentNumber := big.NewInt(int64(test.CurrentBlockNumber - 1))
+	parent := &types.Header{
+		Difficulty: test.ParentDifficulty,
+		Time:       test.ParentTimestamp,
+		Number:     parentNumber,
+		UncleHash:  test.UncleHash,
+	}
+
+	actual := ethash.CalcDifficulty(config, test.CurrentTimestamp.Uint64(), parent)
+	exp := test.CurrentDifficulty
+
+	if actual.Cmp(exp) != 0 {
+		return fmt.Errorf("parent[time %v diff %v unclehash:%x] child[time %v number %v] diff %v != expected %v",
+			test.ParentTimestamp, test.ParentDifficulty, test.UncleHash,
+			test.CurrentTimestamp, test.CurrentBlockNumber, actual, exp)
+	}
+	return nil
+
+}
diff --git a/tests/gen_difficultytest.go b/tests/gen_difficultytest.go
new file mode 100644
index 000000000..88f36ce99
--- /dev/null
+++ b/tests/gen_difficultytest.go
@@ -0,0 +1,66 @@
+// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
+
+package tests
+
+import (
+	"encoding/json"
+	"math/big"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/math"
+)
+
+var _ = (*difficultyTestMarshaling)(nil)
+
+func (d DifficultyTest) MarshalJSON() ([]byte, error) {
+	type DifficultyTest struct {
+		ParentTimestamp    *math.HexOrDecimal256 `json:"parentTimestamp"`
+		ParentDifficulty   *math.HexOrDecimal256 `json:"parentDifficulty"`
+		UncleHash          common.Hash           `json:"parentUncles"`
+		CurrentTimestamp   *math.HexOrDecimal256 `json:"currentTimestamp"`
+		CurrentBlockNumber math.HexOrDecimal64   `json:"currentBlockNumber"`
+		CurrentDifficulty  *math.HexOrDecimal256 `json:"currentDifficulty"`
+	}
+	var enc DifficultyTest
+	enc.ParentTimestamp = (*math.HexOrDecimal256)(d.ParentTimestamp)
+	enc.ParentDifficulty = (*math.HexOrDecimal256)(d.ParentDifficulty)
+	enc.UncleHash = d.UncleHash
+	enc.CurrentTimestamp = (*math.HexOrDecimal256)(d.CurrentTimestamp)
+	enc.CurrentBlockNumber = math.HexOrDecimal64(d.CurrentBlockNumber)
+	enc.CurrentDifficulty = (*math.HexOrDecimal256)(d.CurrentDifficulty)
+	return json.Marshal(&enc)
+}
+
+func (d *DifficultyTest) UnmarshalJSON(input []byte) error {
+	type DifficultyTest struct {
+		ParentTimestamp    *math.HexOrDecimal256 `json:"parentTimestamp"`
+		ParentDifficulty   *math.HexOrDecimal256 `json:"parentDifficulty"`
+		UncleHash          *common.Hash          `json:"parentUncles"`
+		CurrentTimestamp   *math.HexOrDecimal256 `json:"currentTimestamp"`
+		CurrentBlockNumber *math.HexOrDecimal64  `json:"currentBlockNumber"`
+		CurrentDifficulty  *math.HexOrDecimal256 `json:"currentDifficulty"`
+	}
+	var dec DifficultyTest
+	if err := json.Unmarshal(input, &dec); err != nil {
+		return err
+	}
+	if dec.ParentTimestamp != nil {
+		d.ParentTimestamp = (*big.Int)(dec.ParentTimestamp)
+	}
+	if dec.ParentDifficulty != nil {
+		d.ParentDifficulty = (*big.Int)(dec.ParentDifficulty)
+	}
+	if dec.UncleHash != nil {
+		d.UncleHash = *dec.UncleHash
+	}
+	if dec.CurrentTimestamp != nil {
+		d.CurrentTimestamp = (*big.Int)(dec.CurrentTimestamp)
+	}
+	if dec.CurrentBlockNumber != nil {
+		d.CurrentBlockNumber = uint64(*dec.CurrentBlockNumber)
+	}
+	if dec.CurrentDifficulty != nil {
+		d.CurrentDifficulty = (*big.Int)(dec.CurrentDifficulty)
+	}
+	return nil
+}
diff --git a/tests/init_test.go b/tests/init_test.go
index 0adbb533d..ebb0d32c3 100644
--- a/tests/init_test.go
+++ b/tests/init_test.go
@@ -39,6 +39,7 @@ var (
 	transactionTestDir = filepath.Join(baseDir, "TransactionTests")
 	vmTestDir          = filepath.Join(baseDir, "VMTests")
 	rlpTestDir         = filepath.Join(baseDir, "RLPTests")
+	difficultyTestDir  = filepath.Join(baseDir, "BasicTests")
 )
 
 func readJson(reader io.Reader, value interface{}) error {
diff --git a/tests/state_test.go b/tests/state_test.go
index 9a7430fbe..5a67b290d 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -39,14 +39,16 @@ func TestState(t *testing.T) {
 	st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/EIP158`, "bug in test")
 	st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test")
 	st.fails(`^stRevertTest/RevertPrefoundEmptyOOG\.json/Byzantium`, "bug in test")
-	st.fails( `^stRandom/randomStatetest645\.json/EIP150/.*`, "known bug #15119")
-	st.fails( `^stRandom/randomStatetest645\.json/Frontier/.*`, "known bug #15119")
-	st.fails( `^stRandom/randomStatetest645\.json/Homestead/.*`, "known bug #15119")
-	st.fails( `^stRandom/randomStatetest644\.json/EIP150/.*`, "known bug #15119")
-	st.fails( `^stRandom/randomStatetest644\.json/Frontier/.*`, "known bug #15119")
-	st.fails( `^stRandom/randomStatetest644\.json/Homestead/.*`, "known bug #15119")
-
-
+	st.fails(`^stRandom/randomStatetest645\.json/EIP150/.*`, "known bug #15119")
+	st.fails(`^stRandom/randomStatetest645\.json/Frontier/.*`, "known bug #15119")
+	st.fails(`^stRandom/randomStatetest645\.json/Homestead/.*`, "known bug #15119")
+	st.fails(`^stRandom/randomStatetest644\.json/EIP150/.*`, "known bug #15119")
+	st.fails(`^stRandom/randomStatetest644\.json/Frontier/.*`, "known bug #15119")
+	st.fails(`^stRandom/randomStatetest644\.json/Homestead/.*`, "known bug #15119")
+	st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/EIP158/2`, "known bug ")
+	st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/EIP158/3`, "known bug ")
+	st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/Byzantium/2`, "known bug ")
+	st.fails(`^stCreateTest/TransactionCollisionToEmpty\.json/Byzantium/3`, "known bug ")
 	st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) {
 		for _, subtest := range test.Subtests() {
 			subtest := subtest
diff --git a/tests/testdata b/tests/testdata
index ca41e9063..37f555fbc 160000
--- a/tests/testdata
+++ b/tests/testdata
@@ -1 +1 @@
-Subproject commit ca41e906351209481bce3a1b35501f25a79023c5
+Subproject commit 37f555fbc091fbf761aa6f02227132fb31f0681c
-- 
GitLab