| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											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/event" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestDefaultGenesisBlock(t *testing.T) { | 
					
						
							|  |  |  | 	block, _ := DefaultGenesisBlock().ToBlock() | 
					
						
							|  |  |  | 	if block.Hash() != params.MainNetGenesisHash { | 
					
						
							|  |  |  | 		t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash(), params.MainNetGenesisHash) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	block, _ = DefaultTestnetGenesisBlock().ToBlock() | 
					
						
							|  |  |  | 	if block.Hash() != params.TestNetGenesisHash { | 
					
						
							|  |  |  | 		t.Errorf("wrong testnet genesis hash, got %v, want %v", block.Hash(), params.TestNetGenesisHash) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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, | 
					
						
							|  |  |  | 			wantConfig: params.AllProtocolChanges, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			name: "no block in DB, genesis == nil", | 
					
						
							|  |  |  | 			fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { | 
					
						
							|  |  |  | 				return SetupGenesisBlock(db, nil) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantHash:   params.MainNetGenesisHash, | 
					
						
							|  |  |  | 			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) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantHash:   params.MainNetGenesisHash, | 
					
						
							|  |  |  | 			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()) | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantErr:    &GenesisMismatchError{Stored: customghash, New: params.TestNetGenesisHash}, | 
					
						
							|  |  |  | 			wantHash:   params.TestNetGenesisHash, | 
					
						
							|  |  |  | 			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) | 
					
						
							| 
									
										
										
										
											2017-04-05 01:16:29 +03:00
										 |  |  | 				bc, _ := NewBlockChain(db, oldcustomg.Config, ethash.NewFullFaker(), new(event.TypeMux), vm.Config{}) | 
					
						
							| 
									
										
										
										
											2017-03-02 14:03:33 +01:00
										 |  |  | 				bc.SetValidator(bproc{}) | 
					
						
							|  |  |  | 				bc.InsertChain(makeBlockChainWithDiff(genesis, []int{2, 3, 4, 5}, 0)) | 
					
						
							|  |  |  | 				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 { | 
					
						
							|  |  |  | 		db, _ := ethdb.NewMemDatabase() | 
					
						
							|  |  |  | 		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. | 
					
						
							|  |  |  | 			stored := GetBlock(db, test.wantHash, 0) | 
					
						
							|  |  |  | 			if stored.Hash() != test.wantHash { | 
					
						
							|  |  |  | 				t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |