OSDN Git Service

rollback (#503)
[bytom/vapor.git] / test / rollback_test.go
diff --git a/test/rollback_test.go b/test/rollback_test.go
new file mode 100644 (file)
index 0000000..8dc77c5
--- /dev/null
@@ -0,0 +1,1571 @@
+package test
+
+import (
+       "os"
+       "testing"
+
+       "github.com/bytom/vapor/application/mov"
+       movDatabase "github.com/bytom/vapor/application/mov/database"
+       "github.com/bytom/vapor/consensus"
+       "github.com/bytom/vapor/database"
+       dbm "github.com/bytom/vapor/database/leveldb"
+       "github.com/bytom/vapor/database/storage"
+       "github.com/bytom/vapor/protocol"
+       "github.com/bytom/vapor/protocol/bc"
+       "github.com/bytom/vapor/protocol/bc/types"
+       "github.com/bytom/vapor/protocol/state"
+       "github.com/bytom/vapor/testutil"
+)
+
+type chainData struct {
+       bestBlockHeader    *types.BlockHeader
+       lastIrrBlockHeader *types.BlockHeader
+       utxoViewPoint      *state.UtxoViewpoint
+       storedBlocks       []*types.Block
+       consensusResults   []*state.ConsensusResult
+}
+
+func TestRollback(t *testing.T) {
+       cases := []struct {
+               desc                   string
+               movStartHeight         uint64
+               RoundVoteBlockNums     uint64
+               beforeChainData        *chainData
+               wantChainData          *chainData
+               rollbackToTargetHeight uint64
+       }{
+               {
+                       desc:                   "rollback from height 1 to 0",
+                       movStartHeight:         10,
+                       RoundVoteBlockNums:     1200,
+                       rollbackToTargetHeight: 0,
+                       beforeChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100002000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               BlockHeight:    1,
+                                               CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1) + 10000000000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+                       wantChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height: 0,
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height: 0,
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+               },
+               {
+                       desc:                   "rollback from height 2 to 0",
+                       movStartHeight:         10,
+                       RoundVoteBlockNums:     1200,
+                       rollbackToTargetHeight: 0,
+                       beforeChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("afee09925bea1695424450a91ad082a378f20534627fa5cb63f036846347ee08"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                               testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 3000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2500, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100004500,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(2) + 10000000000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+                       wantChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height: 0,
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height: 0,
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+               },
+               {
+                       desc:                   "rollback from height 2 to 1",
+                       movStartHeight:         10,
+                       RoundVoteBlockNums:     1200,
+                       rollbackToTargetHeight: 1,
+                       beforeChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("afee09925bea1695424450a91ad082a378f20534627fa5cb63f036846347ee08"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                               testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 3000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2500, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100004500,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 500},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+                       wantChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100002000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               BlockHeight:    1,
+                                               CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1)},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+               },
+               {
+                       desc:                   "rollback from height 2 to 1, RoundVoteBlockNums is 2",
+                       movStartHeight:         10,
+                       RoundVoteBlockNums:     2,
+                       rollbackToTargetHeight: 1,
+                       beforeChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("afee09925bea1695424450a91ad082a378f20534627fa5cb63f036846347ee08"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                               testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 3000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2500, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100004500,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 500},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+                       wantChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100002000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               BlockHeight:    1,
+                                               CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1)},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+               },
+               {
+                       desc:                   "rollback from height 3 to 1, RoundVoteBlockNums is 2",
+                       movStartHeight:         10,
+                       RoundVoteBlockNums:     2,
+                       rollbackToTargetHeight: 1,
+                       beforeChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            3,
+                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            3,
+                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("5b4d53fbc2a489847f34dd0e0c085797fe7cf0a3a9a2f3231d11bdad16dea2be"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
+                                               testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                               testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            3,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 400000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 2,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 609998000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("0c1cd1c0a6e6161f437c382cca21ce28921234ed7c4f252f7e4bbc9a523b74ac"),
+                                               BlockHeight:    3,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(3) + 240000000},
+                                       },
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 449998000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+                       wantChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            1,
+                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000 + 100000000 - 2000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               BlockHeight:    1,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + 2000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+               },
+               {
+                       desc:                   "rollback from height 3 to 2, RoundVoteBlockNums is 2",
+                       movStartHeight:         10,
+                       RoundVoteBlockNums:     2,
+                       rollbackToTargetHeight: 2,
+                       beforeChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            3,
+                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            3,
+                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("5b4d53fbc2a489847f34dd0e0c085797fe7cf0a3a9a2f3231d11bdad16dea2be"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
+                                               testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                               testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            3,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 400000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 2,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 609998000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("0c1cd1c0a6e6161f437c382cca21ce28921234ed7c4f252f7e4bbc9a523b74ac"),
+                                               BlockHeight:    3,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(3) + 240000000},
+                                       },
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 449998000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+                       wantChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                               testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000 + 100000000 - 2000 + 250000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+               },
+               {
+                       desc:                   "rollback from height 4 to 2, there is two chain , and round vote block nums is 2",
+                       movStartHeight:         10,
+                       RoundVoteBlockNums:     2,
+                       rollbackToTargetHeight: 2,
+                       beforeChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            5,
+                                       Timestamp:         uint64(1528945008),
+                                       PreviousBlockHash: testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            5,
+                                       Timestamp:         uint64(1528945008),
+                                       PreviousBlockHash: testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("3c07f3159d4e2a0527129d644a8fcd09ce26555e94c9c7f348464120ef463275"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 5, Spent: true},
+                                               testutil.MustDecodeHash("927144d2a391e17dc12184f5ae163b994984132ad72c34d854bb9009b68cd4cc"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 4, Spent: true},
+                                               testutil.MustDecodeHash("fa43f4ca43bcb0e94d43b52c56d1740dea1329b59a44f6ee045d70446881c514"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
+                                               testutil.MustDecodeHash("f081ccd0c97ae34bc5580a0405d9b1ed0b0ed9e1410f1786b7112b348a412e3d"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 4, Spent: true},
+                                               testutil.MustDecodeHash("2704fa67c76e020b08ffa3f93a500acebcaf68b45ba43d8b3b08b68c5bb1eff1"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
+                                               testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                               testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                       },
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            3,
+                                                       Timestamp:         uint64(1528945000),
+                                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 440000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            4,
+                                                       Timestamp:         uint64(1528945005),
+                                                       PreviousBlockHash: testutil.MustDecodeHash("bec3dd0d6fecb80a6f3a0373ec2ae676cc1ce72af83546f3d4672231c9b080e6"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 500000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            3,
+                                                       Timestamp:         uint64(1528945001),
+                                                       PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 402000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 200000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            4,
+                                                       Timestamp:         uint64(1528945006),
+                                                       PreviousBlockHash: testutil.MustDecodeHash("1d2d01a97d1239de51b4e7d0fb522f71771d2d4f9a0a559154519859cc44a230"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 410000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 170000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            5,
+                                                       Timestamp:         uint64(1528945008),
+                                                       PreviousBlockHash: testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(3)+consensus.BlockSubsidy(4)+520000000, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 400004000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 160004000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 3,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 980002000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("075ce54f7d4c1b524474265219be52238beec98138f0c0a4d21f1a6b0047914a"),
+                                               BlockHeight:    5,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(5) + 240000000},
+                                       },
+                                       {
+                                               Seq: 2,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 819998000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
+                                               BlockHeight:    4,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(3) + consensus.BlockSubsidy(4) + 442000000},
+                                       },
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 449998000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                       },
+                       wantChainData: &chainData{
+                               bestBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               lastIrrBlockHeader: &types.BlockHeader{
+                                       Height:            2,
+                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                               },
+                               storedBlocks: []*types.Block{
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height: 0,
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            1,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                                       {
+                                               BlockHeader: types.BlockHeader{
+                                                       Height:            2,
+                                                       PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
+                                               },
+                                               Transactions: []*types.Tx{
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
+                                                               },
+                                                       }),
+                                                       types.NewTx(types.TxData{
+                                                               Inputs: []*types.TxInput{
+                                                                       types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
+                                                               },
+                                                               Outputs: []*types.TxOutput{
+                                                                       types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
+                                                               },
+                                                       }),
+                                               },
+                                       },
+                               },
+                               consensusResults: []*state.ConsensusResult{
+                                       {
+                                               Seq: 1,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000 + 100000000 - 2000 + 250000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
+                                               BlockHeight:    2,
+                                               CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
+                                       },
+                                       {
+                                               Seq: 0,
+                                               NumOfVote: map[string]uint64{
+                                                       "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
+                                                       "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
+                                               },
+                                               BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
+                                               BlockHeight:    0,
+                                               CoinbaseReward: map[string]uint64{},
+                                       },
+                               },
+                               utxoViewPoint: &state.UtxoViewpoint{
+                                       Entries: map[bc.Hash]*storage.UtxoEntry{
+                                               testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
+                                               testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
+                                               testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
+                                       },
+                               },
+                       },
+               },
+       }
+
+       for i, c := range cases {
+               consensus.ActiveNetParams.RoundVoteBlockNums = c.RoundVoteBlockNums
+
+               movDB := dbm.NewDB("mov_db", "leveldb", "mov_db")
+               movCore := mov.NewMovCoreWithDB(movDatabase.NewLevelDBMovStore(movDB), c.movStartHeight)
+
+               blockDB := dbm.NewDB("block_db", "leveldb", "block_db")
+               store := database.NewStore(blockDB)
+
+               mustSaveBlocks(c.beforeChainData.storedBlocks, store)
+
+               var mainChainBlockHeaders []*types.BlockHeader
+               for _, block := range c.beforeChainData.storedBlocks {
+                       mainChainBlockHeaders = append(mainChainBlockHeaders, &block.BlockHeader)
+               }
+               if err := store.SaveChainStatus(c.beforeChainData.bestBlockHeader, c.beforeChainData.lastIrrBlockHeader, mainChainBlockHeaders, c.beforeChainData.utxoViewPoint, c.beforeChainData.consensusResults); err != nil {
+                       t.Fatal(err)
+               }
+
+               chain, err := protocol.NewChain(store, nil, []protocol.Protocoler{movCore}, nil)
+               if err != nil {
+                       t.Fatal(err)
+               }
+
+               if err := chain.Rollback(c.rollbackToTargetHeight); err != nil {
+                       t.Fatal(err)
+               }
+
+               if !testutil.DeepEqual(chain.LastIrreversibleHeader(), c.wantChainData.lastIrrBlockHeader) {
+                       t.Errorf("lastIrrBlockHeader is not right!")
+               }
+
+               if !testutil.DeepEqual(chain.BestBlockHeader(), c.wantChainData.bestBlockHeader) {
+                       t.Errorf("wantBestBlockHeader is not right!")
+               }
+
+               gotConsensusResults := mustGetConsensusResultFromStore(store, chain)
+               if !testutil.DeepEqual(gotConsensusResults, c.wantChainData.consensusResults) {
+                       t.Errorf("cases#%d(%s) wantBestConsensusResult is not right!", i, c.desc)
+               }
+
+               gotBlocks := mustGetBlocksFromStore(chain)
+               if !blocksEquals(gotBlocks, c.wantChainData.storedBlocks) {
+                       t.Errorf("cases#%d(%s) the blocks is not same!", i, c.desc)
+               }
+
+               gotTransactions := getBcTransactions(gotBlocks)
+               gotUtxoViewPoint := state.NewUtxoViewpoint()
+               if err = store.GetTransactionsUtxo(gotUtxoViewPoint, gotTransactions); err != nil {
+                       t.Fatal(err)
+               }
+
+               if !testutil.DeepEqual(gotUtxoViewPoint, c.wantChainData.utxoViewPoint) {
+                       t.Fatal(err)
+               }
+
+               blockDB.Close()
+               os.RemoveAll("block_db")
+               movDB.Close()
+               os.RemoveAll("mov_db")
+
+       }
+}
+
+func blocksEquals(blocks1 []*types.Block, blocks2 []*types.Block) bool {
+       blockHashMap1 := make(map[string]interface{})
+       for _, block := range blocks1 {
+               hash := block.Hash()
+               blockHashMap1[hash.String()] = nil
+       }
+
+       blockHashMap2 := make(map[string]interface{})
+       for _, block := range blocks2 {
+               hash := block.Hash()
+               blockHashMap2[hash.String()] = nil
+       }
+       return testutil.DeepEqual(blockHashMap1, blockHashMap2)
+}
+
+func getBcTransactions(blocks []*types.Block) []*bc.Tx {
+       var txs []*bc.Tx
+       for _, block := range blocks {
+               for _, tx := range block.Transactions {
+                       txs = append(txs, tx.Tx)
+               }
+       }
+       return txs
+}
+
+func mustSaveBlocks(blocks []*types.Block, store *database.Store) {
+       for _, block := range blocks {
+               status := bc.NewTransactionStatus()
+               for index := range block.Transactions {
+                       if err := status.SetStatus(index, false); err != nil {
+                               panic(err)
+                       }
+               }
+               if err := store.SaveBlock(block, status); err != nil {
+                       panic(err)
+               }
+       }
+}
+
+func mustGetBlocksFromStore(chain *protocol.Chain) []*types.Block {
+       var blocks []*types.Block
+       for height := int64(chain.BestBlockHeight()); height >= 0; height-- {
+               block, err := chain.GetBlockByHeight(uint64(height))
+               if err != nil {
+                       panic(err)
+               }
+
+               blocks = append(blocks, block)
+       }
+       return blocks
+}
+
+func mustGetConsensusResultFromStore(store *database.Store, chain *protocol.Chain) []*state.ConsensusResult {
+       var consensusResults []*state.ConsensusResult
+       for seq := int64(state.CalcVoteSeq(chain.BestBlockHeight())); seq >= 0; seq-- {
+               consensusResult, err := store.GetConsensusResult(uint64(seq))
+               if err != nil {
+                       panic(err)
+               }
+
+               consensusResults = append(consensusResults, consensusResult)
+       }
+       return consensusResults
+}