OSDN Git Service

add unit test and modify file name (#247)
[bytom/vapor.git] / proposal / proposal_test.go
index 2fbac0f..bfc8fa3 100644 (file)
 package proposal
 
 import (
-       "bytes"
+       "encoding/hex"
        "testing"
 
-       "github.com/vapor/protocol/bc"
+       "github.com/vapor/consensus"
+       "github.com/vapor/protocol/bc/types"
+       "github.com/vapor/protocol/state"
+       "github.com/vapor/protocol/vm/vmutil"
+       "github.com/vapor/testutil"
 )
 
-func TestCreateCoinbaseTx(t *testing.T) {
+func TestCalCoinbaseTxReward(t *testing.T) {
+       consensus.ActiveNetParams = consensus.Params{
+               ProducerSubsidys: []consensus.ProducerSubsidy{
+                       {BeginBlock: 0, EndBlock: 0, Subsidy: 24},
+                       {BeginBlock: 1, EndBlock: 840000, Subsidy: 24},
+                       {BeginBlock: 840001, EndBlock: 1680000, Subsidy: 12},
+                       {BeginBlock: 1680001, EndBlock: 3360000, Subsidy: 6},
+               },
+       }
+       reductionInterval := uint64(840000)
+
+       cases := []struct {
+               desc            string
+               block           *types.Block
+               consensusResult *state.ConsensusResult
+               wantReward      state.CoinbaseReward
+       }{
+               {
+                       desc: "the block height is reductionInterval - 1",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: reductionInterval - 1,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{},
+                       },
+                       wantReward: state.CoinbaseReward{
+                               Amount:         24,
+                               ControlProgram: []byte{0x51},
+                       },
+               },
+               {
+                       desc: "the block height is reductionInterval",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: reductionInterval,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{},
+                       },
+                       wantReward: state.CoinbaseReward{
+                               Amount:         24,
+                               ControlProgram: []byte{0x51},
+                       },
+               },
+               {
+                       desc: "the block height is reductionInterval + 1",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: reductionInterval + 1,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{},
+                       },
+                       wantReward: state.CoinbaseReward{
+                               Amount:         12,
+                               ControlProgram: []byte{0x51},
+                       },
+               },
+               {
+                       desc: "the block height is reductionInterval * 2",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: reductionInterval * 2,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{},
+                       },
+                       wantReward: state.CoinbaseReward{
+                               Amount:         12,
+                               ControlProgram: []byte{0x51},
+                       },
+               },
+               {
+                       desc: "the block height is 2*reductionInterval + 1",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: 2*reductionInterval + 1,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{},
+                       },
+                       wantReward: state.CoinbaseReward{
+                               Amount:         6,
+                               ControlProgram: []byte{0x51},
+                       },
+               },
+       }
+
+       var err error
+       for i, c := range cases {
+               c.block.Transactions[0], err = createCoinbaseTx(nil, c.block.Height)
+               if err != nil {
+                       t.Fatal(err)
+               }
+
+               if err := c.consensusResult.AttachCoinbaseReward(c.block); err != nil {
+                       t.Fatal(err)
+               }
+
+               defaultProgram, _ := vmutil.DefaultCoinbaseProgram()
+               gotReward := state.CoinbaseReward{
+                       Amount:         c.consensusResult.CoinbaseReward[hex.EncodeToString(defaultProgram)],
+                       ControlProgram: defaultProgram,
+               }
+
+               if !testutil.DeepEqual(gotReward, c.wantReward) {
+                       t.Fatalf("test case %d: %s, the coinbase reward got: %v, want: %v", i, c.desc, gotReward, c.wantReward)
+               }
+       }
+}
+
+func TestCountCoinbaseTxRewards(t *testing.T) {
+       consensus.ActiveNetParams = consensus.Params{
+               ProducerSubsidys: []consensus.ProducerSubsidy{
+                       {BeginBlock: 0, EndBlock: 0, Subsidy: 24},
+                       {BeginBlock: 1, EndBlock: 840000, Subsidy: 24},
+                       {BeginBlock: 840001, EndBlock: 1680000, Subsidy: 12},
+                       {BeginBlock: 1680001, EndBlock: 3360000, Subsidy: 6},
+               },
+       }
+
        cases := []struct {
-               desc          string
-               blockHeight   uint64
-               wantArbitrary []byte
-               wantAmount    uint64
+               desc            string
+               block           *types.Block
+               consensusResult *state.ConsensusResult
+               wantRewards     []state.CoinbaseReward
        }{
                {
-                       desc:          "the coinbase block height is reductionInterval",
-                       blockHeight:   1,
-                       wantArbitrary: []byte{0x00, 0x31},
-                       wantAmount:    0,
+                       desc: "the block height is RoundVoteBlockNums - 1",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: consensus.RoundVoteBlockNums - 1,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{
+                                       "51": 10,
+                               },
+                       },
+                       wantRewards: []state.CoinbaseReward{},
+               },
+               {
+                       desc: "the block height is RoundVoteBlockNums",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: consensus.RoundVoteBlockNums,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{
+                                       "51": 10,
+                                       "52": 20,
+                               },
+                       },
+                       wantRewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         20,
+                                       ControlProgram: []byte{0x52},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         34,
+                                       ControlProgram: []byte{0x51},
+                               },
+                       },
                },
                {
-                       desc:          "the coinbase block height is reductionInterval",
-                       blockHeight:   100,
-                       wantArbitrary: []byte{0x00, 0x31, 0x30, 0x30},
-                       wantAmount:    0,
+                       desc: "the block height is RoundVoteBlockNums + 1",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: consensus.RoundVoteBlockNums + 1,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{
+                                       "51": 10,
+                               },
+                       },
+                       wantRewards: []state.CoinbaseReward{},
+               },
+               {
+                       desc: "the block height is RoundVoteBlockNums * 2",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: consensus.RoundVoteBlockNums * 2,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{
+                                       "51": 10,
+                                       "52": 20,
+                                       "53": 30,
+                               },
+                       },
+                       wantRewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         20,
+                                       ControlProgram: []byte{0x52},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         30,
+                                       ControlProgram: []byte{0x53},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         34,
+                                       ControlProgram: []byte{0x51},
+                               },
+                       },
+               },
+               {
+                       desc: "the block height is 2*RoundVoteBlockNums + 1",
+                       block: &types.Block{
+                               BlockHeader: types.BlockHeader{
+                                       Height: 2*consensus.RoundVoteBlockNums + 1,
+                               },
+                               Transactions: []*types.Tx{nil},
+                       },
+                       consensusResult: &state.ConsensusResult{
+                               CoinbaseReward: map[string]uint64{},
+                       },
+                       wantRewards: []state.CoinbaseReward{},
                },
        }
 
+       var err error
        for i, c := range cases {
-               coinbaseTx, err := createCoinbaseTx(nil, c.blockHeight)
+               c.block.Transactions[0], err = createCoinbaseTx(nil, c.block.Height)
                if err != nil {
                        t.Fatal(err)
                }
 
-               input, _ := coinbaseTx.Entries[coinbaseTx.Tx.InputIDs[0]].(*bc.Coinbase)
-               gotArbitrary := input.Arbitrary
-               if res := bytes.Compare(gotArbitrary, c.wantArbitrary); res != 0 {
-                       t.Fatalf("coinbase tx arbitrary dismatch, case: %d, got: %d, want: %d", i, gotArbitrary, c.wantArbitrary)
+               if err := c.consensusResult.AttachCoinbaseReward(c.block); err != nil {
+                       t.Fatal(err)
                }
 
-               gotAmount := coinbaseTx.Outputs[0].AssetAmount().Amount
-               if gotAmount != c.wantAmount {
-                       t.Fatalf("coinbase tx output amount dismatch, case: %d, got: %d, want: %d", i, gotAmount, c.wantAmount)
+               rewards, err := c.consensusResult.GetCoinbaseRewards(c.block.Height)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               if !testutil.DeepEqual(rewards, c.wantRewards) {
+                       t.Fatalf("test case %d: %s, the coinbase reward got: %v, want: %v", i, c.desc, rewards, c.wantRewards)
                }
        }
 }