github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/consensus/dpos/dpos_test.go (about)

     1  // Copyright 2019 The go-vnt Authors
     2  // This file is part of the go-vnt library.
     3  //
     4  // The go-vnt library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-vnt library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package dpos
    18  
    19  import (
    20  	"math/big"
    21  	"testing"
    22  
    23  	"github.com/vntchain/go-vnt/common"
    24  	"github.com/vntchain/go-vnt/core/types"
    25  	"github.com/vntchain/go-vnt/core/vm/election"
    26  	"github.com/vntchain/go-vnt/params"
    27  )
    28  
    29  func TestUpdateTime(t *testing.T) {
    30  	ti := big.NewInt(10000)
    31  	encoded := encodeUpdateTime(ti)
    32  	var up updateTime
    33  	copy(up[:], encoded[:])
    34  	ret := up.bigInt()
    35  	if ret.Cmp(ti) != 0 {
    36  		t.Errorf("updateTime encode and decode error")
    37  	}
    38  }
    39  
    40  func TestNeedUpdateWitnesses(t *testing.T) {
    41  	cfg := &params.DposConfig{
    42  		WitnessesNum: 3,
    43  		Period:       2,
    44  	}
    45  
    46  	dp := New(cfg, nil)
    47  
    48  	tests := []struct {
    49  		cur  int64
    50  		last int64
    51  		ret  bool
    52  	}{
    53  		{1, 0, false},
    54  		{10, 0, false},
    55  		{17, 0, false},
    56  		{18, 0, true},
    57  		{19, 0, true},
    58  		{20, 0, true},
    59  		{21, 0, true},
    60  		{-1, 0, false},
    61  		{-10, 0, false},
    62  		{-100, 0, false},
    63  	}
    64  
    65  	for i, ts := range tests {
    66  		if dp.needUpdateWitnesses(big.NewInt(ts.cur), big.NewInt(ts.last)) != ts.ret {
    67  			t.Errorf("test:%d, failed. cur = %d, last = %d, want=%v\n", i, ts.cur, ts.last, ts.ret)
    68  		}
    69  	}
    70  }
    71  
    72  func TestUpdatedWitnessCheckByTime(t *testing.T) {
    73  	cfg := &params.DposConfig{
    74  		WitnessesNum: 4,
    75  		Period:       2,
    76  	}
    77  
    78  	dp := New(cfg, nil)
    79  
    80  	updatedHeader := &types.Header{Time: big.NewInt(103023930)}
    81  	updatedHeader.Extra = make([]byte, updateTimeLen)
    82  	copy(updatedHeader.Extra, encodeUpdateTime(updatedHeader.Time))
    83  
    84  	noneUpdatedHeader := &types.Header{Time: big.NewInt(103023930)}
    85  	noneUpdatedHeader.Extra = make([]byte, updateTimeLen)
    86  	copy(noneUpdatedHeader.Extra, encodeUpdateTime(big.NewInt(203930394)))
    87  
    88  	tests := []struct {
    89  		header *types.Header
    90  		ret    bool
    91  	}{
    92  		{updatedHeader, true},
    93  		{noneUpdatedHeader, false},
    94  	}
    95  
    96  	for i, ts := range tests {
    97  		if dp.updatedWitnessCheckByTime(ts.header) != ts.ret {
    98  			t.Errorf("test: %d failed", i)
    99  		}
   100  	}
   101  }
   102  
   103  func TestCurHeightBonus(t *testing.T) {
   104  	blkNr1 := big.NewInt(100)
   105  	blkNr2 := big.NewInt(57304000)
   106  	blkNr3 := big.NewInt(104608000)
   107  
   108  	tests := []struct {
   109  		nr    *big.Int
   110  		bonus *big.Int
   111  	}{
   112  		{blkNr1, big.NewInt(0).Set(VortexBlockReward)},
   113  		{blkNr2, big.NewInt(0).Div(big.NewInt(0).Set(VortexBlockReward), big.NewInt(2))},
   114  		{blkNr3, big.NewInt(0).Div(big.NewInt(0).Set(VortexBlockReward), big.NewInt(4))},
   115  	}
   116  
   117  	for i, ts := range tests {
   118  		if ret := curHeightBonus(ts.nr, VortexBlockReward); ret.Cmp(ts.bonus) != 0 {
   119  			t.Errorf("test: %d failed, want: %s, get: %s", i, ts.bonus.String(), ret.String())
   120  		}
   121  	}
   122  }
   123  
   124  func TestCalcVoteBounty(t *testing.T) {
   125  	cfg := &params.DposConfig{
   126  		WitnessesNum: 4,
   127  		Period:       2,
   128  	}
   129  
   130  	dp := New(cfg, nil)
   131  
   132  	// 情况1:人不够,但都是active
   133  	// 情况2:人不够,有inactive
   134  	// 情况3:没投票
   135  	ca1 := election.Candidate{
   136  		Owner:      common.BytesToAddress([]byte{1}),
   137  		VoteCount:  big.NewInt(0),
   138  		Registered: true,
   139  		Bind:       true,
   140  	}
   141  	ca2 := election.Candidate{
   142  		Owner:      common.BytesToAddress([]byte{2}),
   143  		VoteCount:  big.NewInt(0),
   144  		Registered: true,
   145  		Bind:       true,
   146  	}
   147  	ca3 := election.Candidate{
   148  		Owner:      common.BytesToAddress([]byte{3}),
   149  		VoteCount:  big.NewInt(0),
   150  		Registered: true,
   151  		Bind:       true,
   152  	}
   153  	ca4 := election.Candidate{
   154  		Owner:      common.BytesToAddress([]byte{4}),
   155  		VoteCount:  big.NewInt(0),
   156  		Registered: true,
   157  		Bind:       true,
   158  	}
   159  	ca5 := election.Candidate{
   160  		Owner:      common.BytesToAddress([]byte{5}),
   161  		VoteCount:  big.NewInt(0),
   162  		Registered: false,
   163  	}
   164  	ca6 := election.Candidate{
   165  		Owner:      common.BytesToAddress([]byte{5}),
   166  		VoteCount:  big.NewInt(0),
   167  		Registered: true,
   168  		Bind:       true,
   169  	}
   170  
   171  	candis1 := election.CandidateList{ca1, ca2, ca3}
   172  	candis2 := election.CandidateList{ca1, ca2, ca3, ca5}
   173  	candis3 := election.CandidateList{ca2, ca3, ca4, ca6}
   174  
   175  	failTests := []election.CandidateList{candis1, candis2, candis3}
   176  	allBonus := big.NewInt(100)
   177  	rewardsExpEmpty := make(map[common.Address]*big.Int)
   178  	for i, ts := range failTests {
   179  		dp.calcVoteBounty(ts, allBonus, rewardsExpEmpty)
   180  		if len(rewardsExpEmpty) != 0 {
   181  			t.Errorf("test: %d, want: reward is empty, get: len(rewardsExpEmpty)=%v", i, len(rewardsExpEmpty))
   182  		}
   183  	}
   184  
   185  	// 情况4:人够,按比例分配,其中1个inactive
   186  	ca1.VoteCount = big.NewInt(10)
   187  	ca2.VoteCount = big.NewInt(40)
   188  	ca3.VoteCount = big.NewInt(20)
   189  	ca4.VoteCount = big.NewInt(30)
   190  	ca5.VoteCount = big.NewInt(15)
   191  	candis4 := election.CandidateList{ca1, ca2, ca3, ca4, ca5}
   192  	rewardsExpNoneEmpty := make(map[common.Address]*big.Int)
   193  	rewardsExpNoneEmpty[ca1.Owner] = big.NewInt(3) // ca1有3个的已有激励
   194  	dp.calcVoteBounty(candis4, allBonus, rewardsExpNoneEmpty)
   195  	if len(rewardsExpNoneEmpty) == 0 {
   196  		t.Errorf("want: rewardsExpNoneEmpty, get: len(rewardsExpNoneEmpty) == 0")
   197  	}
   198  	for i, ca := range candis4 {
   199  		if !ca.Active() {
   200  			continue
   201  		}
   202  		caBonus := rewardsExpNoneEmpty[ca.Owner]
   203  		if caBonus == nil {
   204  			t.Errorf("can %d, want bonus: %s, get: nil", i, ca.VoteCount.String())
   205  			continue
   206  		}
   207  		if ca.Owner == ca1.Owner {
   208  			// ca1的已有激励不能被覆盖
   209  			if ca.VoteCount.Add(ca.VoteCount, big.NewInt(3)).Cmp(caBonus) != 0 {
   210  				t.Errorf("can %d, want bonus: %s+3, get: %s", i, ca.VoteCount.String(), caBonus.String())
   211  			}
   212  		} else {
   213  			if ca.VoteCount.Cmp(caBonus) != 0 {
   214  				t.Errorf("can %d, want bonus: %s, get: %s", i, ca.VoteCount.String(), caBonus.String())
   215  			}
   216  		}
   217  
   218  	}
   219  }