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  }