github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/state_processor_test.go (about) 1 package core 2 3 import ( 4 "math/big" 5 "math/rand" 6 "testing" 7 "time" 8 9 "fmt" 10 11 "github.com/ethereumproject/go-ethereum/common" 12 "github.com/ethereumproject/go-ethereum/core/state" 13 "github.com/ethereumproject/go-ethereum/core/types" 14 "github.com/ethereumproject/go-ethereum/ethdb" 15 ) 16 17 var ( 18 defaultEraLength *big.Int = big.NewInt(5000000) 19 ) 20 21 // Unit tests. 22 23 // Use default era length 5,000,000 24 func TestGetBlockEra1(t *testing.T) { 25 cases := map[*big.Int]*big.Int{ 26 big.NewInt(0): big.NewInt(0), 27 big.NewInt(1): big.NewInt(0), 28 big.NewInt(1914999): big.NewInt(0), 29 big.NewInt(1915000): big.NewInt(0), 30 big.NewInt(1915001): big.NewInt(0), 31 big.NewInt(4999999): big.NewInt(0), 32 big.NewInt(5000000): big.NewInt(0), 33 big.NewInt(5000001): big.NewInt(1), 34 big.NewInt(9999999): big.NewInt(1), 35 big.NewInt(10000000): big.NewInt(1), 36 big.NewInt(10000001): big.NewInt(2), 37 big.NewInt(14999999): big.NewInt(2), 38 big.NewInt(15000000): big.NewInt(2), 39 big.NewInt(15000001): big.NewInt(3), 40 big.NewInt(100000001): big.NewInt(20), 41 big.NewInt(123456789): big.NewInt(24), 42 } 43 44 for bn, expectedEra := range cases { 45 gotEra := GetBlockEra(bn, defaultEraLength) 46 if gotEra.Cmp(expectedEra) != 0 { 47 t.Errorf("got: %v, want: %v", gotEra, expectedEra) 48 } 49 } 50 } 51 52 // Use custom era length 2 53 func TestGetBlockEra2(t *testing.T) { 54 cases := map[*big.Int]*big.Int{ 55 big.NewInt(0): big.NewInt(0), 56 big.NewInt(1): big.NewInt(0), 57 big.NewInt(2): big.NewInt(0), 58 big.NewInt(3): big.NewInt(1), 59 big.NewInt(4): big.NewInt(1), 60 big.NewInt(5): big.NewInt(2), 61 big.NewInt(6): big.NewInt(2), 62 big.NewInt(7): big.NewInt(3), 63 big.NewInt(8): big.NewInt(3), 64 big.NewInt(9): big.NewInt(4), 65 big.NewInt(10): big.NewInt(4), 66 big.NewInt(11): big.NewInt(5), 67 big.NewInt(12): big.NewInt(5), 68 } 69 70 for bn, expectedEra := range cases { 71 gotEra := GetBlockEra(bn, big.NewInt(2)) 72 if gotEra.Cmp(expectedEra) != 0 { 73 t.Errorf("got: %v, want: %v", gotEra, expectedEra) 74 } 75 } 76 } 77 78 func TestGetBlockWinnerRewardByEra(t *testing.T) { 79 80 cases := map[*big.Int]*big.Int{ 81 big.NewInt(0): MaximumBlockReward, 82 big.NewInt(1): MaximumBlockReward, 83 big.NewInt(4999999): MaximumBlockReward, 84 big.NewInt(5000000): MaximumBlockReward, 85 big.NewInt(5000001): big.NewInt(4e+18), 86 big.NewInt(9999999): big.NewInt(4e+18), 87 big.NewInt(10000000): big.NewInt(4e+18), 88 big.NewInt(10000001): big.NewInt(3.2e+18), 89 big.NewInt(14999999): big.NewInt(3.2e+18), 90 big.NewInt(15000000): big.NewInt(3.2e+18), 91 big.NewInt(15000001): big.NewInt(2.56e+18), 92 } 93 94 for bn, expectedReward := range cases { 95 gotReward := GetBlockWinnerRewardByEra(GetBlockEra(bn, defaultEraLength)) 96 if gotReward.Cmp(expectedReward) != 0 { 97 t.Errorf("@ %v, got: %v, want: %v", bn, gotReward, expectedReward) 98 } 99 if gotReward.Cmp(big.NewInt(0)) <= 0 { 100 t.Errorf("@ %v, got: %v, want: %v", bn, gotReward, expectedReward) 101 } 102 if gotReward.Cmp(MaximumBlockReward) > 0 { 103 t.Errorf("@ %v, got: %v, want %v", bn, gotReward, expectedReward) 104 } 105 } 106 107 } 108 109 func TestGetBlockUncleRewardByEra(t *testing.T) { 110 111 var we1, we2, we3, we4 *big.Int = new(big.Int), new(big.Int), new(big.Int), new(big.Int) 112 113 // manually divide maxblockreward/32 to compare to got 114 we2.Div(GetBlockWinnerRewardByEra(GetBlockEra(big.NewInt(5000001), defaultEraLength)), big.NewInt(32)) 115 we3.Div(GetBlockWinnerRewardByEra(GetBlockEra(big.NewInt(10000001), defaultEraLength)), big.NewInt(32)) 116 we4.Div(GetBlockWinnerRewardByEra(GetBlockEra(big.NewInt(15000001), defaultEraLength)), big.NewInt(32)) 117 118 cases := map[*big.Int]*big.Int{ 119 big.NewInt(0): nil, 120 big.NewInt(1): nil, 121 big.NewInt(4999999): nil, 122 big.NewInt(5000000): nil, 123 big.NewInt(5000001): we2, 124 big.NewInt(9999999): we2, 125 big.NewInt(10000000): we2, 126 big.NewInt(10000001): we3, 127 big.NewInt(14999999): we3, 128 big.NewInt(15000000): we3, 129 big.NewInt(15000001): we4, 130 } 131 132 for bn, want := range cases { 133 134 era := GetBlockEra(bn, defaultEraLength) 135 136 var header, uncle *types.Header = &types.Header{}, &types.Header{} 137 header.Number = bn 138 139 rand.Seed(time.Now().UTC().UnixNano()) 140 uncle.Number = big.NewInt(0).Sub(header.Number, big.NewInt(int64(rand.Int31n(int32(7))))) 141 142 got := GetBlockUncleRewardByEra(era, header, uncle) 143 144 // "Era 1" 145 if want == nil { 146 we1.Add(uncle.Number, big8) // 2,534,998 + 8 = 2,535,006 147 we1.Sub(we1, header.Number) // 2,535,006 - 2,534,999 = 7 148 we1.Mul(we1, MaximumBlockReward) // 7 * 5e+18 = 35e+18 149 we1.Div(we1, big8) // 35e+18 / 8 = 7/8 * 5e+18 150 151 if got.Cmp(we1) != 0 { 152 t.Errorf("@ %v, want: %v, got: %v", bn, we1, got) 153 } 154 } else { 155 if got.Cmp(want) != 0 { 156 t.Errorf("@ %v, want: %v, got: %v", bn, want, got) 157 } 158 } 159 } 160 } 161 162 func TestGetBlockWinnerRewardForUnclesByEra(t *testing.T) { 163 164 // "want era 1", "want era 2", ... 165 var we1, we2, we3, we4 *big.Int = new(big.Int), new(big.Int), new(big.Int), new(big.Int) 166 we1.Div(MaximumBlockReward, big.NewInt(32)) 167 we2.Div(GetBlockWinnerRewardByEra(big.NewInt(1)), big.NewInt(32)) 168 we3.Div(GetBlockWinnerRewardByEra(big.NewInt(2)), big.NewInt(32)) 169 we4.Div(GetBlockWinnerRewardByEra(big.NewInt(3)), big.NewInt(32)) 170 171 cases := map[*big.Int]*big.Int{ 172 big.NewInt(0): we1, 173 big.NewInt(1): we1, 174 big.NewInt(4999999): we1, 175 big.NewInt(5000000): we1, 176 big.NewInt(5000001): we2, 177 big.NewInt(9999999): we2, 178 big.NewInt(10000000): we2, 179 big.NewInt(10000001): we3, 180 big.NewInt(14999999): we3, 181 big.NewInt(15000000): we3, 182 big.NewInt(15000001): we4, 183 } 184 185 var uncleSingle, uncleDouble []*types.Header = []*types.Header{{}}, []*types.Header{{}, {}} 186 187 for bn, want := range cases { 188 // test single uncle 189 got := GetBlockWinnerRewardForUnclesByEra(GetBlockEra(bn, defaultEraLength), uncleSingle) 190 if got.Cmp(want) != 0 { 191 t.Errorf("@ %v: want: %v, got: %v", bn, want, got) 192 } 193 194 // test double uncle 195 got = GetBlockWinnerRewardForUnclesByEra(GetBlockEra(bn, defaultEraLength), uncleDouble) 196 dub := new(big.Int) 197 if got.Cmp(dub.Mul(want, big.NewInt(2))) != 0 { 198 t.Errorf("@ %v: want: %v, got: %v", bn, want, got) 199 } 200 } 201 } 202 203 // Integration tests. 204 // 205 // There are two kinds of integration tests: accumulating and non-accumulation. 206 // Accumulating tests check simulated accrual of a 207 // winner and two uncle accounts over the winnings of many mined blocks. 208 // If ecip1017 feature is not included in the hardcoded mainnet configuration, it will be temporarily 209 // included and tested in this test. 210 // This tests not only reward changes, but summations and state tallies over time. 211 // Non-accumulating tests check the one-off reward structure at any point 212 // over the specified era period. 213 // Currently tested eras are 1, 2, 3, and the beginning of 4. 214 // Both kinds of tests rely on manual calculations of 'want' account balance state, 215 // and purposely avoid using existing calculation functions in state_processor.go. 216 // Check points confirming calculations are at and around the 'boundaries' of forks and eras. 217 // 218 // Helpers. 219 220 // expectedEraForTesting is a 1-indexed version of era number, 221 // used exclusively for testing. 222 type expectedEraForTesting int 223 224 const ( 225 era1 expectedEraForTesting = iota + 1 226 era2 227 era3 228 era4 229 ) 230 231 type expectedRewards map[common.Address]*big.Int 232 233 func calculateExpectedEraRewards(era expectedEraForTesting, numUncles int) expectedRewards { 234 wr := new(big.Int) 235 wur := new(big.Int) 236 ur := new(big.Int) 237 switch era { 238 case era1: 239 wr = Era1WinnerReward 240 wur = Era1WinnerUncleReward 241 ur = Era1UncleReward 242 case era2: 243 wr = Era2WinnerReward 244 wur = Era2WinnerUncleReward 245 ur = Era2UncleReward 246 case era3: 247 wr = Era3WinnerReward 248 wur = Era3WinnerUncleReward 249 ur = Era3UncleReward 250 case era4: 251 wr = Era4WinnerReward 252 wur = Era4WinnerUncleReward 253 ur = Era4UncleReward 254 } 255 return expectedRewards{ 256 WinnerCoinbase: new(big.Int).Add(wr, new(big.Int).Mul(wur, big.NewInt(int64(numUncles)))), 257 Uncle1Coinbase: ur, 258 Uncle2Coinbase: ur, 259 } 260 } 261 262 // expectedEraFromBlockNumber is similar to GetBlockEra, but it 263 // returns a 1-indexed version of the number of type expectedEraForTesting 264 func expectedEraFromBlockNumber(i, eralen *big.Int, t *testing.T) expectedEraForTesting { 265 e := GetBlockEra(i, eralen) 266 ePlusOne := new(big.Int).Add(e, big.NewInt(1)) // since expectedEraForTesting is not 0-indexed; iota + 1 267 ei := ePlusOne.Int64() 268 expEra := int(ei) 269 if expEra > 4 || expEra < 1 { 270 t.Fatalf("Unexpected era value, want 1 < e < 5, got: %d", expEra) 271 } 272 return expectedEraForTesting(expEra) 273 } 274 275 type expectedRewardCase struct { 276 eraNum expectedEraForTesting 277 block *big.Int 278 rewards expectedRewards 279 } 280 281 // String implements stringer interface for expectedRewards 282 // Useful for logging tests for visual confirmation. 283 func (r expectedRewards) String() string { 284 return fmt.Sprintf("w: %d, u1: %d, u2: %d", r[WinnerCoinbase], r[Uncle1Coinbase], r[Uncle2Coinbase]) 285 } 286 287 // String implements stringer interface for expectedRewardCase -- 288 // useful for double-checking test cases with t.Log 289 // to visually ensure getting all desired test cases. 290 func (c *expectedRewardCase) String() string { 291 return fmt.Sprintf("block=%d era=%d rewards=%s", c.block, c.eraNum, c.rewards) 292 } 293 294 // makeExpectedRewardCasesForConfig makes an array of expectedRewardCases. 295 // It checks boundary cases for era length and fork numbers. 296 // 297 // An example of output: 298 // ---- 299 // { 300 // // mainnet 301 // { 302 // block: big.NewInt(2), 303 // rewards: calculateExpectedEraRewards(era1, 1), 304 // }, 305 // ... 306 // { 307 // block: big.NewInt(20000000), 308 // rewards: calculateExpectedEraRewards(era4, 1), 309 // }, 310 // }, 311 func makeExpectedRewardCasesForConfig(c *ChainConfig, numUncles int, t *testing.T) []expectedRewardCase { 312 erasToTest := []expectedEraForTesting{era1, era2, era3} 313 eraLen := new(big.Int) 314 feat, _, configured := c.HasFeature("reward") 315 if !configured { 316 eraLen = defaultEraLength 317 } else { 318 elen, ok := feat.GetBigInt("era") 319 if !ok { 320 t.Error("unexpected reward length not configured") 321 } else { 322 eraLen = elen 323 } 324 } 325 326 var cases []expectedRewardCase 327 var boundaryDiffs = []int64{-2, -1, 0, 1, 2} 328 329 // Include trivial initial early block values. 330 for _, i := range []*big.Int{big.NewInt(2), big.NewInt(13)} { 331 cases = append(cases, expectedRewardCase{ 332 eraNum: era1, 333 block: i, 334 rewards: calculateExpectedEraRewards(era1, numUncles), 335 }) 336 } 337 338 // Test boundaries of forks. 339 for _, f := range c.Forks { 340 fn := f.Block 341 for _, d := range boundaryDiffs { 342 fnb := new(big.Int).Add(fn, big.NewInt(d)) 343 if fnb.Sign() < 1 { 344 t.Fatalf("unexpected 0 or neg block number: %d", fnb) 345 } 346 expEra := expectedEraFromBlockNumber(fnb, eraLen, t) 347 348 cases = append(cases, expectedRewardCase{ 349 eraNum: expEra, 350 block: fnb, 351 rewards: calculateExpectedEraRewards(expEra, numUncles), 352 }) 353 } 354 } 355 356 // Test boundaries of era. 357 for _, e := range erasToTest { 358 for _, d := range boundaryDiffs { 359 eb := big.NewInt(int64(e)) 360 eraBoundary := new(big.Int).Mul(eb, eraLen) 361 bn := new(big.Int).Add(eraBoundary, big.NewInt(d)) 362 if bn.Sign() < 1 { 363 t.Fatalf("unexpected 0 or neg block number: %d", bn) 364 } 365 era := expectedEraFromBlockNumber(bn, eraLen, t) 366 cases = append(cases, expectedRewardCase{ 367 eraNum: era, 368 block: bn, 369 rewards: calculateExpectedEraRewards(era, numUncles), 370 }) 371 } 372 } 373 374 return cases 375 } 376 377 // Accruing over block cases simulates miner account winning many times. 378 // Uses maps of running sums for winner & 2 uncles to keep tally. 379 func TestAccumulateRewards1(t *testing.T) { 380 configs := []*ChainConfig{DefaultConfigMainnet.ChainConfig, DefaultConfigMorden.ChainConfig} 381 cases := [][]expectedRewardCase{} 382 for _, c := range configs { 383 cases = append(cases, makeExpectedRewardCasesForConfig(c, 2, t)) 384 } 385 386 // t.Logf("Accruing balances over cases. 2 uncles. Configs mainnet=0, morden=1") 387 for i, config := range configs { 388 // Set up era len by chain configurations. 389 feat, _, exists := config.HasFeature("reward") 390 eraLen := new(big.Int) 391 if !exists { 392 // t.Logf("No ecip1017 feature installed for config=%d, setting up a placeholder ecip1017 feature for testing.", i) 393 dhFork := config.ForkByName("Diehard") 394 dhFork.Features = append(dhFork.Features, &ForkFeature{ 395 ID: "reward", 396 Options: ChainFeatureConfigOptions{ 397 "type": "ecip1017", 398 "era": 5000000, // for mainnet will be 5m 399 }, 400 }) 401 feat, _, exists = config.HasFeature("reward") 402 if !exists { 403 t.Fatal("no expected feature installed") 404 } 405 } 406 eraLen, ok := feat.GetBigInt("era") 407 if !ok { 408 t.Error("No era length configured, is required.") 409 } 410 411 db, _ := ethdb.NewMemDatabase() 412 413 stateDB, err := state.New(common.Hash{}, state.NewDatabase(db)) 414 if err != nil { 415 t.Fatalf("could not open statedb: %v", err) 416 } 417 418 var header *types.Header = &types.Header{} 419 var uncles []*types.Header = []*types.Header{{}, {}} 420 421 if i == 0 { 422 header.Coinbase = common.StringToAddress("000d836201318ec6899a67540690382780743280") 423 uncles[0].Coinbase = common.StringToAddress("001762430ea9c3a26e5749afdb70da5f78ddbb8c") 424 uncles[1].Coinbase = common.StringToAddress("001d14804b399c6ef80e64576f657660804fec0b") 425 } else { 426 header.Coinbase = common.StringToAddress("0000000000000000000000000000000000000001") 427 uncles[0].Coinbase = common.StringToAddress("0000000000000000000000000000000000000002") 428 uncles[1].Coinbase = common.StringToAddress("0000000000000000000000000000000000000003") 429 } 430 431 // Manual tallies for reward accumulation. 432 winnerB, totalB := new(big.Int), new(big.Int) 433 unclesB := []*big.Int{new(big.Int), new(big.Int)} 434 435 winnerB = stateDB.GetBalance(header.Coinbase) 436 unclesB[0] = stateDB.GetBalance(uncles[0].Coinbase) 437 unclesB[1] = stateDB.GetBalance(uncles[1].Coinbase) 438 439 totalB.Add(totalB, winnerB) 440 totalB.Add(totalB, unclesB[0]) 441 totalB.Add(totalB, unclesB[1]) 442 443 if totalB.Cmp(big.NewInt(0)) != 0 { 444 t.Errorf("unexpected: %v", totalB) 445 } 446 447 for _, c := range cases[i] { 448 bn := c.block 449 era := GetBlockEra(bn, eraLen) 450 451 header.Number = bn 452 453 for i, uncle := range uncles { 454 455 // Randomize uncle numbers with bound ( n-1 <= uncleNum <= n-7 ), where n is current head number 456 // See yellowpaper@11.1 for ommer validation reference. I expect n-7 is 6th-generation ommer. 457 // Note that ommer nth-generation impacts reward only for "Era 1". 458 rand.Seed(time.Now().UTC().UnixNano()) 459 460 // 1 + [0..rand..7) == 1 + 0, 1 + 1, ... 1 + 6 461 un := new(big.Int).Add(big.NewInt(1), big.NewInt(int64(rand.Int31n(int32(7))))) 462 uncle.Number = new(big.Int).Sub(header.Number, un) // n - un 463 464 ur := GetBlockUncleRewardByEra(era, header, uncle) 465 unclesB[i].Add(unclesB[i], ur) 466 467 totalB.Add(totalB, ur) 468 } 469 470 wr := GetBlockWinnerRewardByEra(era) 471 wr.Add(wr, GetBlockWinnerRewardForUnclesByEra(era, uncles)) 472 winnerB.Add(winnerB, wr) 473 474 totalB.Add(totalB, winnerB) 475 476 AccumulateRewards(config, stateDB, header, uncles) 477 478 // Check balances. 479 //t.Logf("config=%d block=%d era=%d w:%d u1:%d u2:%d", i, bn, new(big.Int).Add(era, big.NewInt(1)), winnerB, unclesB[0], unclesB[1]) 480 if wb := stateDB.GetBalance(header.Coinbase); wb.Cmp(winnerB) != 0 { 481 t.Errorf("winner balance @ %v, want: %v, got: %v (config: %v)", bn, winnerB, wb, i) 482 } 483 if uB0 := stateDB.GetBalance(uncles[0].Coinbase); unclesB[0].Cmp(uB0) != 0 { 484 t.Errorf("uncle1 balance @ %v, want: %v, got: %v (config: %v)", bn, unclesB[0], uB0, i) 485 } 486 if uB1 := stateDB.GetBalance(uncles[1].Coinbase); unclesB[1].Cmp(uB1) != 0 { 487 t.Errorf("uncle2 balance @ %v, want: %v, got: %v (config: %v)", bn, unclesB[1], uB1, i) 488 } 489 } 490 db.Close() 491 } 492 } 493 494 var ( 495 WinnerCoinbase = common.StringToAddress("0000000000000000000000000000000000000001") 496 Uncle1Coinbase = common.StringToAddress("0000000000000000000000000000000000000002") 497 Uncle2Coinbase = common.StringToAddress("0000000000000000000000000000000000000003") 498 499 Era1WinnerReward = big.NewInt(5e+18) 500 Era1WinnerUncleReward = big.NewInt(156250000000000000) 501 Era1UncleReward = big.NewInt(4375000000000000000) 502 503 Era2WinnerReward = big.NewInt(4e+18) 504 Era2WinnerUncleReward = new(big.Int).Div(big.NewInt(4e+18), big32) 505 Era2UncleReward = new(big.Int).Div(big.NewInt(4e+18), big32) 506 507 Era3WinnerReward = new(big.Int).Mul(new(big.Int).Div(Era2WinnerReward, big.NewInt(5)), big.NewInt(4)) 508 Era3WinnerUncleReward = new(big.Int).Div(new(big.Int).Mul(new(big.Int).Div(Era2WinnerReward, big.NewInt(5)), big.NewInt(4)), big32) 509 Era3UncleReward = new(big.Int).Div(new(big.Int).Mul(new(big.Int).Div(Era2WinnerReward, big.NewInt(5)), big.NewInt(4)), big32) 510 511 Era4WinnerReward = new(big.Int).Mul(new(big.Int).Div(Era3WinnerReward, big.NewInt(5)), big.NewInt(4)) 512 Era4WinnerUncleReward = new(big.Int).Div(new(big.Int).Mul(new(big.Int).Div(Era3WinnerReward, big.NewInt(5)), big.NewInt(4)), big32) 513 Era4UncleReward = new(big.Int).Div(new(big.Int).Mul(new(big.Int).Div(Era3WinnerReward, big.NewInt(5)), big.NewInt(4)), big32) 514 ) 515 516 // Non-accruing over block cases simulates instance, 517 // ie. a miner wins once at different blocks. 518 // 519 // Tests winner includes 2 ommer headers. 520 func TestAccumulateRewards2_2Uncles(t *testing.T) { 521 522 // Order matters here; expected cases must be ordered the same. 523 // Will uses indexes to match expectations -> test outcomes. 524 configs := []*ChainConfig{DefaultConfigMainnet.ChainConfig, DefaultConfigMorden.ChainConfig} 525 cases := [][]expectedRewardCase{} 526 for _, c := range configs { 527 cases = append(cases, makeExpectedRewardCasesForConfig(c, 2, t)) 528 } 529 // t.Logf("Non-accruing balances over cases. 2 uncles. Configs mainnet=0, morden=1") 530 for i, config := range configs { 531 // Here's where cases slice is assign according to config slice. 532 for _, c := range cases[i] { 533 db, _ := ethdb.NewMemDatabase() 534 stateDB, err := state.New(common.Hash{}, state.NewDatabase(db)) 535 if err != nil { 536 t.Fatalf("could not open statedb: %v", err) 537 } 538 539 var winner *types.Header = &types.Header{ 540 Number: c.block, 541 Coinbase: WinnerCoinbase, 542 } 543 var uncles []*types.Header = []*types.Header{{ 544 Number: new(big.Int).Sub(c.block, common.Big1), // use 1st-generation ommer, since random n-[1,7) is tested by accrual above 545 Coinbase: Uncle1Coinbase, 546 }, { 547 Number: new(big.Int).Sub(c.block, common.Big1), 548 Coinbase: Uncle2Coinbase, 549 }} 550 551 gotWinnerBalance := stateDB.GetBalance(winner.Coinbase) 552 gotUncle1Balance := stateDB.GetBalance(Uncle1Coinbase) 553 gotUncle2Balance := stateDB.GetBalance(Uncle2Coinbase) 554 r := new(big.Int) 555 r.Add(gotWinnerBalance, gotUncle1Balance) 556 r.Add(r, gotUncle2Balance) 557 if r.Cmp(big.NewInt(0)) != 0 { 558 t.Errorf("unexpected: %v", r) 559 } 560 561 AccumulateRewards(config, stateDB, winner, uncles) 562 gotWinnerBalance = stateDB.GetBalance(winner.Coinbase) 563 gotUncle1Balance = stateDB.GetBalance(Uncle1Coinbase) 564 gotUncle2Balance = stateDB.GetBalance(Uncle2Coinbase) 565 566 // Use config if possible. Currently installed on testnet only. 567 // If not configured, assume default and still test it. 568 eraLen := new(big.Int) 569 feat, _, configured := config.HasFeature("reward") 570 if !configured { 571 eraLen = defaultEraLength 572 } else { 573 elen, ok := feat.GetBigInt("era") 574 if !ok { 575 t.Error("unexpected reward length not configured") 576 } else { 577 eraLen = elen 578 } 579 } 580 era := GetBlockEra(c.block, eraLen) 581 582 // Check we have expected era number. 583 indexed1EraNum := new(big.Int).Add(era, big.NewInt(1)) 584 if indexed1EraNum.Cmp(big.NewInt(int64(c.eraNum))) != 0 { 585 t.Errorf("era num mismatch, want: %v, got %v", c.eraNum, indexed1EraNum) 586 } 587 588 // Check balances. 589 // t.Logf("config=%d block=%d era=%d w:%d u1:%d u2:%d", i, c.block, c.eraNum, gotWinnerBalance, gotUncle1Balance, gotUncle2Balance) 590 if configured { 591 if gotWinnerBalance.Cmp(c.rewards[WinnerCoinbase]) != 0 { 592 t.Errorf("Config: %v | Era %v: winner balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, c.rewards[WinnerCoinbase], gotWinnerBalance, new(big.Int).Sub(gotWinnerBalance, c.rewards[WinnerCoinbase])) 593 } 594 if gotUncle1Balance.Cmp(c.rewards[Uncle1Coinbase]) != 0 { 595 t.Errorf("Config: %v | Era %v: uncle1 balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, c.rewards[Uncle1Coinbase], gotUncle1Balance, new(big.Int).Sub(gotUncle1Balance, c.rewards[Uncle1Coinbase])) 596 } 597 if gotUncle2Balance.Cmp(c.rewards[Uncle2Coinbase]) != 0 { 598 t.Errorf("Config: %v | Era %v: uncle2 balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, c.rewards[Uncle2Coinbase], gotUncle2Balance, new(big.Int).Sub(gotUncle2Balance, c.rewards[Uncle2Coinbase])) 599 } 600 } else { 601 if gotWinnerBalance.Cmp(new(big.Int).Add(Era1WinnerReward, new(big.Int).Mul(Era1WinnerUncleReward, big.NewInt(2)))) != 0 { 602 t.Errorf("Config: %v | Era %v: winner balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, new(big.Int).Add(Era1WinnerReward, new(big.Int).Mul(Era1WinnerUncleReward, big.NewInt(2))), gotWinnerBalance, new(big.Int).Sub(gotWinnerBalance, c.rewards[WinnerCoinbase])) 603 } 604 if gotUncle1Balance.Cmp(Era1UncleReward) != 0 { 605 t.Errorf("Config: %v | Era %v: uncle1 balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, Era1UncleReward, gotUncle1Balance, new(big.Int).Sub(gotUncle1Balance, c.rewards[Uncle1Coinbase])) 606 } 607 if gotUncle2Balance.Cmp(Era1UncleReward) != 0 { 608 t.Errorf("Config: %v | Era %v: uncle2 balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, Era1UncleReward, gotUncle2Balance, new(big.Int).Sub(gotUncle2Balance, c.rewards[Uncle2Coinbase])) 609 } 610 } 611 db.Close() 612 } 613 } 614 } 615 616 // Non-accruing over block cases simulates instance, 617 // ie. a miner wins once at different blocks. 618 // 619 // Tests winner includes 1 ommer header. 620 func TestAccumulateRewards3_1Uncle(t *testing.T) { 621 622 configs := []*ChainConfig{DefaultConfigMainnet.ChainConfig, DefaultConfigMorden.ChainConfig} 623 cases := [][]expectedRewardCase{} 624 for _, c := range configs { 625 cases = append(cases, makeExpectedRewardCasesForConfig(c, 1, t)) 626 } 627 // t.Logf("Non-accruing balances over cases. 1 uncle. Configs mainnet=0, morden=1") 628 for i, config := range configs { 629 for _, c := range cases[i] { 630 631 db, _ := ethdb.NewMemDatabase() 632 stateDB, err := state.New(common.Hash{}, state.NewDatabase(db)) 633 if err != nil { 634 t.Fatalf("could not open statedb: %v", err) 635 } 636 637 var winner *types.Header = &types.Header{ 638 Number: c.block, 639 Coinbase: WinnerCoinbase, 640 } 641 var uncles []*types.Header = []*types.Header{{ 642 Number: new(big.Int).Sub(c.block, common.Big1), // use 1st-generation ommer, since random n-[1,7) is tested by accrual above 643 Coinbase: Uncle1Coinbase, 644 }} 645 646 gotWinnerBalance := stateDB.GetBalance(winner.Coinbase) 647 gotUncle1Balance := stateDB.GetBalance(Uncle1Coinbase) 648 r := new(big.Int) 649 r.Add(gotWinnerBalance, gotUncle1Balance) 650 if r.Cmp(big.NewInt(0)) != 0 { 651 t.Errorf("unexpected: %v", r) 652 } 653 654 AccumulateRewards(config, stateDB, winner, uncles) 655 gotWinnerBalance = stateDB.GetBalance(winner.Coinbase) 656 gotUncle1Balance = stateDB.GetBalance(Uncle1Coinbase) 657 658 // Use config if possible. Currently on testnet only. 659 eraLen := new(big.Int) 660 feat, _, configured := config.HasFeature("reward") 661 if !configured { 662 eraLen = defaultEraLength 663 } else { 664 elen, ok := feat.GetBigInt("era") 665 if !ok { 666 t.Error("unexpected reward length not configured") 667 } else { 668 eraLen = elen 669 } 670 } 671 era := GetBlockEra(c.block, eraLen) 672 673 // Check we have expected era number. 674 indexed1EraNum := new(big.Int).Add(era, big.NewInt(1)) 675 if indexed1EraNum.Cmp(big.NewInt(int64(c.eraNum))) != 0 { 676 t.Errorf("era num mismatch, want: %v, got %v", c.eraNum, indexed1EraNum) 677 } 678 679 // Check balances. 680 // t.Logf("config=%d block=%d era=%d w:%d u1:%d", i, c.block, c.eraNum, gotWinnerBalance, gotUncle1Balance) 681 if configured { 682 if gotWinnerBalance.Cmp(c.rewards[WinnerCoinbase]) != 0 { 683 t.Errorf("Config: %v | Era %v: winner balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, c.rewards[WinnerCoinbase], gotWinnerBalance, new(big.Int).Sub(gotWinnerBalance, c.rewards[WinnerCoinbase])) 684 } 685 if gotUncle1Balance.Cmp(c.rewards[Uncle1Coinbase]) != 0 { 686 t.Errorf("Config: %v | Era %v: uncle1 balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, c.rewards[Uncle1Coinbase], gotUncle1Balance, new(big.Int).Sub(gotUncle1Balance, c.rewards[Uncle1Coinbase])) 687 } 688 } else { 689 if gotWinnerBalance.Cmp(new(big.Int).Add(Era1WinnerReward, new(big.Int).Mul(Era1WinnerUncleReward, big.NewInt(1)))) != 0 { 690 t.Errorf("Config: %v | Era %v: winner balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, new(big.Int).Add(Era1WinnerReward, new(big.Int).Mul(Era1WinnerUncleReward, big.NewInt(1))), gotWinnerBalance, new(big.Int).Sub(gotWinnerBalance, c.rewards[WinnerCoinbase])) 691 } 692 if gotUncle1Balance.Cmp(Era1UncleReward) != 0 { 693 t.Errorf("Config: %v | Era %v: uncle1 balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, Era1UncleReward, gotUncle1Balance, new(big.Int).Sub(gotUncle1Balance, c.rewards[Uncle1Coinbase])) 694 } 695 } 696 697 db.Close() 698 } 699 } 700 } 701 702 // Non-accruing over block cases simulates instance, 703 // ie. a miner wins once at different blocks. 704 // 705 // Tests winner includes 0 ommer headers. 706 func TestAccumulateRewards4_0Uncles(t *testing.T) { 707 708 configs := []*ChainConfig{DefaultConfigMainnet.ChainConfig, DefaultConfigMorden.ChainConfig} 709 cases := [][]expectedRewardCase{} 710 for _, c := range configs { 711 cases = append(cases, makeExpectedRewardCasesForConfig(c, 0, t)) 712 } 713 // t.Logf("Non-accruing balances over cases. 0 uncles. Configs mainnet=0, morden=1") 714 for i, config := range configs { 715 for _, c := range cases[i] { 716 717 db, _ := ethdb.NewMemDatabase() 718 stateDB, err := state.New(common.Hash{}, state.NewDatabase(db)) 719 if err != nil { 720 t.Fatalf("could not open statedb: %v", err) 721 } 722 723 var winner *types.Header = &types.Header{ 724 Number: c.block, 725 Coinbase: WinnerCoinbase, 726 } 727 var uncles []*types.Header = []*types.Header{} 728 729 gotWinnerBalance := stateDB.GetBalance(winner.Coinbase) 730 if gotWinnerBalance.Cmp(big.NewInt(0)) != 0 { 731 t.Errorf("unexpected: %v", gotWinnerBalance) 732 } 733 734 AccumulateRewards(config, stateDB, winner, uncles) 735 gotWinnerBalance = stateDB.GetBalance(winner.Coinbase) 736 737 // Use config if possible. Currently on testnet only. 738 eraLen := new(big.Int) 739 feat, _, configured := config.HasFeature("reward") 740 if !configured { 741 eraLen = defaultEraLength 742 } else { 743 elen, ok := feat.GetBigInt("era") 744 if !ok { 745 t.Error("unexpected reward length not configured") 746 } else { 747 eraLen = elen 748 } 749 } 750 era := GetBlockEra(c.block, eraLen) 751 752 // Check balances. 753 // t.Logf("config=%d block=%d era=%d w:%d", i, c.block, c.eraNum, gotWinnerBalance) 754 if configured { 755 if gotWinnerBalance.Cmp(c.rewards[WinnerCoinbase]) != 0 { 756 t.Errorf("Config: %v | Era %v: winner balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, c.rewards[WinnerCoinbase], gotWinnerBalance, new(big.Int).Sub(gotWinnerBalance, c.rewards[WinnerCoinbase])) 757 } 758 } else { 759 if gotWinnerBalance.Cmp(Era1WinnerReward) != 0 { 760 t.Errorf("Config: %v | Era %v: winner balance @ %v, want: %v, got: %v, \n-> diff: %v", i, era, c.block, Era1WinnerReward, gotWinnerBalance, new(big.Int).Sub(gotWinnerBalance, c.rewards[WinnerCoinbase])) 761 } 762 } 763 764 db.Close() 765 } 766 } 767 }