github.com/theQRL/go-zond@v0.2.1/core/forkid/forkid_test.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package forkid
    18  
    19  import (
    20  	"bytes"
    21  	"hash/crc32"
    22  	"math/big"
    23  
    24  	// "hash/crc32"
    25  	"math"
    26  	// "math/big"
    27  	"testing"
    28  
    29  	"github.com/theQRL/go-zond/common"
    30  	"github.com/theQRL/go-zond/core"
    31  	"github.com/theQRL/go-zond/core/types"
    32  	"github.com/theQRL/go-zond/params"
    33  
    34  	// "github.com/theQRL/go-zond/core"
    35  	// "github.com/theQRL/go-zond/core/types"
    36  	// "github.com/theQRL/go-zond/params"
    37  	"github.com/theQRL/go-zond/rlp"
    38  )
    39  
    40  // TestCreation tests that different genesis and fork rule combinations result in
    41  // the correct fork ID.
    42  func TestCreation(t *testing.T) {
    43  	type testcase struct {
    44  		head uint64
    45  		time uint64
    46  		want ID
    47  	}
    48  	tests := []struct {
    49  		config  *params.ChainConfig
    50  		genesis *types.Block
    51  		cases   []testcase
    52  	}{
    53  		// Mainnet test cases
    54  		{
    55  			params.MainnetChainConfig,
    56  			core.DefaultGenesisBlock().ToBlock(),
    57  			[]testcase{
    58  				{0, 0, ID{Hash: checksumToBytes(0x6170f487), Next: 0}},
    59  				// NOTE(rgeraldes24): revisit upon new fork
    60  				/*
    61  					{0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}},                    // Unsynced
    62  					{1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}},              // Last Frontier block
    63  					{1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}},              // First Homestead block
    64  					{1919999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}},              // Last Homestead block
    65  					{1920000, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}},              // First DAO block
    66  					{2462999, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}},              // Last DAO block
    67  					{2463000, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}},              // First Tangerine block
    68  					{2674999, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}},              // Last Tangerine block
    69  					{2675000, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}},              // First Spurious block
    70  					{4369999, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}},              // Last Spurious block
    71  					{4370000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}},              // First Byzantium block
    72  					{7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}},              // Last Byzantium block
    73  					{7280000, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}},              // First and last Constantinople, first Petersburg block
    74  					{9068999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}},              // Last Petersburg block
    75  					{9069000, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}},              // First Istanbul and first Muir Glacier block
    76  					{9199999, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}},              // Last  and first Muir Glacier block
    77  					{9200000, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}},             // First Muir Glacier block
    78  					{12243999, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}},            // Last Muir Glacier block
    79  					{12244000, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}},            // First Berlin block
    80  					{12964999, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}},            // Last Berlin block
    81  					{12965000, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}},            // First London block
    82  					{13772999, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}},            // Last London block
    83  					{13773000, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}},            // First Arrow Glacier block
    84  					{15049999, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}},            // Last Arrow Glacier block
    85  					{15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}},          // First Gray Glacier block
    86  					{20000000, 1681338454, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // Last Gray Glacier block
    87  					{20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}},          // First Shanghai block
    88  					{30000000, 2000000000, ID{Hash: checksumToBytes(0xdce96c2d), Next: 0}},          // Future Shanghai block
    89  				*/
    90  			},
    91  		},
    92  	}
    93  	for i, tt := range tests {
    94  		for j, ttt := range tt.cases {
    95  			if have := NewID(tt.config, tt.genesis, ttt.head, ttt.time); have != ttt.want {
    96  				t.Errorf("test %d, case %d: fork ID mismatch: have %x, want %x", i, j, have, ttt.want)
    97  			}
    98  		}
    99  	}
   100  }
   101  
   102  // NOTE(rgeraldes24): revisit upon new fork
   103  // TestValidation tests that a local peer correctly validates and accepts a remote
   104  // fork ID.
   105  func TestValidation(t *testing.T) {
   106  	tests := []struct {
   107  		config *params.ChainConfig
   108  		head   uint64
   109  		time   uint64
   110  		id     ID
   111  		err    error
   112  	}{
   113  		//----------------------
   114  		// Timestamp based tests
   115  		//----------------------
   116  
   117  		// Local is mainnet Shanghai, remote announces the same. No future fork is announced.
   118  		{params.MainnetChainConfig, 15050000, 20000000, ID{Hash: checksumToBytes(0x6170f487), Next: 0}, nil},
   119  
   120  		// Local is mainnet Shanghai, remote announces the same. Remote also announces a next fork
   121  		// at time 0xffffffff, but that is uncertain.
   122  		{params.MainnetChainConfig, 15050000, 20000000, ID{Hash: checksumToBytes(0x6170f487), Next: math.MaxUint64}, nil},
   123  
   124  		// Local is mainnet Shanghai, and isn't aware of more forks. Remote announces Shanghai +
   125  		// 0xffffffff. Local needs software update, reject.
   126  		{params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(checksumUpdate(0xdce96c2d, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale},
   127  
   128  		// Local is mainnet Shanghai, remote is random Shanghai.
   129  		{params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0x12345678), Next: 0}, ErrLocalIncompatibleOrStale},
   130  
   131  		// Local is mainnet Shanghai, far in the future. Remote announces Gopherium (non existing fork)
   132  		// at some future timestamp 8888888888, for itself, but past block for local. Local is incompatible.
   133  		//
   134  		// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
   135  		{params.MainnetChainConfig, 88888888, 8888888888, ID{Hash: checksumToBytes(0xdce96c2d), Next: 8888888888}, ErrLocalIncompatibleOrStale},
   136  	}
   137  	for i, tt := range tests {
   138  		filter := newFilter(tt.config, core.DefaultGenesisBlock().ToBlock(), func() (uint64, uint64) { return tt.head, tt.time })
   139  		if err := filter(tt.id); err != tt.err {
   140  			t.Errorf("test %d: validation error mismatch: have %v, want %v", i, err, tt.err)
   141  		}
   142  	}
   143  }
   144  
   145  // Tests that IDs are properly RLP encoded (specifically important because we
   146  // use uint32 to store the hash, but we need to encode it as [4]byte).
   147  func TestEncoding(t *testing.T) {
   148  	tests := []struct {
   149  		id   ID
   150  		want []byte
   151  	}{
   152  		{ID{Hash: checksumToBytes(0), Next: 0}, common.Hex2Bytes("c6840000000080")},
   153  		{ID{Hash: checksumToBytes(0xdeadbeef), Next: 0xBADDCAFE}, common.Hex2Bytes("ca84deadbeef84baddcafe,")},
   154  		{ID{Hash: checksumToBytes(math.MaxUint32), Next: math.MaxUint64}, common.Hex2Bytes("ce84ffffffff88ffffffffffffffff")},
   155  	}
   156  	for i, tt := range tests {
   157  		have, err := rlp.EncodeToBytes(tt.id)
   158  		if err != nil {
   159  			t.Errorf("test %d: failed to encode forkid: %v", i, err)
   160  			continue
   161  		}
   162  		if !bytes.Equal(have, tt.want) {
   163  			t.Errorf("test %d: RLP mismatch: have %x, want %x", i, have, tt.want)
   164  		}
   165  	}
   166  }
   167  
   168  // Tests that time-based forks which are active at genesis are not included in
   169  // forkid hash.
   170  func TestTimeBasedForkInGenesis(t *testing.T) {
   171  	var (
   172  		time       = uint64(1690475657)
   173  		genesis    = types.NewBlockWithHeader(&types.Header{Time: time})
   174  		forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes()))
   175  		config     = func() *params.ChainConfig {
   176  			return &params.ChainConfig{
   177  				ChainID: big.NewInt(1337),
   178  			}
   179  		}
   180  	)
   181  	tests := []struct {
   182  		config *params.ChainConfig
   183  		want   ID
   184  	}{
   185  		// NOTE(rgeraldes24): revisit upon new fork
   186  		/*
   187  			// Shanghai active before genesis, skip
   188  			{config(), ID{Hash: forkidHash, Next: time + 1}},
   189  
   190  			// Shanghai active at genesis, skip
   191  			{config(), ID{Hash: forkidHash, Next: time + 1}},
   192  
   193  			// Shanghai not active, skip
   194  			{config(), ID{Hash: forkidHash, Next: time + 1}},
   195  		*/
   196  		// No forks
   197  		{config(), ID{Hash: forkidHash, Next: 0}},
   198  	}
   199  	for _, tt := range tests {
   200  		if have := NewID(tt.config, genesis, 0, time); have != tt.want {
   201  			t.Fatalf("incorrect forkid hash: have %x, want %x", have, tt.want)
   202  		}
   203  	}
   204  }