github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/config_test.go (about) 1 package core 2 3 import ( 4 "io" 5 "math/big" 6 "os" 7 "strings" 8 "testing" 9 10 "path/filepath" 11 12 "github.com/ethereumproject/go-ethereum/common" 13 "github.com/ethereumproject/go-ethereum/core/types" 14 "github.com/ethereumproject/go-ethereum/ethdb" 15 "reflect" 16 ) 17 18 func TestConfigErrorProperties(t *testing.T) { 19 if IsValidateError(ErrHashKnownBad) { 20 t.Error("ErrHashKnownBad is a validation error") 21 } 22 if !IsValidateError(ErrHashKnownFork) { 23 t.Error("ErrHashKnownFork is not a validation error") 24 } 25 } 26 27 func TestChainConfig_IsHomestead(t *testing.T) { 28 config := DefaultConfigMainnet.ChainConfig 29 30 if config.IsHomestead(big.NewInt(10000)) { 31 t.Errorf("Unexpected for %d", 10000) 32 } 33 34 if !config.IsHomestead(big.NewInt(1920000)) { 35 t.Errorf("Expected for %d", 1920000) 36 } 37 if !config.IsHomestead(big.NewInt(2325166)) { 38 t.Errorf("Expected for %d", 2325166) 39 } 40 if !config.IsHomestead(big.NewInt(3000000)) { 41 t.Errorf("Expected for %d", 3000000) 42 } 43 if !config.IsHomestead(big.NewInt(3000001)) { 44 t.Errorf("Expected for %d", 3000001) 45 } 46 if !config.IsHomestead(big.NewInt(4000000)) { 47 t.Errorf("Expected for %d", 3000000) 48 } 49 if !config.IsHomestead(big.NewInt(5000000)) { 50 t.Errorf("Expected for %d", 5000000) 51 } 52 if !config.IsHomestead(big.NewInt(5000001)) { 53 t.Errorf("Expected for %d", 5000001) 54 } 55 } 56 57 func TestChainConfig_IsDiehard(t *testing.T) { 58 config := DefaultConfigMainnet.ChainConfig 59 60 if config.IsDiehard(big.NewInt(1920000)) { 61 t.Errorf("Unexpected for %d", 1920000) 62 } 63 64 if config.IsDiehard(big.NewInt(2325166)) { 65 t.Errorf("Unexpected for %d", 2325166) 66 } 67 68 if !config.IsDiehard(big.NewInt(3000000)) { 69 t.Errorf("Expected for %d", 3000000) 70 } 71 if !config.IsDiehard(big.NewInt(3000001)) { 72 t.Errorf("Expected for %d", 3000001) 73 } 74 if !config.IsDiehard(big.NewInt(4000000)) { 75 t.Errorf("Expected for %d", 3000000) 76 } 77 78 if !config.IsDiehard(big.NewInt(5000000)) { 79 t.Errorf("Expected for %d", 5000000) 80 } 81 if !config.IsDiehard(big.NewInt(5000001)) { 82 t.Errorf("Expected for %d", 5000001) 83 } 84 } 85 86 func TestChainConfig_IsExplosion(t *testing.T) { 87 config := DefaultConfigMainnet.ChainConfig 88 89 if config.IsExplosion(big.NewInt(1920000)) { 90 t.Errorf("Unexpected for %d", 1920000) 91 } 92 93 if config.IsExplosion(big.NewInt(2325166)) { 94 t.Errorf("Unexpected for %d", 2325166) 95 } 96 97 // Default Diehard block is 3000000 98 if config.IsExplosion(big.NewInt(3000000)) { 99 t.Errorf("Unxpected for %d", 3000000) 100 } 101 if config.IsExplosion(big.NewInt(3000001)) { 102 t.Errorf("Unxpected for %d", 3000001) 103 } 104 if config.IsExplosion(big.NewInt(4000000)) { 105 t.Errorf("Unxpected for %d", 3000000) 106 } 107 108 // Default BombDelay length is 2000000. 109 if !config.IsExplosion(big.NewInt(5000000)) { 110 t.Errorf("Expected for %d", 5000000) 111 } 112 if !config.IsExplosion(big.NewInt(5000001)) { 113 t.Errorf("Expected for %d", 5000001) 114 } 115 116 } 117 118 func sameGenesisDumpAllocationsBalances(gd1, gd2 *GenesisDump) bool { 119 for address, alloc := range gd2.Alloc { 120 if gd1.Alloc[address] != nil { 121 bal1, _ := new(big.Int).SetString(gd1.Alloc[address].Balance, 0) 122 bal2, _ := new(big.Int).SetString(alloc.Balance, 0) 123 if bal1.Cmp(bal2) != 0 { 124 return false 125 } 126 } else if alloc.Balance != "" { 127 return false 128 } 129 130 } 131 return true 132 } 133 134 // TestMakeGenesisDump is a unit-ish test for MakeGenesisDump() 135 func TestMakeGenesisDump(t *testing.T) { 136 // setup so we have a genesis block in this test db 137 db, _ := ethdb.NewMemDatabase() 138 genesisDump := &GenesisDump{ 139 Nonce: "0x0000000000000042", 140 Timestamp: "0x0000000000000000000000000000000000000000000000000000000000000000", 141 Coinbase: "0x0000000000000000000000000000000000000000", 142 Difficulty: "0x0000000000000000000000000000000000000000000000000000000400000000", 143 ExtraData: "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", 144 GasLimit: "0x0000000000000000000000000000000000000000000000000000000000001388", 145 Mixhash: "0x0000000000000000000000000000000000000000000000000000000000000000", 146 ParentHash: "0x0000000000000000000000000000000000000000000000000000000000000000", 147 Alloc: map[hex]*GenesisDumpAlloc{ 148 "000d836201318ec6899a67540690382780743280": {Balance: "200000000000000000000"}, 149 "001762430ea9c3a26e5749afdb70da5f78ddbb8c": {Balance: "200000000000000000000"}, 150 "001d14804b399c6ef80e64576f657660804fec0b": {Balance: "4200000000000000000000"}, 151 "0032403587947b9f15622a68d104d54d33dbd1cd": {Balance: "77500000000000000000"}, 152 "00497e92cdc0e0b963d752b2296acb87da828b24": {Balance: "194800000000000000000"}, 153 "004bfbe1546bc6c65b5c7eaa55304b38bbfec6d3": {Balance: "2000000000000000000000"}, 154 "005a9c03f69d17d66cbb8ad721008a9ebbb836fb": {Balance: "2000000000000000000000"}, 155 }, 156 } 157 gBlock1, err := WriteGenesisBlock(db, genesisDump) 158 if err != nil { 159 t.Errorf("WriteGenesisBlock could not setup genesisDump: err: %v", err) 160 } 161 162 // ensure equivalent genesis dumps in and out 163 gotGenesisDump, err := MakeGenesisDump(db) 164 if gotGenesisDump.Nonce != genesisDump.Nonce { 165 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump nonce: wanted: %v, got: %v", genesisDump.Nonce, gotGenesisDump.Nonce) 166 } 167 if gotGenesisDump.Timestamp != genesisDump.Timestamp { 168 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump timestamp: wanted: %v, got: %v", genesisDump.Timestamp, gotGenesisDump.Timestamp) 169 } 170 if gotGenesisDump.Coinbase != genesisDump.Coinbase { 171 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump coinbase: wanted: %v, got: %v", genesisDump.Coinbase, gotGenesisDump.Coinbase) 172 } 173 if gotGenesisDump.Difficulty != genesisDump.Difficulty { 174 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump difficulty: wanted: %v, got: %v", genesisDump.Difficulty, gotGenesisDump.Difficulty) 175 } 176 if gotGenesisDump.ExtraData != genesisDump.ExtraData { 177 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump extra data: wanted: %v, got: %v", genesisDump.ExtraData, gotGenesisDump.ExtraData) 178 } 179 if gotGenesisDump.GasLimit != genesisDump.GasLimit { 180 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump gaslimit: wanted: %v, got: %v", genesisDump.GasLimit, gotGenesisDump.GasLimit) 181 } 182 if gotGenesisDump.Mixhash != genesisDump.Mixhash { 183 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump mixhash: wanted: %v, got: %v", genesisDump.Mixhash, gotGenesisDump.Mixhash) 184 } 185 if gotGenesisDump.ParentHash != genesisDump.ParentHash { 186 t.Errorf("MakeGenesisDump failed to make equivalent genesis dump parenthash: wanted: %v, got: %v", genesisDump.ParentHash, gotGenesisDump.ParentHash) 187 } 188 if !sameGenesisDumpAllocationsBalances(genesisDump, gotGenesisDump) { 189 t.Error("MakeGenesisDump failed to make equivalent genesis dump allocations.") 190 } 191 192 // ensure equivalent genesis blocks in and out 193 gBlock2, err := WriteGenesisBlock(db, gotGenesisDump) 194 if err != nil { 195 t.Errorf("WriteGenesisBlock could not setup gotGenesisDump: err: %v", err) 196 } 197 198 if gBlock1.Hash() != gBlock2.Hash() { 199 t.Errorf("MakeGenesisDump failed to make genesis block with equivalent hashes: wanted: %v, got: %v", gBlock1.Hash(), gBlock2.Hash()) 200 } 201 db.Close() 202 } 203 204 func TestMakeGenesisDump2(t *testing.T) { 205 // setup so we have a genesis block in this test db 206 for i, gen := range []*GenesisDump{DefaultConfigMainnet.Genesis, DefaultConfigMorden.Genesis} { 207 db, _ := ethdb.NewMemDatabase() 208 genesisDump := gen 209 gBlock1, err := WriteGenesisBlock(db, genesisDump) 210 if err != nil { 211 t.Errorf("WriteGenesisBlock could not setup initial genesisDump: %v, err: %v", i, err) 212 } 213 214 // ensure equivalent genesis dumps in and out 215 gotGenesisDump, err := MakeGenesisDump(db) 216 217 // ensure equivalent genesis blocks in and out 218 gBlock2, err := WriteGenesisBlock(db, gotGenesisDump) 219 if err != nil { 220 t.Errorf("WriteGenesisBlock could not setup gotGenesisDump: %v, err: %v", i, err) 221 } 222 223 if !sameGenesisDumpAllocationsBalances(genesisDump, gotGenesisDump) { 224 t.Error("MakeGenesisDump failed to make equivalent genesis dump allocations.") 225 } 226 227 if gBlock1.Hash() != gBlock2.Hash() { 228 t.Errorf(`MakeGenesisDump failed to make genesis block with equivalent hashes: %v: wanted: %v, got: %v 229 WANTED: 230 %v 231 232 GOT: 233 %v`, i, gBlock1.Hash().Hex(), gBlock2.Hash().Hex(), gBlock1.String(), gBlock2.String()) 234 235 } 236 db.Close() 237 } 238 } 239 240 func getDefaultChainConfigSorted() *ChainConfig { 241 return DefaultConfigMainnet.ChainConfig.SortForks() 242 } 243 244 // Unit-y tests. 245 246 func TestChainConfig_HasFeature(t *testing.T) { 247 c := DefaultConfigMorden.ChainConfig.SortForks() 248 for _, id := range allAvailableTestnetConfigKeys { 249 if _, _, ok := c.HasFeature(id); !ok { 250 t.Errorf("feature not found: %v", id) 251 } 252 } 253 c = getDefaultChainConfigSorted() 254 for _, id := range allAvailableDefaultConfigKeys { 255 if _, _, ok := c.HasFeature(id); !ok { 256 t.Errorf("feature not found: %v", id) 257 } 258 } 259 260 // never gets unavailable keys 261 c = DefaultConfigMorden.ChainConfig.SortForks() 262 for _, id := range unavailableConfigKeys { 263 if _, _, ok := c.HasFeature(id); ok { 264 t.Errorf("nonexisting feature found: %v", id) 265 } 266 } 267 c = getDefaultChainConfigSorted() 268 for _, id := range unavailableConfigKeys { 269 if _, _, ok := c.HasFeature(id); ok { 270 t.Errorf("nonexisting feature found: %v", id) 271 } 272 } 273 } 274 275 // TestChainConfig_GetFeature should be able to get all features described in DefaultChainConfigMainnet. 276 func TestChainConfig_GetFeature(t *testing.T) { 277 c := getDefaultChainConfigSorted() 278 var dict = make(map[*big.Int][]string) 279 for _, fork := range c.Forks { 280 for _, feat := range fork.Features { 281 dict[fork.Block] = append(dict[fork.Block], feat.ID) 282 } 283 } 284 for block, ids := range dict { 285 for _, name := range ids { 286 feat, fork, ok := c.GetFeature(block, name) 287 if !ok { 288 t.Errorf("expected feature exist: feat: %v, fork: %v, block: %v", feat, fork, block) 289 } 290 } 291 } 292 } 293 294 var allAvailableDefaultConfigKeys = []string{ 295 "difficulty", 296 "gastable", 297 "eip155", 298 } 299 var allAvailableTestnetConfigKeys = []string{ 300 "difficulty", 301 "gastable", 302 "eip155", 303 "reward", 304 } 305 var unavailableConfigKeys = []string{ 306 "foo", 307 "bar", 308 "monkey", 309 } 310 311 // veryHighBlock is a block in the far distant future (so far, in fact, that it will never actually exist) 312 // Used to test cumulative aggregation functions, ie "eventually". 313 var veryHighBlock *big.Int = big.NewInt(250000000) 314 315 // TestChainConfig_EventuallyGetAllPossibleFeatures should aggregate all available features from previous branches 316 func TestChainConfig_GetFeature2_EventuallyGetAllPossibleFeatures(t *testing.T) { 317 c := getDefaultChainConfigSorted() 318 for _, id := range allAvailableDefaultConfigKeys { 319 if _, _, ok := c.GetFeature(veryHighBlock, id); !ok { 320 t.Errorf("could not get feature with id: %v, at block: %v", id, big.NewInt(5000000)) 321 } 322 } 323 } 324 325 // TestChainConfig_NeverGetNonexistantFeatures should never eventually collect features that don't exist 326 func TestChainConfig_GetFeature3_NeverGetNonexistantFeatures(t *testing.T) { 327 c := getDefaultChainConfigSorted() 328 for _, id := range unavailableConfigKeys { 329 if feat, _, ok := c.GetFeature(veryHighBlock, id); ok { 330 t.Errorf("found unexpected feature: %v, for name: %v, at block: %v", feat, id, big.NewInt(5000000)) 331 } 332 } 333 } 334 335 func TestChainConfig_GetFeature4_WorkForHighNumbers(t *testing.T) { 336 c := getDefaultChainConfigSorted() 337 ultraHighBlock := big.NewInt(99999999999999999) 338 if _, _, ok := c.GetFeature(ultraHighBlock, "difficulty"); !ok { 339 t.Errorf("unexpected unfound difficulty feature for far-future block: %v", ultraHighBlock) 340 } 341 } 342 343 func TestChainConfig_GetChainID(t *testing.T) { 344 // Test default hardcoded configs. 345 if DefaultConfigMainnet.ChainConfig.GetChainID().Cmp(DefaultConfigMainnet.ChainConfig.GetChainID()) != 0 { 346 t.Errorf("got: %v, want: %v", DefaultConfigMainnet.ChainConfig.GetChainID(), DefaultConfigMainnet.ChainConfig.GetChainID()) 347 } 348 if DefaultConfigMorden.ChainConfig.GetChainID().Cmp(DefaultConfigMorden.ChainConfig.GetChainID()) != 0 { 349 t.Errorf("got: %v, want: %v", DefaultConfigMorden.ChainConfig.GetChainID(), DefaultConfigMorden.ChainConfig.GetChainID()) 350 } 351 352 // If no chainID (config is empty) returns 0. 353 c := &ChainConfig{} 354 cid := c.GetChainID() 355 // check is zero 356 if cid.Cmp(new(big.Int)) != 0 { 357 t.Errorf("got: %v, want: %v", cid, new(big.Int)) 358 } 359 360 // Test parsing default external mainnet config. 361 cases := map[string]*big.Int{ 362 "../core/config/mainnet.json": DefaultConfigMainnet.ChainConfig.GetChainID(), 363 "../core/config/morden.json": DefaultConfigMorden.ChainConfig.GetChainID(), 364 } 365 for extConfigPath, wantInt := range cases { 366 p, e := filepath.Abs(extConfigPath) 367 if e != nil { 368 t.Fatalf("filepath err: %v", e) 369 } 370 extConfig, err := ReadExternalChainConfigFromFile(p) 371 if err != nil { 372 t.Fatalf("could not decode file: %v", err) 373 } 374 if extConfig.ChainConfig.GetChainID().Cmp(wantInt) != 0 { 375 t.Errorf("got: %v, want: %v", extConfig.ChainConfig.GetChainID(), wantInt) 376 } 377 } 378 } 379 380 // Acceptance-y tests. 381 382 // Test GetFeature gets expected feature values from default configuration data... 383 384 // TestChainConfig_GetFeature_DefaultEIP155 should get the eip155 feature for (only and above) its default implemented block. 385 func TestChainConfig_GetFeature5_DefaultEIP155(t *testing.T) { 386 c := getDefaultChainConfigSorted() 387 var tables = map[*big.Int]*big.Int{ 388 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block, big.NewInt(1)): nil, 389 DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block: nil, 390 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block, big.NewInt(1)): nil, 391 392 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block, big.NewInt(1)): nil, 393 DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block: nil, 394 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block, big.NewInt(1)): nil, 395 396 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block, big.NewInt(1)): nil, 397 DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block: big.NewInt(61), 398 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block, big.NewInt(1)): big.NewInt(61), 399 } 400 for block, expected := range tables { 401 feat, fork, ok := c.GetFeature(block, "eip155") 402 if expected != nil { 403 if !ok { 404 t.Errorf("Expected eip155 feature to exist. feat: %v, fork: %v, block: %v", feat, fork, block) 405 } 406 val, ok := feat.GetBigInt("chainID") 407 if !ok { 408 t.Errorf("failed to get value for eip155 feature. feat: %v, fork: %v, block: %v", feat, fork, block) 409 } 410 if val.Cmp(expected) != 0 { 411 t.Errorf("want: %v, got: %v", expected, val) 412 } 413 } else { 414 if ok { 415 t.Errorf("Unexpected eip155 feature exists. feat: %v, fork: %v, block: %v", feat, fork, block) 416 } 417 } 418 } 419 } 420 421 // TestChainConfig_GetFeature_DefaultGasTables sets that GetFeatures gets expected feature values for default fork configs. 422 func TestChainConfig_GetFeature6_DefaultGasTables(t *testing.T) { 423 c := getDefaultChainConfigSorted() 424 var tables = map[*big.Int]string{ 425 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block, big.NewInt(1)): "", 426 DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block: "homestead", 427 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block, big.NewInt(1)): "homestead", 428 429 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block, big.NewInt(1)): "homestead", 430 DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block: "eip150", 431 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block, big.NewInt(1)): "eip150", 432 433 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block, big.NewInt(1)): "eip150", 434 DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block: "eip160", 435 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block, big.NewInt(1)): "eip160", 436 } 437 for block, expected := range tables { 438 feat, fork, ok := c.GetFeature(block, "gastable") 439 if expected != "" { 440 if !ok { 441 t.Errorf("Expected gastable feature to exist. feat: %v, fork: %v, block: %v", feat, fork, block) 442 } 443 val, ok := feat.GetString("type") 444 if !ok { 445 t.Errorf("failed to get value for gastable feature. feat: %v, fork: %v, block: %v", feat, fork, block) 446 } 447 if val != expected { 448 t.Errorf("want: %v, got: %v", expected, val) 449 } 450 } else { 451 if ok { 452 t.Errorf("Unexpected gastable feature exists. feat: %v, fork: %v, block: %v", feat, fork, block) 453 } 454 } 455 } 456 } 457 458 // TestChainConfig_GetFeature_DefaultGasTables sets that GetFeatures gets expected feature values for default fork configs. 459 func TestChainConfig_GetFeature7_DefaultDifficulty(t *testing.T) { 460 c := getDefaultChainConfigSorted() 461 var tables = map[*big.Int]string{ 462 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block, big.NewInt(1)): "", 463 DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block: "homestead", 464 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("Homestead").Block, big.NewInt(1)): "homestead", 465 466 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block, big.NewInt(1)): "homestead", 467 DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block: "homestead", 468 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("GasReprice").Block, big.NewInt(1)): "homestead", 469 470 big.NewInt(0).Sub(DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block, big.NewInt(1)): "homestead", 471 DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block: "ecip1010", 472 big.NewInt(0).Add(DefaultConfigMainnet.ChainConfig.ForkByName("Diehard").Block, big.NewInt(1)): "ecip1010", 473 } 474 for block, expected := range tables { 475 feat, fork, ok := c.GetFeature(block, "difficulty") 476 if expected != "" { 477 if !ok { 478 t.Errorf("Expected difficulty feature to exist. feat: %v, fork: %v, block: %v", feat, fork, block) 479 } 480 val, ok := feat.GetString("type") 481 if !ok { 482 t.Errorf("failed to get value for difficulty feature. feat: %v, fork: %v, block: %v", feat, fork, block) 483 } 484 if val != expected { 485 t.Errorf("want: %v, got: %v", expected, val) 486 } 487 } else { 488 if ok { 489 t.Errorf("Unexpected difficulty feature exists. feat: %v, fork: %v, block: %v", feat, fork, block) 490 } 491 } 492 } 493 } 494 495 func TestChainConfig_SortForks(t *testing.T) { 496 // check code data default 497 c := getDefaultChainConfigSorted() 498 n := big.NewInt(0) 499 for _, fork := range c.Forks { 500 if n.Cmp(fork.Block) > 0 { 501 t.Errorf("unexpected fork block: %v is greater than: %v", fork.Block, n) 502 } 503 n = fork.Block 504 } 505 506 // introduce disorder 507 f := &Fork{} 508 f.Block = big.NewInt(0).Sub(c.Forks[0].Block, big.NewInt(1)) 509 c.Forks = append(c.Forks, f) // last fork should be out of order 510 511 c.SortForks() 512 n = big.NewInt(0) 513 for _, fork := range c.Forks { 514 if n.Cmp(fork.Block) > 0 { 515 t.Errorf("unexpected fork block: %v is greater than: %v", fork.Block, n) 516 } 517 n = fork.Block 518 } 519 } 520 521 func TestChainConfigGetSet(t *testing.T) { 522 c := getDefaultChainConfigSorted() 523 set := SetCacheChainConfig(&SufficientChainConfig{ChainConfig: c}) 524 525 if set == nil { 526 t.Fatal("set returned nil") 527 } 528 529 got := GetCacheChainConfig() 530 if got == nil { 531 t.Fatal("get returned nil") 532 } 533 534 // create new "checkpoint" fork for testing 535 checkpoint := &Fork{ 536 Name: "checkpoint", 537 Block: big.NewInt(1930000), 538 RequiredHash: common.HexToHash("0xabc65e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ad123"), 539 } 540 c.Forks = append(c.Forks, checkpoint) 541 542 got.ChainConfig.Forks = c.Forks 543 didSet := SetCacheChainConfig(got) 544 if !reflect.DeepEqual(got, didSet) { 545 t.Errorf("got: %v, want: %v", didSet, got) 546 } 547 548 if f := set.ChainConfig.ForkByName("checkpoint"); f == nil { 549 t.Errorf("got: %v, want: %v", f, checkpoint) 550 } 551 } 552 553 func TestChainConfig_GetLastRequiredHashFork(t *testing.T) { 554 c := getDefaultChainConfigSorted() 555 556 daoFork := c.ForkByName("The DAO Hard Fork") 557 got, want := c.GetLatestRequiredHashFork(big.NewInt(1920000)), daoFork 558 559 // sanity check 560 if want == nil { 561 t.Fatal("nil want hard fork") 562 } 563 564 if got == nil { 565 t.Fatalf("got: %v, want: %s", got, want.Name) 566 } 567 if got.RequiredHash.Hex() != "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f" { 568 t.Errorf("got: %v, want: %s", got, got.RequiredHash.Hex()) 569 } 570 if got.Block.Cmp(big.NewInt(1920000)) != 0 { 571 t.Errorf("got: %d, want: %d", got.Block, 1920000) 572 } 573 574 // create new "checkpoint" fork for testing 575 checkpoint := &Fork{ 576 Name: "checkpoint", 577 Block: big.NewInt(1930000), 578 RequiredHash: common.HexToHash("0xabc65e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ad123"), 579 } 580 c.Forks = append(c.Forks, checkpoint) 581 582 // Noting that config forks do not have to be sorted for this function to work. 583 //c.SortForks() 584 585 got, want = c.GetLatestRequiredHashFork(big.NewInt(1930000)), checkpoint 586 if !reflect.DeepEqual(got, want) { 587 t.Errorf("got: %v, want: %v", got, want) 588 } 589 590 // should use dao fork, not checkpoint since block n has not reached checkpoint 591 got, want = c.GetLatestRequiredHashFork(big.NewInt(1920001)), daoFork 592 if !reflect.DeepEqual(got, want) { 593 t.Errorf("got: %v, want: %v", got, want) 594 } 595 } 596 597 func TestChainConfig_GetSigner(t *testing.T) { 598 c := getDefaultChainConfigSorted() 599 var forkBlocks []*big.Int 600 for _, fork := range c.Forks { 601 forkBlocks = append(forkBlocks, fork.Block) 602 } 603 604 blockMinus := big.NewInt(-2) 605 blockPlus := big.NewInt(2) 606 607 for _, block := range forkBlocks { 608 bottom := big.NewInt(0).Add(block, blockMinus) 609 top := big.NewInt(0).Add(block, blockPlus) 610 current := bottom 611 for current.Cmp(top) <= 0 { 612 signer := c.GetSigner(current) 613 feat, _, configured := c.GetFeature(current, "eip155") 614 if !configured { 615 if !signer.Equal(types.BasicSigner{}) { 616 t.Errorf("expected basic signer, block: %v", current) 617 } 618 } else { 619 cid, ok := feat.GetBigInt("chainID") 620 if !ok { 621 t.Errorf("unexpected missing eip155 chainid, block: %v", current) 622 } 623 shouldb := types.NewChainIdSigner(cid) 624 if !signer.Equal(shouldb) { 625 t.Errorf("want: %v, got: %v", shouldb, current) 626 } 627 } 628 current = big.NewInt(0).Add(current, big.NewInt(1)) 629 } 630 } 631 632 } 633 634 func TestResolvePath(t *testing.T) { 635 cases := []struct { 636 args []string 637 want string 638 }{ 639 { 640 args: []string{"./a/b/config.csv", "."}, 641 want: filepath.Clean("a/b/config.csv"), 642 }, 643 { 644 args: []string{"./a/b/config.csv", ""}, 645 want: filepath.Clean("a/b/config.csv"), 646 }, 647 { 648 args: []string{"./a/b/config.csv", "./a/b/config.json"}, 649 want: filepath.Clean("a/b/a/b/config.csv"), 650 }, 651 { 652 args: []string{"config.csv", "a/b"}, 653 want: filepath.Clean("a/config.csv"), // since resolvePath expects b|config.csv to be adjacent (neighboring filepaths), ie. 'b' should be a file 654 }, 655 { 656 args: []string{"config.csv", "a/b/config.json"}, 657 want: filepath.Clean("a/b/config.csv"), 658 }, 659 { 660 args: []string{"test.txt", "some/dir/conf.json"}, 661 want: filepath.Clean("some/dir/test.txt"), 662 }, 663 { 664 args: []string{"test.txt", "./some/dir/conf.json"}, 665 want: filepath.Clean("some/dir/test.txt"), 666 }, 667 { 668 args: []string{"./test.txt", "some/dir/conf.json"}, 669 want: filepath.Clean("some/dir/test.txt"), 670 }, 671 { 672 args: []string{"./test.txt", "./some/dir/conf.json"}, 673 want: filepath.Clean("some/dir/test.txt"), 674 }, 675 { 676 args: []string{"../test.txt", "some/dir/conf.json"}, 677 want: filepath.Clean("some/test.txt"), 678 }, 679 { 680 args: []string{"../test.txt", "/some/dir/conf.json"}, 681 want: filepath.Clean("/some/test.txt"), 682 }, 683 { 684 args: []string{"../test.txt", "some/dir/.././conf.json"}, 685 want: filepath.Clean("test.txt"), 686 }, 687 { 688 args: []string{"../test.txt", "conf.json"}, 689 want: filepath.Clean("../test.txt"), 690 }, 691 { 692 args: []string{"../../../../a/b/c/d/test.txt", "conf.json"}, 693 want: filepath.Clean("../../../../a/b/c/d/test.txt"), 694 }, 695 { 696 args: []string{"../../../../a/b/c/d/test.txt", "a/b/c/d/conf.json"}, 697 want: filepath.Clean("a/b/c/d/test.txt"), 698 }, 699 } 700 for _, c := range cases { 701 t.Run(c.args[0]+"+"+c.args[1], func(t *testing.T) { 702 if got := resolvePath(c.args[0], c.args[1]); got != c.want { 703 t.Errorf("got: %v, want: %v", got, c.want) 704 } 705 }) 706 } 707 } 708 709 func makeOKSufficientChainConfig(dump *GenesisDump, config *ChainConfig) *SufficientChainConfig { 710 // Setup. 711 whole := &SufficientChainConfig{} 712 whole.Identity = "testID" 713 whole.Network = 3 714 whole.Name = "testable" 715 whole.Consensus = "ethash" 716 whole.Genesis = dump 717 whole.ChainConfig = config 718 whole.Bootstrap = []string{ 719 "enode://e809c4a2fec7daed400e5e28564e23693b23b2cc5a019b612505631bbe7b9ccf709c1796d2a3d29ef2b045f210caf51e3c4f5b6d3587d43ad5d6397526fa6179@174.112.32.157:30303", 720 "enode://6e538e7c1280f0a31ff08b382db5302480f775480b8e68f8febca0ceff81e4b19153c6f8bf60313b93bef2cc34d34e1df41317de0ce613a201d1660a788a03e2@52.206.67.235:30303", 721 "enode://5fbfb426fbb46f8b8c1bd3dd140f5b511da558cd37d60844b525909ab82e13a25ee722293c829e52cb65c2305b1637fa9a2ea4d6634a224d5f400bfe244ac0de@162.243.55.45:30303", 722 "enode://42d8f29d1db5f4b2947cd5c3d76c6d0d3697e6b9b3430c3d41e46b4bb77655433aeedc25d4b4ea9d8214b6a43008ba67199374a9b53633301bca0cd20c6928ab@104.155.176.151:30303", 723 "enode://814920f1ec9510aa9ea1c8f79d8b6e6a462045f09caa2ae4055b0f34f7416fca6facd3dd45f1cf1673c0209e0503f02776b8ff94020e98b6679a0dc561b4eba0@104.154.136.117:30303", 724 "enode://72e445f4e89c0f476d404bc40478b0df83a5b500d2d2e850e08eb1af0cd464ab86db6160d0fde64bd77d5f0d33507ae19035671b3c74fec126d6e28787669740@104.198.71.200:30303", 725 "enode://5cd218959f8263bc3721d7789070806b0adff1a0ed3f95ec886fb469f9362c7507e3b32b256550b9a7964a23a938e8d42d45a0c34b332bfebc54b29081e83b93@35.187.57.94:30303", 726 "enode://39abab9d2a41f53298c0c9dc6bbca57b0840c3ba9dccf42aa27316addc1b7e56ade32a0a9f7f52d6c5db4fe74d8824bcedfeaecf1a4e533cacb71cf8100a9442@144.76.238.49:30303", 727 "enode://f50e675a34f471af2438b921914b5f06499c7438f3146f6b8936f1faeb50b8a91d0d0c24fb05a66f05865cd58c24da3e664d0def806172ddd0d4c5bdbf37747e@144.76.238.49:30306", 728 } 729 return whole 730 } 731 732 // TestSufficientChainConfig_IsValid tests against defaulty dumps and chainconfigs. 733 func TestSufficientChainConfig_IsValid(t *testing.T) { 734 dumps := []*GenesisDump{DefaultConfigMainnet.Genesis, DefaultConfigMorden.Genesis} 735 configs := []*ChainConfig{DefaultConfigMainnet.ChainConfig, DefaultConfigMorden.ChainConfig} 736 737 for i, dump := range dumps { 738 for j, config := range configs { 739 // Make sure initial ok config is ok. 740 scc := makeOKSufficientChainConfig(dump, config) 741 if s, ok := scc.IsValid(); !ok { 742 t.Errorf("unexpected notok: %v @ %v/%v", s, i, j) 743 } 744 745 // Remove each required field and ensure is NOT ok. 746 o1 := scc.Identity 747 scc.Identity = "" 748 if s, ok := scc.IsValid(); ok { 749 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 750 } 751 scc.Identity = o1 752 753 o2 := scc.Network 754 scc.Network = 0 755 if s, ok := scc.IsValid(); ok { 756 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 757 } 758 scc.Network = o2 759 760 o3 := scc.Consensus 761 scc.Consensus = "asdf" 762 if s, ok := scc.IsValid(); ok { 763 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 764 } 765 scc.Consensus = o3 766 767 o4 := scc.Consensus 768 scc.Consensus = "" 769 if s, ok := scc.IsValid(); ok { 770 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 771 } 772 scc.Consensus = o4 773 774 o := scc.Genesis 775 scc.Genesis = nil 776 if s, ok := scc.IsValid(); ok { 777 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 778 } 779 scc.Genesis = o 780 781 oo := scc.ChainConfig 782 scc.ChainConfig = nil 783 if s, ok := scc.IsValid(); ok { 784 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 785 } 786 scc.ChainConfig = oo 787 788 ooo := scc.Bootstrap 789 scc.Bootstrap = []string{} 790 if s, ok := scc.IsValid(); !ok { 791 t.Errorf("unexpected notok: %v @ %v/%v", s, i, j) 792 } 793 scc.Bootstrap = ooo 794 795 oooo := scc.Genesis.Nonce 796 scc.Genesis.Nonce = "" 797 if s, ok := scc.IsValid(); ok { 798 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 799 } 800 scc.Genesis.Nonce = oooo 801 802 ooooo := scc.Genesis.Nonce 803 scc.Genesis.Nonce = "0xasdf" 804 if s, ok := scc.IsValid(); ok { 805 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 806 } 807 scc.Genesis.Nonce = ooooo 808 809 oooooo := scc.Genesis.GasLimit 810 scc.Genesis.GasLimit = "0xasdf" 811 if s, ok := scc.IsValid(); ok { 812 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 813 } 814 scc.Genesis.GasLimit = oooooo 815 816 ooooooo0 := scc.Genesis.Difficulty 817 scc.Genesis.Difficulty = "0xasdf" 818 if s, ok := scc.IsValid(); ok { 819 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 820 } 821 scc.Genesis.Difficulty = ooooooo0 822 823 ooooooo00 := scc.ChainConfig.Forks 824 scc.ChainConfig.Forks = []*Fork{} 825 if s, ok := scc.IsValid(); ok { 826 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 827 } 828 scc.ChainConfig.Forks = ooooooo00 829 830 ooooooo1 := scc.ChainConfig.Forks 831 scc.ChainConfig.Forks = nil 832 if s, ok := scc.IsValid(); ok { 833 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 834 } 835 scc.ChainConfig.Forks = ooooooo1 836 837 scc = &SufficientChainConfig{} 838 if s, ok := scc.IsValid(); ok { 839 t.Errorf("unexpected ok: %v @ %v/%v", s, i, j) 840 } 841 } 842 } 843 } 844 845 func TestGenesisAllocationError(t *testing.T) { 846 _, err := parseExternalChainConfig("testdata/test.json", func(path string) (io.ReadCloser, error) { return os.Open(path) }) 847 if err == nil { 848 t.Error("expected error, got nil") 849 } 850 if !strings.Contains(err.Error(), "\"alloc\" values already set") { 851 t.Error("invalid error message") 852 } 853 }