| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | // 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 core | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/davecgh/go-spew/spew" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/consensus/ethash" | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/rawdb" | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/vm" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestDefaultGenesisBlock(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 	block := DefaultGenesisBlock().ToBlock(nil) | 
					
						
							| 
									
										
										
										
											2017-07-04 12:28:58 +03:00
										 |  |  | 	if block.Hash() != params.MainnetGenesisHash { | 
					
						
							|  |  |  | 		t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash(), params.MainnetGenesisHash) | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 	block = DefaultTestnetGenesisBlock().ToBlock(nil) | 
					
						
							| 
									
										
										
										
											2017-07-04 12:28:58 +03:00
										 |  |  | 	if block.Hash() != params.TestnetGenesisHash { | 
					
						
							|  |  |  | 		t.Errorf("wrong testnet genesis hash, got %v, want %v", block.Hash(), params.TestnetGenesisHash) | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestSetupGenesis(t *testing.T) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50") | 
					
						
							|  |  |  | 		customg     = Genesis{ | 
					
						
							|  |  |  | 			Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)}, | 
					
						
							|  |  |  | 			Alloc: GenesisAlloc{ | 
					
						
							|  |  |  | 				{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		oldcustomg = customg | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)} | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name       string | 
					
						
							|  |  |  | 		fn         func(ethdb.Database) (*params.ChainConfig, common.Hash, error) | 
					
						
							|  |  |  | 		wantConfig *params.ChainConfig | 
					
						
							|  |  |  | 		wantHash   common.Hash | 
					
						
							|  |  |  | 		wantErr    error | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "genesis without ChainConfig", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, new(Genesis)) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr:    errGenesisNoConfig, | 
					
						
							| 
									
										
										
										
											2017-10-24 13:40:42 +03:00
										 |  |  | 			wantConfig: params.AllEthashProtocolChanges, | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "no block in DB, genesis == nil", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, nil) | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-07-04 12:28:58 +03:00
										 |  |  | 			wantHash:   params.MainnetGenesisHash, | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 			wantConfig: params.MainnetChainConfig, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "mainnet block in DB, genesis == nil", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				DefaultGenesisBlock().MustCommit(db) | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, nil) | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-07-04 12:28:58 +03:00
										 |  |  | 			wantHash:   params.MainnetGenesisHash, | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 			wantConfig: params.MainnetChainConfig, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "custom block in DB, genesis == nil", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				customg.MustCommit(db) | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, nil) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantHash:   customghash, | 
					
						
							|  |  |  | 			wantConfig: customg.Config, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "custom block in DB, genesis == testnet", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				customg.MustCommit(db) | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, DefaultTestnetGenesisBlock()) | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-07-04 12:28:58 +03:00
										 |  |  | 			wantErr:    &GenesisMismatchError{Stored: customghash, New: params.TestnetGenesisHash}, | 
					
						
							|  |  |  | 			wantHash:   params.TestnetGenesisHash, | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 			wantConfig: params.TestnetChainConfig, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "compatible config in DB", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				oldcustomg.MustCommit(db) | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, &customg) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantHash:   customghash, | 
					
						
							|  |  |  | 			wantConfig: customg.Config, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "incompatible config in DB", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				// Commit the 'old' genesis block with Homestead transition at #2. | 
					
						
							|  |  |  | 				// Advance to block #4, past the homestead transition block of customg. | 
					
						
							|  |  |  | 				genesis := oldcustomg.MustCommit(db) | 
					
						
							| 
									
										
										
										
											2018-02-23 14:02:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 20:09:30 +08:00
										 |  |  | 				bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil) | 
					
						
							| 
									
										
										
										
											2017-08-07 15:47:25 +03:00
										 |  |  | 				defer bc.Stop() | 
					
						
							| 
									
										
										
										
											2018-02-23 14:02:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil) | 
					
						
							|  |  |  | 				bc.InsertChain(blocks) | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 				bc.CurrentBlock() | 
					
						
							|  |  |  | 				// This should return a compatibility error. | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, &customg) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantHash:   customghash, | 
					
						
							|  |  |  | 			wantConfig: customg.Config, | 
					
						
							|  |  |  | 			wantErr: ¶ms.ConfigCompatError{ | 
					
						
							|  |  |  | 				What:         "Homestead fork block", | 
					
						
							|  |  |  | 				StoredConfig: big.NewInt(2), | 
					
						
							|  |  |  | 				NewConfig:    big.NewInt(3), | 
					
						
							|  |  |  | 				RewindTo:     1, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, test := range tests { | 
					
						
							| 
									
										
										
										
											2018-09-24 15:57:49 +03:00
										 |  |  | 		db := rawdb.NewMemoryDatabase() | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 		config, hash, err := test.fn(db) | 
					
						
							|  |  |  | 		// Check the return values. | 
					
						
							|  |  |  | 		if !reflect.DeepEqual(err, test.wantErr) { | 
					
						
							|  |  |  | 			spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true} | 
					
						
							|  |  |  | 			t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !reflect.DeepEqual(config, test.wantConfig) { | 
					
						
							|  |  |  | 			t.Errorf("%s:\nreturned %v\nwant     %v", test.name, config, test.wantConfig) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if hash != test.wantHash { | 
					
						
							|  |  |  | 			t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex()) | 
					
						
							|  |  |  | 		} else if err == nil { | 
					
						
							|  |  |  | 			// Check database content. | 
					
						
							| 
									
										
										
										
											2018-05-07 14:35:06 +03:00
										 |  |  | 			stored := rawdb.ReadBlock(db, test.wantHash, 0) | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 			if stored.Hash() != test.wantHash { | 
					
						
							|  |  |  | 				t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |