github.com/m3shine/gochain@v2.2.26+incompatible/core/genesis_test.go (about) 1 // Copyright 2017 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 core 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/json" 23 "io/ioutil" 24 "math/big" 25 "reflect" 26 "testing" 27 28 "github.com/davecgh/go-spew/spew" 29 30 "github.com/gochain-io/gochain/common" 31 "github.com/gochain-io/gochain/consensus/clique" 32 "github.com/gochain-io/gochain/core/rawdb" 33 "github.com/gochain-io/gochain/core/vm" 34 "github.com/gochain-io/gochain/ethdb" 35 "github.com/gochain-io/gochain/params" 36 ) 37 38 func TestDefaultGenesisBlockHash(t *testing.T) { 39 for _, test := range []struct { 40 name string 41 exp, got common.Hash 42 }{ 43 {"mainnet", params.MainnetGenesisHash, DefaultGenesisBlock().ToBlock(nil).Hash()}, 44 {"testnet", params.TestnetGenesisHash, DefaultTestnetGenesisBlock().ToBlock(nil).Hash()}, 45 } { 46 if test.exp != test.got { 47 t.Errorf("wrong %s genesis hash, got %s, want %s", test.name, test.got.Hex(), test.exp.Hex()) 48 } 49 } 50 } 51 52 func TestSetupGenesis(t *testing.T) { 53 ctx := context.Background() 54 var ( 55 customghash = common.HexToHash("0x2ba5deb4ad470a1b170475fe5004f0e0cefffa8e18469e6510937e74db11094a") 56 customg = Genesis{ 57 Config: ¶ms.ChainConfig{ 58 HomesteadBlock: big.NewInt(3), 59 Clique: params.DefaultCliqueConfig(), 60 }, 61 Alloc: GenesisAlloc{ 62 {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, 63 }, 64 } 65 oldcustomg = customg 66 ) 67 oldcustomg.Config = ¶ms.ChainConfig{ 68 HomesteadBlock: big.NewInt(2), 69 Clique: params.DefaultCliqueConfig(), 70 } 71 tests := []struct { 72 name string 73 fn func(common.Database) (*params.ChainConfig, common.Hash, error) 74 wantConfig *params.ChainConfig 75 wantHash common.Hash 76 wantErr error 77 }{ 78 { 79 name: "genesis without ChainConfig", 80 fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) { 81 return SetupGenesisBlock(db, new(Genesis)) 82 }, 83 wantErr: errGenesisNoConfig, 84 wantConfig: params.AllCliqueProtocolChanges, 85 }, 86 { 87 name: "no block in DB, genesis == nil", 88 fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) { 89 return SetupGenesisBlock(db, nil) 90 }, 91 wantHash: params.MainnetGenesisHash, 92 wantConfig: params.MainnetChainConfig, 93 }, 94 { 95 name: "mainnet block in DB, genesis == nil", 96 fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) { 97 DefaultGenesisBlock().MustCommit(db) 98 return SetupGenesisBlock(db, nil) 99 }, 100 wantHash: params.MainnetGenesisHash, 101 wantConfig: params.MainnetChainConfig, 102 }, 103 { 104 name: "custom block in DB, genesis == nil", 105 fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) { 106 customg.MustCommit(db) 107 return SetupGenesisBlock(db, nil) 108 }, 109 wantHash: customghash, 110 wantConfig: customg.Config, 111 }, 112 { 113 name: "custom block in DB, genesis == testnet", 114 fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) { 115 customg.MustCommit(db) 116 return SetupGenesisBlock(db, DefaultTestnetGenesisBlock()) 117 }, 118 wantErr: &GenesisMismatchError{Stored: customghash, New: params.TestnetGenesisHash}, 119 wantHash: params.TestnetGenesisHash, 120 wantConfig: params.TestnetChainConfig, 121 }, 122 { 123 name: "compatible config in DB", 124 fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) { 125 oldcustomg.MustCommit(db) 126 return SetupGenesisBlock(db, &customg) 127 }, 128 wantHash: customghash, 129 wantConfig: customg.Config, 130 }, 131 { 132 name: "incompatible config in DB", 133 fn: func(db common.Database) (*params.ChainConfig, common.Hash, error) { 134 // Commit the 'old' genesis block with Homestead transition at #2. 135 // Advance to block #4, past the homestead transition block of customg. 136 genesis := oldcustomg.MustCommit(db) 137 138 bc, _ := NewBlockChain(ctx, db, nil, oldcustomg.Config, clique.NewFullFaker(), vm.Config{}) 139 defer bc.Stop() 140 141 blocks, _ := GenerateChain(ctx, oldcustomg.Config, genesis, clique.NewFaker(), db, 4, nil) 142 _, err := bc.InsertChain(ctx, blocks) 143 if err != nil { 144 return nil, common.Hash{}, err 145 } 146 bc.CurrentBlock() 147 // This should return a compatibility error. 148 return SetupGenesisBlock(db, &customg) 149 }, 150 wantHash: customghash, 151 wantConfig: customg.Config, 152 wantErr: ¶ms.ConfigCompatError{ 153 What: "Homestead fork block", 154 StoredConfig: big.NewInt(2), 155 NewConfig: big.NewInt(3), 156 RewindTo: 1, 157 }, 158 }, 159 } 160 161 for _, test := range tests { 162 db := ethdb.NewMemDatabase() 163 config, hash, err := test.fn(db) 164 // Check the return values. 165 if !reflect.DeepEqual(err, test.wantErr) { 166 spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true} 167 t.Fatalf("%s:\nhave: %#v\nwant: %#v\n", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr)) 168 } 169 if !reflect.DeepEqual(config, test.wantConfig) { 170 t.Errorf("%s:\nhave: %v\nwant: %v\n", test.name, config, test.wantConfig) 171 } 172 if hash != test.wantHash { 173 t.Errorf("%s:\nhave: %s\nwant: %s\n", test.name, hash.Hex(), test.wantHash.Hex()) 174 } else if err == nil { 175 // Check database content. 176 stored := rawdb.ReadBlock(db, test.wantHash, 0) 177 if stored.Hash() != test.wantHash { 178 t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash) 179 } 180 } 181 } 182 } 183 184 func TestDefaultGenesisBlock(t *testing.T) { 185 for _, test := range []struct { 186 name string 187 file string 188 genesis *Genesis 189 }{ 190 {"mainnet", "genesis-main.json", DefaultGenesisBlock()}, 191 {"testnet", "genesis-test.json", DefaultTestnetGenesisBlock()}, 192 } { 193 exp, err := ioutil.ReadFile(test.file) 194 if err != nil { 195 t.Fatal(err) 196 } 197 exp = bytes.TrimSpace(exp) 198 got, err := json.MarshalIndent(test.genesis, "", " ") 199 if err != nil { 200 t.Fatal(err) 201 } 202 if !bytes.Equal(exp, got) { 203 t.Errorf("mismatched %s genesis, expected:\n%s\ngot:\n%s", test.name, string(exp), string(got)) 204 } 205 } 206 } 207 208 func TestGenesisAlloc_Total(t *testing.T) { 209 for _, test := range []struct { 210 name string 211 exp *big.Int 212 alloc GenesisAlloc 213 }{ 214 { 215 name: "mainnet", 216 exp: new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(1000000000)), 217 alloc: DefaultGenesisBlock().Alloc, 218 }, 219 { 220 name: "testnet", 221 exp: new(big.Int).Mul(big.NewInt(params.Ether), big.NewInt(1000000000)), 222 alloc: DefaultTestnetGenesisBlock().Alloc, 223 }, 224 { 225 name: "custom", 226 exp: big.NewInt(100), 227 alloc: GenesisAlloc{ 228 common.StringToAddress("a"): {Balance: big.NewInt(1)}, 229 common.StringToAddress("b"): {Balance: big.NewInt(10)}, 230 common.StringToAddress("c"): {Balance: big.NewInt(19)}, 231 common.StringToAddress("d"): {Balance: big.NewInt(30)}, 232 common.StringToAddress("e"): {Balance: big.NewInt(40)}, 233 }, 234 }, 235 } { 236 if got := test.alloc.Total(); got.Cmp(test.exp) != 0 { 237 t.Errorf("%s: expected %s but got %s", test.name, test.exp, got) 238 } 239 } 240 }