OSDN Git Service

Mov (#518)
[bytom/vapor.git] / test / rollback_test.go
1 package test
2
3 import (
4         "os"
5         "testing"
6
7         "github.com/bytom/vapor/application/mov"
8         movDatabase "github.com/bytom/vapor/application/mov/database"
9         "github.com/bytom/vapor/consensus"
10         "github.com/bytom/vapor/database"
11         dbm "github.com/bytom/vapor/database/leveldb"
12         "github.com/bytom/vapor/database/storage"
13         "github.com/bytom/vapor/protocol"
14         "github.com/bytom/vapor/protocol/bc"
15         "github.com/bytom/vapor/protocol/bc/types"
16         "github.com/bytom/vapor/protocol/state"
17         "github.com/bytom/vapor/testutil"
18 )
19
20 type chainData struct {
21         bestBlockHeader    *types.BlockHeader
22         lastIrrBlockHeader *types.BlockHeader
23         utxoViewPoint      *state.UtxoViewpoint
24         storedBlocks       []*types.Block
25         consensusResults   []*state.ConsensusResult
26 }
27
28 func TestRollback(t *testing.T) {
29         cases := []struct {
30                 desc                   string
31                 movStartHeight         uint64
32                 RoundVoteBlockNums     uint64
33                 beforeChainData        *chainData
34                 wantChainData          *chainData
35                 rollbackToTargetHeight uint64
36         }{
37                 {
38                         desc:                   "rollback from height 1 to 0",
39                         movStartHeight:         10,
40                         RoundVoteBlockNums:     1200,
41                         rollbackToTargetHeight: 0,
42                         beforeChainData: &chainData{
43                                 bestBlockHeader: &types.BlockHeader{
44                                         Height:            1,
45                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
46                                 },
47                                 lastIrrBlockHeader: &types.BlockHeader{
48                                         Height:            1,
49                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
50                                 },
51                                 utxoViewPoint: &state.UtxoViewpoint{
52                                         Entries: map[bc.Hash]*storage.UtxoEntry{
53                                                 testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
54                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
55                                         },
56                                 },
57                                 storedBlocks: []*types.Block{
58                                         {
59                                                 BlockHeader: types.BlockHeader{
60                                                         Height: 0,
61                                                 },
62                                                 Transactions: []*types.Tx{
63                                                         types.NewTx(types.TxData{
64                                                                 Inputs: []*types.TxInput{
65                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
66                                                                 },
67                                                                 Outputs: []*types.TxOutput{
68                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
69                                                                 },
70                                                         }),
71                                                 },
72                                         },
73                                         {
74                                                 BlockHeader: types.BlockHeader{
75                                                         Height:            1,
76                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
77                                                 },
78                                                 Transactions: []*types.Tx{
79                                                         types.NewTx(types.TxData{
80                                                                 Inputs: []*types.TxInput{
81                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
82                                                                 },
83                                                                 Outputs: []*types.TxOutput{
84                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
85                                                                 },
86                                                         }),
87                                                 },
88                                         },
89                                 },
90                                 consensusResults: []*state.ConsensusResult{
91                                         {
92                                                 Seq: 1,
93                                                 NumOfVote: map[string]uint64{
94                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100002000,
95                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
96                                                 },
97                                                 BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
98                                                 BlockHeight:    1,
99                                                 CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1) + 10000000000},
100                                         },
101                                         {
102                                                 Seq: 0,
103                                                 NumOfVote: map[string]uint64{
104                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
105                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
106                                                 },
107                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
108                                                 BlockHeight:    0,
109                                                 CoinbaseReward: map[string]uint64{},
110                                         },
111                                 },
112                         },
113                         wantChainData: &chainData{
114                                 bestBlockHeader: &types.BlockHeader{
115                                         Height: 0,
116                                 },
117                                 lastIrrBlockHeader: &types.BlockHeader{
118                                         Height: 0,
119                                 },
120                                 storedBlocks: []*types.Block{
121                                         {
122                                                 BlockHeader: types.BlockHeader{
123                                                         Height: 0,
124                                                 },
125                                                 Transactions: []*types.Tx{
126                                                         types.NewTx(types.TxData{
127                                                                 Inputs: []*types.TxInput{
128                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
129                                                                 },
130                                                                 Outputs: []*types.TxOutput{
131                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
132                                                                 },
133                                                         }),
134                                                 },
135                                         },
136                                 },
137                                 utxoViewPoint: &state.UtxoViewpoint{
138                                         Entries: map[bc.Hash]*storage.UtxoEntry{
139                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
140                                         },
141                                 },
142                                 consensusResults: []*state.ConsensusResult{
143                                         {
144                                                 Seq: 0,
145                                                 NumOfVote: map[string]uint64{
146                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
147                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
148                                                 },
149                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
150                                                 BlockHeight:    0,
151                                                 CoinbaseReward: map[string]uint64{},
152                                         },
153                                 },
154                         },
155                 },
156                 {
157                         desc:                   "rollback from height 2 to 0",
158                         movStartHeight:         10,
159                         RoundVoteBlockNums:     1200,
160                         rollbackToTargetHeight: 0,
161                         beforeChainData: &chainData{
162                                 bestBlockHeader: &types.BlockHeader{
163                                         Height:            2,
164                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
165                                 },
166                                 lastIrrBlockHeader: &types.BlockHeader{
167                                         Height:            2,
168                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
169                                 },
170                                 utxoViewPoint: &state.UtxoViewpoint{
171                                         Entries: map[bc.Hash]*storage.UtxoEntry{
172                                                 testutil.MustDecodeHash("afee09925bea1695424450a91ad082a378f20534627fa5cb63f036846347ee08"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
173                                                 testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
174                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
175                                         },
176                                 },
177                                 storedBlocks: []*types.Block{
178                                         {
179                                                 BlockHeader: types.BlockHeader{
180                                                         Height: 0,
181                                                 },
182                                                 Transactions: []*types.Tx{
183                                                         types.NewTx(types.TxData{
184                                                                 Inputs: []*types.TxInput{
185                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
186                                                                 },
187                                                                 Outputs: []*types.TxOutput{
188                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
189                                                                 },
190                                                         }),
191                                                 },
192                                         },
193                                         {
194                                                 BlockHeader: types.BlockHeader{
195                                                         Height:            1,
196                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
197                                                 },
198                                                 Transactions: []*types.Tx{
199                                                         types.NewTx(types.TxData{
200                                                                 Inputs: []*types.TxInput{
201                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
202                                                                 },
203                                                                 Outputs: []*types.TxOutput{
204                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
205                                                                 },
206                                                         }),
207                                                 },
208                                         },
209                                         {
210                                                 BlockHeader: types.BlockHeader{
211                                                         Height:            2,
212                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
213                                                 },
214                                                 Transactions: []*types.Tx{
215                                                         types.NewTx(types.TxData{
216                                                                 Inputs: []*types.TxInput{
217                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 3000, 0, []byte{0, 1}),
218                                                                 },
219                                                                 Outputs: []*types.TxOutput{
220                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2500, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
221                                                                 },
222                                                         }),
223                                                 },
224                                         },
225                                 },
226                                 consensusResults: []*state.ConsensusResult{
227                                         {
228                                                 Seq: 1,
229                                                 NumOfVote: map[string]uint64{
230                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100004500,
231                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
232                                                 },
233                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
234                                                 BlockHeight:    2,
235                                                 CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(2) + 10000000000},
236                                         },
237                                         {
238                                                 Seq: 0,
239                                                 NumOfVote: map[string]uint64{
240                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
241                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
242                                                 },
243                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
244                                                 BlockHeight:    0,
245                                                 CoinbaseReward: map[string]uint64{},
246                                         },
247                                 },
248                         },
249                         wantChainData: &chainData{
250                                 bestBlockHeader: &types.BlockHeader{
251                                         Height: 0,
252                                 },
253                                 lastIrrBlockHeader: &types.BlockHeader{
254                                         Height: 0,
255                                 },
256                                 storedBlocks: []*types.Block{
257                                         {
258                                                 BlockHeader: types.BlockHeader{
259                                                         Height: 0,
260                                                 },
261                                                 Transactions: []*types.Tx{
262                                                         types.NewTx(types.TxData{
263                                                                 Inputs: []*types.TxInput{
264                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
265                                                                 },
266                                                                 Outputs: []*types.TxOutput{
267                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
268                                                                 },
269                                                         }),
270                                                 },
271                                         },
272                                 },
273                                 utxoViewPoint: &state.UtxoViewpoint{
274                                         Entries: map[bc.Hash]*storage.UtxoEntry{
275                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
276                                         },
277                                 },
278                                 consensusResults: []*state.ConsensusResult{
279                                         {
280                                                 Seq: 0,
281                                                 NumOfVote: map[string]uint64{
282                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
283                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
284                                                 },
285                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
286                                                 BlockHeight:    0,
287                                                 CoinbaseReward: map[string]uint64{},
288                                         },
289                                 },
290                         },
291                 },
292                 {
293                         desc:                   "rollback from height 2 to 1",
294                         movStartHeight:         10,
295                         RoundVoteBlockNums:     1200,
296                         rollbackToTargetHeight: 1,
297                         beforeChainData: &chainData{
298                                 bestBlockHeader: &types.BlockHeader{
299                                         Height:            2,
300                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
301                                 },
302                                 lastIrrBlockHeader: &types.BlockHeader{
303                                         Height:            2,
304                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
305                                 },
306                                 utxoViewPoint: &state.UtxoViewpoint{
307                                         Entries: map[bc.Hash]*storage.UtxoEntry{
308                                                 testutil.MustDecodeHash("afee09925bea1695424450a91ad082a378f20534627fa5cb63f036846347ee08"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
309                                                 testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
310                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
311                                         },
312                                 },
313                                 storedBlocks: []*types.Block{
314                                         {
315                                                 BlockHeader: types.BlockHeader{
316                                                         Height: 0,
317                                                 },
318                                                 Transactions: []*types.Tx{
319                                                         types.NewTx(types.TxData{
320                                                                 Inputs: []*types.TxInput{
321                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
322                                                                 },
323                                                                 Outputs: []*types.TxOutput{
324                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
325                                                                 },
326                                                         }),
327                                                 },
328                                         },
329                                         {
330                                                 BlockHeader: types.BlockHeader{
331                                                         Height:            1,
332                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
333                                                 },
334                                                 Transactions: []*types.Tx{
335                                                         types.NewTx(types.TxData{
336                                                                 Inputs: []*types.TxInput{
337                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
338                                                                 },
339                                                                 Outputs: []*types.TxOutput{
340                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
341                                                                 },
342                                                         }),
343                                                 },
344                                         },
345                                         {
346                                                 BlockHeader: types.BlockHeader{
347                                                         Height:            2,
348                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
349                                                 },
350                                                 Transactions: []*types.Tx{
351                                                         types.NewTx(types.TxData{
352                                                                 Inputs: []*types.TxInput{
353                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 3000, 0, []byte{0, 1}),
354                                                                 },
355                                                                 Outputs: []*types.TxOutput{
356                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2500, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
357                                                                 },
358                                                         }),
359                                                 },
360                                         },
361                                 },
362                                 consensusResults: []*state.ConsensusResult{
363                                         {
364                                                 Seq: 1,
365                                                 NumOfVote: map[string]uint64{
366                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100004500,
367                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
368                                                 },
369                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
370                                                 BlockHeight:    2,
371                                                 CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 500},
372                                         },
373                                         {
374                                                 Seq: 0,
375                                                 NumOfVote: map[string]uint64{
376                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
377                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
378                                                 },
379                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
380                                                 BlockHeight:    0,
381                                                 CoinbaseReward: map[string]uint64{},
382                                         },
383                                 },
384                         },
385                         wantChainData: &chainData{
386                                 bestBlockHeader: &types.BlockHeader{
387                                         Height:            1,
388                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
389                                 },
390                                 lastIrrBlockHeader: &types.BlockHeader{
391                                         Height:            1,
392                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
393                                 },
394                                 storedBlocks: []*types.Block{
395                                         {
396                                                 BlockHeader: types.BlockHeader{
397                                                         Height: 0,
398                                                 },
399                                                 Transactions: []*types.Tx{
400                                                         types.NewTx(types.TxData{
401                                                                 Inputs: []*types.TxInput{
402                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
403                                                                 },
404                                                                 Outputs: []*types.TxOutput{
405                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
406                                                                 },
407                                                         }),
408                                                 },
409                                         },
410                                         {
411                                                 BlockHeader: types.BlockHeader{
412                                                         Height:            1,
413                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
414                                                 },
415                                                 Transactions: []*types.Tx{
416                                                         types.NewTx(types.TxData{
417                                                                 Inputs: []*types.TxInput{
418                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
419                                                                 },
420                                                                 Outputs: []*types.TxOutput{
421                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
422                                                                 },
423                                                         }),
424                                                 },
425                                         },
426                                 },
427                                 utxoViewPoint: &state.UtxoViewpoint{
428                                         Entries: map[bc.Hash]*storage.UtxoEntry{
429                                                 testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
430                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
431                                         },
432                                 },
433                                 consensusResults: []*state.ConsensusResult{
434                                         {
435                                                 Seq: 1,
436                                                 NumOfVote: map[string]uint64{
437                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100002000,
438                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
439                                                 },
440                                                 BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
441                                                 BlockHeight:    1,
442                                                 CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1)},
443                                         },
444                                         {
445                                                 Seq: 0,
446                                                 NumOfVote: map[string]uint64{
447                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
448                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
449                                                 },
450                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
451                                                 BlockHeight:    0,
452                                                 CoinbaseReward: map[string]uint64{},
453                                         },
454                                 },
455                         },
456                 },
457                 {
458                         desc:                   "rollback from height 2 to 1, RoundVoteBlockNums is 2",
459                         movStartHeight:         10,
460                         RoundVoteBlockNums:     2,
461                         rollbackToTargetHeight: 1,
462                         beforeChainData: &chainData{
463                                 bestBlockHeader: &types.BlockHeader{
464                                         Height:            2,
465                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
466                                 },
467                                 lastIrrBlockHeader: &types.BlockHeader{
468                                         Height:            2,
469                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
470                                 },
471                                 utxoViewPoint: &state.UtxoViewpoint{
472                                         Entries: map[bc.Hash]*storage.UtxoEntry{
473                                                 testutil.MustDecodeHash("afee09925bea1695424450a91ad082a378f20534627fa5cb63f036846347ee08"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
474                                                 testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
475                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
476                                         },
477                                 },
478                                 storedBlocks: []*types.Block{
479                                         {
480                                                 BlockHeader: types.BlockHeader{
481                                                         Height: 0,
482                                                 },
483                                                 Transactions: []*types.Tx{
484                                                         types.NewTx(types.TxData{
485                                                                 Inputs: []*types.TxInput{
486                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
487                                                                 },
488                                                                 Outputs: []*types.TxOutput{
489                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
490                                                                 },
491                                                         }),
492                                                 },
493                                         },
494                                         {
495                                                 BlockHeader: types.BlockHeader{
496                                                         Height:            1,
497                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
498                                                 },
499                                                 Transactions: []*types.Tx{
500                                                         types.NewTx(types.TxData{
501                                                                 Inputs: []*types.TxInput{
502                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
503                                                                 },
504                                                                 Outputs: []*types.TxOutput{
505                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
506                                                                 },
507                                                         }),
508                                                 },
509                                         },
510                                         {
511                                                 BlockHeader: types.BlockHeader{
512                                                         Height:            2,
513                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
514                                                 },
515                                                 Transactions: []*types.Tx{
516                                                         types.NewTx(types.TxData{
517                                                                 Inputs: []*types.TxInput{
518                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 3000, 0, []byte{0, 1}),
519                                                                 },
520                                                                 Outputs: []*types.TxOutput{
521                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2500, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
522                                                                 },
523                                                         }),
524                                                 },
525                                         },
526                                 },
527                                 consensusResults: []*state.ConsensusResult{
528                                         {
529                                                 Seq: 1,
530                                                 NumOfVote: map[string]uint64{
531                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100004500,
532                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
533                                                 },
534                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
535                                                 BlockHeight:    2,
536                                                 CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 500},
537                                         },
538                                         {
539                                                 Seq: 0,
540                                                 NumOfVote: map[string]uint64{
541                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
542                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
543                                                 },
544                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
545                                                 BlockHeight:    0,
546                                                 CoinbaseReward: map[string]uint64{},
547                                         },
548                                 },
549                         },
550                         wantChainData: &chainData{
551                                 bestBlockHeader: &types.BlockHeader{
552                                         Height:            1,
553                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
554                                 },
555                                 lastIrrBlockHeader: &types.BlockHeader{
556                                         Height:            1,
557                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
558                                 },
559                                 storedBlocks: []*types.Block{
560                                         {
561                                                 BlockHeader: types.BlockHeader{
562                                                         Height: 0,
563                                                 },
564                                                 Transactions: []*types.Tx{
565                                                         types.NewTx(types.TxData{
566                                                                 Inputs: []*types.TxInput{
567                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}),
568                                                                 },
569                                                                 Outputs: []*types.TxOutput{
570                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
571                                                                 },
572                                                         }),
573                                                 },
574                                         },
575                                         {
576                                                 BlockHeader: types.BlockHeader{
577                                                         Height:            1,
578                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
579                                                 },
580                                                 Transactions: []*types.Tx{
581                                                         types.NewTx(types.TxData{
582                                                                 Inputs: []*types.TxInput{
583                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}),
584                                                                 },
585                                                                 Outputs: []*types.TxOutput{
586                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
587                                                                 },
588                                                         }),
589                                                 },
590                                         },
591                                 },
592                                 utxoViewPoint: &state.UtxoViewpoint{
593                                         Entries: map[bc.Hash]*storage.UtxoEntry{
594                                                 testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
595                                                 testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
596                                         },
597                                 },
598                                 consensusResults: []*state.ConsensusResult{
599                                         {
600                                                 Seq: 1,
601                                                 NumOfVote: map[string]uint64{
602                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100002000,
603                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
604                                                 },
605                                                 BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
606                                                 BlockHeight:    1,
607                                                 CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1)},
608                                         },
609                                         {
610                                                 Seq: 0,
611                                                 NumOfVote: map[string]uint64{
612                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
613                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000,
614                                                 },
615                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
616                                                 BlockHeight:    0,
617                                                 CoinbaseReward: map[string]uint64{},
618                                         },
619                                 },
620                         },
621                 },
622                 {
623                         desc:                   "rollback from height 3 to 1, RoundVoteBlockNums is 2",
624                         movStartHeight:         10,
625                         RoundVoteBlockNums:     2,
626                         rollbackToTargetHeight: 1,
627                         beforeChainData: &chainData{
628                                 bestBlockHeader: &types.BlockHeader{
629                                         Height:            3,
630                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
631                                 },
632                                 lastIrrBlockHeader: &types.BlockHeader{
633                                         Height:            3,
634                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
635                                 },
636                                 utxoViewPoint: &state.UtxoViewpoint{
637                                         Entries: map[bc.Hash]*storage.UtxoEntry{
638                                                 testutil.MustDecodeHash("5b4d53fbc2a489847f34dd0e0c085797fe7cf0a3a9a2f3231d11bdad16dea2be"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
639                                                 testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
640                                                 testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
641                                                 testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
642                                         },
643                                 },
644                                 storedBlocks: []*types.Block{
645                                         {
646                                                 BlockHeader: types.BlockHeader{
647                                                         Height: 0,
648                                                 },
649                                                 Transactions: []*types.Tx{
650                                                         types.NewTx(types.TxData{
651                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
652                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
653                                                         }),
654                                                         types.NewTx(types.TxData{
655                                                                 Inputs: []*types.TxInput{
656                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
657                                                                 },
658                                                                 Outputs: []*types.TxOutput{
659                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
660                                                                 },
661                                                         }),
662                                                 },
663                                         },
664                                         {
665                                                 BlockHeader: types.BlockHeader{
666                                                         Height:            1,
667                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
668                                                 },
669                                                 Transactions: []*types.Tx{
670                                                         types.NewTx(types.TxData{
671                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
672                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
673                                                         }),
674                                                         types.NewTx(types.TxData{
675                                                                 Inputs: []*types.TxInput{
676                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
677                                                                 },
678                                                                 Outputs: []*types.TxOutput{
679                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
680                                                                 },
681                                                         }),
682                                                 },
683                                         },
684                                         {
685                                                 BlockHeader: types.BlockHeader{
686                                                         Height:            2,
687                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
688                                                 },
689                                                 Transactions: []*types.Tx{
690                                                         types.NewTx(types.TxData{
691                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
692                                                                 Outputs: []*types.TxOutput{
693                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
694                                                                 },
695                                                         }),
696                                                         types.NewTx(types.TxData{
697                                                                 Inputs: []*types.TxInput{
698                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
699                                                                 },
700                                                                 Outputs: []*types.TxOutput{
701                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
702                                                                 },
703                                                         }),
704                                                 },
705                                         },
706                                         {
707                                                 BlockHeader: types.BlockHeader{
708                                                         Height:            3,
709                                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
710                                                 },
711                                                 Transactions: []*types.Tx{
712                                                         types.NewTx(types.TxData{
713                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
714                                                                 Outputs: []*types.TxOutput{
715                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
716                                                                         types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
717                                                                 },
718                                                         }),
719                                                         types.NewTx(types.TxData{
720                                                                 Inputs: []*types.TxInput{
721                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 400000000, 0, []byte{0, 1}),
722                                                                 },
723                                                                 Outputs: []*types.TxOutput{
724                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
725                                                                 },
726                                                         }),
727                                                 },
728                                         },
729                                 },
730                                 consensusResults: []*state.ConsensusResult{
731                                         {
732                                                 Seq: 2,
733                                                 NumOfVote: map[string]uint64{
734                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 609998000,
735                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
736                                                 },
737                                                 BlockHash:      testutil.MustDecodeHash("0c1cd1c0a6e6161f437c382cca21ce28921234ed7c4f252f7e4bbc9a523b74ac"),
738                                                 BlockHeight:    3,
739                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(3) + 240000000},
740                                         },
741                                         {
742                                                 Seq: 1,
743                                                 NumOfVote: map[string]uint64{
744                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 449998000,
745                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
746                                                 },
747                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
748                                                 BlockHeight:    2,
749                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
750                                         },
751                                         {
752                                                 Seq: 0,
753                                                 NumOfVote: map[string]uint64{
754                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
755                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
756                                                 },
757                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
758                                                 BlockHeight:    0,
759                                                 CoinbaseReward: map[string]uint64{},
760                                         },
761                                 },
762                         },
763                         wantChainData: &chainData{
764                                 bestBlockHeader: &types.BlockHeader{
765                                         Height:            1,
766                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
767                                 },
768                                 lastIrrBlockHeader: &types.BlockHeader{
769                                         Height:            1,
770                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
771                                 },
772                                 storedBlocks: []*types.Block{
773                                         {
774                                                 BlockHeader: types.BlockHeader{
775                                                         Height: 0,
776                                                 },
777                                                 Transactions: []*types.Tx{
778                                                         types.NewTx(types.TxData{
779                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
780                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
781                                                         }),
782                                                         types.NewTx(types.TxData{
783                                                                 Inputs: []*types.TxInput{
784                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
785                                                                 },
786                                                                 Outputs: []*types.TxOutput{
787                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
788                                                                 },
789                                                         }),
790                                                 },
791                                         },
792                                         {
793                                                 BlockHeader: types.BlockHeader{
794                                                         Height:            1,
795                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
796                                                 },
797                                                 Transactions: []*types.Tx{
798                                                         types.NewTx(types.TxData{
799                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
800                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
801                                                         }),
802                                                         types.NewTx(types.TxData{
803                                                                 Inputs: []*types.TxInput{
804                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
805                                                                 },
806                                                                 Outputs: []*types.TxOutput{
807                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
808                                                                 },
809                                                         }),
810                                                 },
811                                         },
812                                 },
813                                 utxoViewPoint: &state.UtxoViewpoint{
814                                         Entries: map[bc.Hash]*storage.UtxoEntry{
815                                                 testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
816                                                 testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
817                                         },
818                                 },
819                                 consensusResults: []*state.ConsensusResult{
820                                         {
821                                                 Seq: 1,
822                                                 NumOfVote: map[string]uint64{
823                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000 + 100000000 - 2000,
824                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
825                                                 },
826                                                 BlockHash:      testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
827                                                 BlockHeight:    1,
828                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + 2000},
829                                         },
830                                         {
831                                                 Seq: 0,
832                                                 NumOfVote: map[string]uint64{
833                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
834                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
835                                                 },
836                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
837                                                 BlockHeight:    0,
838                                                 CoinbaseReward: map[string]uint64{},
839                                         },
840                                 },
841                         },
842                 },
843                 {
844                         desc:                   "rollback from height 3 to 2, RoundVoteBlockNums is 2",
845                         movStartHeight:         10,
846                         RoundVoteBlockNums:     2,
847                         rollbackToTargetHeight: 2,
848                         beforeChainData: &chainData{
849                                 bestBlockHeader: &types.BlockHeader{
850                                         Height:            3,
851                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
852                                 },
853                                 lastIrrBlockHeader: &types.BlockHeader{
854                                         Height:            3,
855                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
856                                 },
857                                 utxoViewPoint: &state.UtxoViewpoint{
858                                         Entries: map[bc.Hash]*storage.UtxoEntry{
859                                                 testutil.MustDecodeHash("5b4d53fbc2a489847f34dd0e0c085797fe7cf0a3a9a2f3231d11bdad16dea2be"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
860                                                 testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
861                                                 testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
862                                                 testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
863                                         },
864                                 },
865                                 storedBlocks: []*types.Block{
866                                         {
867                                                 BlockHeader: types.BlockHeader{
868                                                         Height: 0,
869                                                 },
870                                                 Transactions: []*types.Tx{
871                                                         types.NewTx(types.TxData{
872                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
873                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
874                                                         }),
875                                                         types.NewTx(types.TxData{
876                                                                 Inputs: []*types.TxInput{
877                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
878                                                                 },
879                                                                 Outputs: []*types.TxOutput{
880                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
881                                                                 },
882                                                         }),
883                                                 },
884                                         },
885                                         {
886                                                 BlockHeader: types.BlockHeader{
887                                                         Height:            1,
888                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
889                                                 },
890                                                 Transactions: []*types.Tx{
891                                                         types.NewTx(types.TxData{
892                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
893                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
894                                                         }),
895                                                         types.NewTx(types.TxData{
896                                                                 Inputs: []*types.TxInput{
897                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
898                                                                 },
899                                                                 Outputs: []*types.TxOutput{
900                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
901                                                                 },
902                                                         }),
903                                                 },
904                                         },
905                                         {
906                                                 BlockHeader: types.BlockHeader{
907                                                         Height:            2,
908                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
909                                                 },
910                                                 Transactions: []*types.Tx{
911                                                         types.NewTx(types.TxData{
912                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
913                                                                 Outputs: []*types.TxOutput{
914                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
915                                                                 },
916                                                         }),
917                                                         types.NewTx(types.TxData{
918                                                                 Inputs: []*types.TxInput{
919                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
920                                                                 },
921                                                                 Outputs: []*types.TxOutput{
922                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
923                                                                 },
924                                                         }),
925                                                 },
926                                         },
927                                         {
928                                                 BlockHeader: types.BlockHeader{
929                                                         Height:            3,
930                                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
931                                                 },
932                                                 Transactions: []*types.Tx{
933                                                         types.NewTx(types.TxData{
934                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
935                                                                 Outputs: []*types.TxOutput{
936                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
937                                                                         types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
938                                                                 },
939                                                         }),
940                                                         types.NewTx(types.TxData{
941                                                                 Inputs: []*types.TxInput{
942                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 400000000, 0, []byte{0, 1}),
943                                                                 },
944                                                                 Outputs: []*types.TxOutput{
945                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
946                                                                 },
947                                                         }),
948                                                 },
949                                         },
950                                 },
951                                 consensusResults: []*state.ConsensusResult{
952                                         {
953                                                 Seq: 2,
954                                                 NumOfVote: map[string]uint64{
955                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 609998000,
956                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
957                                                 },
958                                                 BlockHash:      testutil.MustDecodeHash("0c1cd1c0a6e6161f437c382cca21ce28921234ed7c4f252f7e4bbc9a523b74ac"),
959                                                 BlockHeight:    3,
960                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(3) + 240000000},
961                                         },
962                                         {
963                                                 Seq: 1,
964                                                 NumOfVote: map[string]uint64{
965                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 449998000,
966                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
967                                                 },
968                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
969                                                 BlockHeight:    2,
970                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
971                                         },
972                                         {
973                                                 Seq: 0,
974                                                 NumOfVote: map[string]uint64{
975                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
976                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
977                                                 },
978                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
979                                                 BlockHeight:    0,
980                                                 CoinbaseReward: map[string]uint64{},
981                                         },
982                                 },
983                         },
984                         wantChainData: &chainData{
985                                 bestBlockHeader: &types.BlockHeader{
986                                         Height:            2,
987                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
988                                 },
989                                 lastIrrBlockHeader: &types.BlockHeader{
990                                         Height:            2,
991                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
992                                 },
993                                 storedBlocks: []*types.Block{
994                                         {
995                                                 BlockHeader: types.BlockHeader{
996                                                         Height: 0,
997                                                 },
998                                                 Transactions: []*types.Tx{
999                                                         types.NewTx(types.TxData{
1000                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1001                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
1002                                                         }),
1003                                                         types.NewTx(types.TxData{
1004                                                                 Inputs: []*types.TxInput{
1005                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
1006                                                                 },
1007                                                                 Outputs: []*types.TxOutput{
1008                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
1009                                                                 },
1010                                                         }),
1011                                                 },
1012                                         },
1013                                         {
1014                                                 BlockHeader: types.BlockHeader{
1015                                                         Height:            1,
1016                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
1017                                                 },
1018                                                 Transactions: []*types.Tx{
1019                                                         types.NewTx(types.TxData{
1020                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1021                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
1022                                                         }),
1023                                                         types.NewTx(types.TxData{
1024                                                                 Inputs: []*types.TxInput{
1025                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
1026                                                                 },
1027                                                                 Outputs: []*types.TxOutput{
1028                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1029                                                                 },
1030                                                         }),
1031                                                 },
1032                                         },
1033                                         {
1034                                                 BlockHeader: types.BlockHeader{
1035                                                         Height:            2,
1036                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
1037                                                 },
1038                                                 Transactions: []*types.Tx{
1039                                                         types.NewTx(types.TxData{
1040                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1041                                                                 Outputs: []*types.TxOutput{
1042                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1043                                                                 },
1044                                                         }),
1045                                                         types.NewTx(types.TxData{
1046                                                                 Inputs: []*types.TxInput{
1047                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
1048                                                                 },
1049                                                                 Outputs: []*types.TxOutput{
1050                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1051                                                                 },
1052                                                         }),
1053                                                 },
1054                                         },
1055                                 },
1056                                 utxoViewPoint: &state.UtxoViewpoint{
1057                                         Entries: map[bc.Hash]*storage.UtxoEntry{
1058                                                 testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
1059                                                 testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
1060                                                 testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
1061                                         },
1062                                 },
1063                                 consensusResults: []*state.ConsensusResult{
1064                                         {
1065                                                 Seq: 1,
1066                                                 NumOfVote: map[string]uint64{
1067                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000 + 100000000 - 2000 + 250000000,
1068                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1069                                                 },
1070                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
1071                                                 BlockHeight:    2,
1072                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
1073                                         },
1074                                         {
1075                                                 Seq: 0,
1076                                                 NumOfVote: map[string]uint64{
1077                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
1078                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1079                                                 },
1080                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
1081                                                 BlockHeight:    0,
1082                                                 CoinbaseReward: map[string]uint64{},
1083                                         },
1084                                 },
1085                         },
1086                 },
1087                 {
1088                         desc:                   "rollback from height 4 to 2, there is two chain , and round vote block nums is 2",
1089                         movStartHeight:         10,
1090                         RoundVoteBlockNums:     2,
1091                         rollbackToTargetHeight: 2,
1092                         beforeChainData: &chainData{
1093                                 bestBlockHeader: &types.BlockHeader{
1094                                         Height:            5,
1095                                         Timestamp:         uint64(1528945008),
1096                                         PreviousBlockHash: testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
1097                                 },
1098                                 lastIrrBlockHeader: &types.BlockHeader{
1099                                         Height:            5,
1100                                         Timestamp:         uint64(1528945008),
1101                                         PreviousBlockHash: testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
1102                                 },
1103                                 utxoViewPoint: &state.UtxoViewpoint{
1104                                         Entries: map[bc.Hash]*storage.UtxoEntry{
1105                                                 testutil.MustDecodeHash("3c07f3159d4e2a0527129d644a8fcd09ce26555e94c9c7f348464120ef463275"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 5, Spent: true},
1106                                                 testutil.MustDecodeHash("927144d2a391e17dc12184f5ae163b994984132ad72c34d854bb9009b68cd4cc"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 4, Spent: true},
1107                                                 testutil.MustDecodeHash("fa43f4ca43bcb0e94d43b52c56d1740dea1329b59a44f6ee045d70446881c514"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
1108                                                 testutil.MustDecodeHash("f081ccd0c97ae34bc5580a0405d9b1ed0b0ed9e1410f1786b7112b348a412e3d"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 4, Spent: true},
1109                                                 testutil.MustDecodeHash("2704fa67c76e020b08ffa3f93a500acebcaf68b45ba43d8b3b08b68c5bb1eff1"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 3, Spent: true},
1110                                                 testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
1111                                                 testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
1112                                                 testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
1113                                         },
1114                                 },
1115                                 storedBlocks: []*types.Block{
1116                                         {
1117                                                 BlockHeader: types.BlockHeader{
1118                                                         Height: 0,
1119                                                 },
1120                                                 Transactions: []*types.Tx{
1121                                                         types.NewTx(types.TxData{
1122                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1123                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
1124                                                         }),
1125                                                         types.NewTx(types.TxData{
1126                                                                 Inputs: []*types.TxInput{
1127                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
1128                                                                 },
1129                                                                 Outputs: []*types.TxOutput{
1130                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
1131                                                                 },
1132                                                         }),
1133                                                 },
1134                                         },
1135                                         {
1136                                                 BlockHeader: types.BlockHeader{
1137                                                         Height:            1,
1138                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
1139                                                 },
1140                                                 Transactions: []*types.Tx{
1141                                                         types.NewTx(types.TxData{
1142                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1143                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
1144                                                         }),
1145                                                         types.NewTx(types.TxData{
1146                                                                 Inputs: []*types.TxInput{
1147                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
1148                                                                 },
1149                                                                 Outputs: []*types.TxOutput{
1150                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1151                                                                 },
1152                                                         }),
1153                                                 },
1154                                         },
1155                                         {
1156                                                 BlockHeader: types.BlockHeader{
1157                                                         Height:            2,
1158                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
1159                                                 },
1160                                                 Transactions: []*types.Tx{
1161                                                         types.NewTx(types.TxData{
1162                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1163                                                                 Outputs: []*types.TxOutput{
1164                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1165                                                                 },
1166                                                         }),
1167                                                         types.NewTx(types.TxData{
1168                                                                 Inputs: []*types.TxInput{
1169                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
1170                                                                 },
1171                                                                 Outputs: []*types.TxOutput{
1172                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1173                                                                 },
1174                                                         }),
1175                                                 },
1176                                         },
1177                                         {
1178                                                 BlockHeader: types.BlockHeader{
1179                                                         Height:            3,
1180                                                         Timestamp:         uint64(1528945000),
1181                                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
1182                                                 },
1183                                                 Transactions: []*types.Tx{
1184                                                         types.NewTx(types.TxData{
1185                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1186                                                                 Outputs: []*types.TxOutput{
1187                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1188                                                                         types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
1189                                                                 },
1190                                                         }),
1191                                                         types.NewTx(types.TxData{
1192                                                                 Inputs: []*types.TxInput{
1193                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 440000000, 0, []byte{0, 1}),
1194                                                                 },
1195                                                                 Outputs: []*types.TxOutput{
1196                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1197                                                                 },
1198                                                         }),
1199                                                 },
1200                                         },
1201                                         {
1202                                                 BlockHeader: types.BlockHeader{
1203                                                         Height:            4,
1204                                                         Timestamp:         uint64(1528945005),
1205                                                         PreviousBlockHash: testutil.MustDecodeHash("bec3dd0d6fecb80a6f3a0373ec2ae676cc1ce72af83546f3d4672231c9b080e6"),
1206                                                 },
1207                                                 Transactions: []*types.Tx{
1208                                                         types.NewTx(types.TxData{
1209                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1210                                                                 Outputs: []*types.TxOutput{
1211                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1212                                                                 },
1213                                                         }),
1214                                                         types.NewTx(types.TxData{
1215                                                                 Inputs: []*types.TxInput{
1216                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 500000000, 0, []byte{0, 1}),
1217                                                                 },
1218                                                                 Outputs: []*types.TxOutput{
1219                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 160000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1220                                                                 },
1221                                                         }),
1222                                                 },
1223                                         },
1224                                         {
1225                                                 BlockHeader: types.BlockHeader{
1226                                                         Height:            3,
1227                                                         Timestamp:         uint64(1528945001),
1228                                                         PreviousBlockHash: testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
1229                                                 },
1230                                                 Transactions: []*types.Tx{
1231                                                         types.NewTx(types.TxData{
1232                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1233                                                                 Outputs: []*types.TxOutput{
1234                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1235                                                                         types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(1)+consensus.BlockSubsidy(2)+50002000, []byte{0x51}),
1236                                                                 },
1237                                                         }),
1238                                                         types.NewTx(types.TxData{
1239                                                                 Inputs: []*types.TxInput{
1240                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 402000000, 0, []byte{0, 1}),
1241                                                                 },
1242                                                                 Outputs: []*types.TxOutput{
1243                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 200000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1244                                                                 },
1245                                                         }),
1246                                                 },
1247                                         },
1248                                         {
1249                                                 BlockHeader: types.BlockHeader{
1250                                                         Height:            4,
1251                                                         Timestamp:         uint64(1528945006),
1252                                                         PreviousBlockHash: testutil.MustDecodeHash("1d2d01a97d1239de51b4e7d0fb522f71771d2d4f9a0a559154519859cc44a230"),
1253                                                 },
1254                                                 Transactions: []*types.Tx{
1255                                                         types.NewTx(types.TxData{
1256                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1257                                                                 Outputs: []*types.TxOutput{
1258                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1259                                                                 },
1260                                                         }),
1261                                                         types.NewTx(types.TxData{
1262                                                                 Inputs: []*types.TxInput{
1263                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 410000000, 0, []byte{0, 1}),
1264                                                                 },
1265                                                                 Outputs: []*types.TxOutput{
1266                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 170000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1267                                                                 },
1268                                                         }),
1269                                                 },
1270                                         },
1271                                         {
1272                                                 BlockHeader: types.BlockHeader{
1273                                                         Height:            5,
1274                                                         Timestamp:         uint64(1528945008),
1275                                                         PreviousBlockHash: testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
1276                                                 },
1277                                                 Transactions: []*types.Tx{
1278                                                         types.NewTx(types.TxData{
1279                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1280                                                                 Outputs: []*types.TxOutput{
1281                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1282                                                                         types.NewIntraChainOutput(bc.AssetID{}, consensus.BlockSubsidy(3)+consensus.BlockSubsidy(4)+520000000, []byte{0x51}),
1283                                                                 },
1284                                                         }),
1285                                                         types.NewTx(types.TxData{
1286                                                                 Inputs: []*types.TxInput{
1287                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 400004000, 0, []byte{0, 1}),
1288                                                                 },
1289                                                                 Outputs: []*types.TxOutput{
1290                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 160004000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1291                                                                 },
1292                                                         }),
1293                                                 },
1294                                         },
1295                                 },
1296                                 consensusResults: []*state.ConsensusResult{
1297                                         {
1298                                                 Seq: 3,
1299                                                 NumOfVote: map[string]uint64{
1300                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 980002000,
1301                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1302                                                 },
1303                                                 BlockHash:      testutil.MustDecodeHash("075ce54f7d4c1b524474265219be52238beec98138f0c0a4d21f1a6b0047914a"),
1304                                                 BlockHeight:    5,
1305                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(5) + 240000000},
1306                                         },
1307                                         {
1308                                                 Seq: 2,
1309                                                 NumOfVote: map[string]uint64{
1310                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 819998000,
1311                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1312                                                 },
1313                                                 BlockHash:      testutil.MustDecodeHash("64a41230412f26a5c0a1734515d9e177bd3573be2ae1d55c4533509a7c9cce8e"),
1314                                                 BlockHeight:    4,
1315                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(3) + consensus.BlockSubsidy(4) + 442000000},
1316                                         },
1317                                         {
1318                                                 Seq: 1,
1319                                                 NumOfVote: map[string]uint64{
1320                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 449998000,
1321                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1322                                                 },
1323                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
1324                                                 BlockHeight:    2,
1325                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
1326                                         },
1327                                         {
1328                                                 Seq: 0,
1329                                                 NumOfVote: map[string]uint64{
1330                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
1331                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1332                                                 },
1333                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
1334                                                 BlockHeight:    0,
1335                                                 CoinbaseReward: map[string]uint64{},
1336                                         },
1337                                 },
1338                         },
1339                         wantChainData: &chainData{
1340                                 bestBlockHeader: &types.BlockHeader{
1341                                         Height:            2,
1342                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
1343                                 },
1344                                 lastIrrBlockHeader: &types.BlockHeader{
1345                                         Height:            2,
1346                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
1347                                 },
1348                                 storedBlocks: []*types.Block{
1349                                         {
1350                                                 BlockHeader: types.BlockHeader{
1351                                                         Height: 0,
1352                                                 },
1353                                                 Transactions: []*types.Tx{
1354                                                         types.NewTx(types.TxData{
1355                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1356                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
1357                                                         }),
1358                                                         types.NewTx(types.TxData{
1359                                                                 Inputs: []*types.TxInput{
1360                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 100000000, 0, []byte{0, 1}),
1361                                                                 },
1362                                                                 Outputs: []*types.TxOutput{
1363                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 100000000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
1364                                                                 },
1365                                                         }),
1366                                                 },
1367                                         },
1368                                         {
1369                                                 BlockHeader: types.BlockHeader{
1370                                                         Height:            1,
1371                                                         PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
1372                                                 },
1373                                                 Transactions: []*types.Tx{
1374                                                         types.NewTx(types.TxData{
1375                                                                 Inputs:  []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1376                                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51})},
1377                                                         }),
1378                                                         types.NewTx(types.TxData{
1379                                                                 Inputs: []*types.TxInput{
1380                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 200000000, 0, []byte{0, 1}),
1381                                                                 },
1382                                                                 Outputs: []*types.TxOutput{
1383                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 200000000-2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1384                                                                 },
1385                                                         }),
1386                                                 },
1387                                         },
1388                                         {
1389                                                 BlockHeader: types.BlockHeader{
1390                                                         Height:            2,
1391                                                         PreviousBlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"),
1392                                                 },
1393                                                 Transactions: []*types.Tx{
1394                                                         types.NewTx(types.TxData{
1395                                                                 Inputs: []*types.TxInput{types.NewCoinbaseInput([]byte{0x01})},
1396                                                                 Outputs: []*types.TxOutput{
1397                                                                         types.NewIntraChainOutput(bc.AssetID{}, 0, []byte{0x51}),
1398                                                                 },
1399                                                         }),
1400                                                         types.NewTx(types.TxData{
1401                                                                 Inputs: []*types.TxInput{
1402                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 300000000, 0, []byte{0, 1}),
1403                                                                 },
1404                                                                 Outputs: []*types.TxOutput{
1405                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 250000000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
1406                                                                 },
1407                                                         }),
1408                                                 },
1409                                         },
1410                                 },
1411                                 consensusResults: []*state.ConsensusResult{
1412                                         {
1413                                                 Seq: 1,
1414                                                 NumOfVote: map[string]uint64{
1415                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000 + 100000000 - 2000 + 250000000,
1416                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1417                                                 },
1418                                                 BlockHash:      testutil.MustDecodeHash("699d3f59d4afe7eea85df31814628d7d34ace7f5e76d6c9ebf4c54482d2cd333"),
1419                                                 BlockHeight:    2,
1420                                                 CoinbaseReward: map[string]uint64{"51": consensus.BlockSubsidy(1) + consensus.BlockSubsidy(2) + 50002000},
1421                                         },
1422                                         {
1423                                                 Seq: 0,
1424                                                 NumOfVote: map[string]uint64{
1425                                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000,
1426                                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 200000000,
1427                                                 },
1428                                                 BlockHash:      testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"),
1429                                                 BlockHeight:    0,
1430                                                 CoinbaseReward: map[string]uint64{},
1431                                         },
1432                                 },
1433                                 utxoViewPoint: &state.UtxoViewpoint{
1434                                         Entries: map[bc.Hash]*storage.UtxoEntry{
1435                                                 testutil.MustDecodeHash("9fb6f213e3130810e755675707d0e9870c79a91c575638a580fae65568ca9e99"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true},
1436                                                 testutil.MustDecodeHash("3d1617908e624a2042c23be4f671b261d5b8a2a61b8421ee6a702c6e071428a8"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true},
1437                                                 testutil.MustDecodeHash("4c2b719d10fc6b9c2a7c343491ddd8c0d6bd57f9c6680bfda557689c182cf685"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 2, Spent: true},
1438                                         },
1439                                 },
1440                         },
1441                 },
1442         }
1443
1444         for i, c := range cases {
1445                 consensus.ActiveNetParams.RoundVoteBlockNums = c.RoundVoteBlockNums
1446
1447                 movDB := dbm.NewDB("mov_db", "leveldb", "mov_db")
1448                 movCore := mov.NewCoreWithDB(movDatabase.NewLevelDBMovStore(movDB), c.movStartHeight)
1449
1450                 blockDB := dbm.NewDB("block_db", "leveldb", "block_db")
1451                 store := database.NewStore(blockDB)
1452
1453                 mustSaveBlocks(c.beforeChainData.storedBlocks, store)
1454
1455                 var mainChainBlockHeaders []*types.BlockHeader
1456                 for _, block := range c.beforeChainData.storedBlocks {
1457                         mainChainBlockHeaders = append(mainChainBlockHeaders, &block.BlockHeader)
1458                 }
1459                 if err := store.SaveChainStatus(c.beforeChainData.bestBlockHeader, c.beforeChainData.lastIrrBlockHeader, mainChainBlockHeaders, c.beforeChainData.utxoViewPoint, c.beforeChainData.consensusResults); err != nil {
1460                         t.Fatal(err)
1461                 }
1462
1463                 chain, err := protocol.NewChain(store, nil, []protocol.Protocoler{movCore}, nil)
1464                 if err != nil {
1465                         t.Fatal(err)
1466                 }
1467
1468                 if err := chain.Rollback(c.rollbackToTargetHeight); err != nil {
1469                         t.Fatal(err)
1470                 }
1471
1472                 if !testutil.DeepEqual(chain.LastIrreversibleHeader(), c.wantChainData.lastIrrBlockHeader) {
1473                         t.Errorf("lastIrrBlockHeader is not right!")
1474                 }
1475
1476                 if !testutil.DeepEqual(chain.BestBlockHeader(), c.wantChainData.bestBlockHeader) {
1477                         t.Errorf("wantBestBlockHeader is not right!")
1478                 }
1479
1480                 gotConsensusResults := mustGetConsensusResultFromStore(store, chain)
1481                 if !testutil.DeepEqual(gotConsensusResults, c.wantChainData.consensusResults) {
1482                         t.Errorf("cases#%d(%s) wantBestConsensusResult is not right!", i, c.desc)
1483                 }
1484
1485                 gotBlocks := mustGetBlocksFromStore(chain)
1486                 if !blocksEquals(gotBlocks, c.wantChainData.storedBlocks) {
1487                         t.Errorf("cases#%d(%s) the blocks is not same!", i, c.desc)
1488                 }
1489
1490                 gotTransactions := getBcTransactions(gotBlocks)
1491                 gotUtxoViewPoint := state.NewUtxoViewpoint()
1492                 if err = store.GetTransactionsUtxo(gotUtxoViewPoint, gotTransactions); err != nil {
1493                         t.Fatal(err)
1494                 }
1495
1496                 if !testutil.DeepEqual(gotUtxoViewPoint, c.wantChainData.utxoViewPoint) {
1497                         t.Fatal(err)
1498                 }
1499
1500                 blockDB.Close()
1501                 os.RemoveAll("block_db")
1502                 movDB.Close()
1503                 os.RemoveAll("mov_db")
1504
1505         }
1506 }
1507
1508 func blocksEquals(blocks1 []*types.Block, blocks2 []*types.Block) bool {
1509         blockHashMap1 := make(map[string]interface{})
1510         for _, block := range blocks1 {
1511                 hash := block.Hash()
1512                 blockHashMap1[hash.String()] = nil
1513         }
1514
1515         blockHashMap2 := make(map[string]interface{})
1516         for _, block := range blocks2 {
1517                 hash := block.Hash()
1518                 blockHashMap2[hash.String()] = nil
1519         }
1520         return testutil.DeepEqual(blockHashMap1, blockHashMap2)
1521 }
1522
1523 func getBcTransactions(blocks []*types.Block) []*bc.Tx {
1524         var txs []*bc.Tx
1525         for _, block := range blocks {
1526                 for _, tx := range block.Transactions {
1527                         txs = append(txs, tx.Tx)
1528                 }
1529         }
1530         return txs
1531 }
1532
1533 func mustSaveBlocks(blocks []*types.Block, store *database.Store) {
1534         for _, block := range blocks {
1535                 status := bc.NewTransactionStatus()
1536                 for index := range block.Transactions {
1537                         if err := status.SetStatus(index, false); err != nil {
1538                                 panic(err)
1539                         }
1540                 }
1541                 if err := store.SaveBlock(block, status); err != nil {
1542                         panic(err)
1543                 }
1544         }
1545 }
1546
1547 func mustGetBlocksFromStore(chain *protocol.Chain) []*types.Block {
1548         var blocks []*types.Block
1549         for height := int64(chain.BestBlockHeight()); height >= 0; height-- {
1550                 block, err := chain.GetBlockByHeight(uint64(height))
1551                 if err != nil {
1552                         panic(err)
1553                 }
1554
1555                 blocks = append(blocks, block)
1556         }
1557         return blocks
1558 }
1559
1560 func mustGetConsensusResultFromStore(store *database.Store, chain *protocol.Chain) []*state.ConsensusResult {
1561         var consensusResults []*state.ConsensusResult
1562         for seq := int64(state.CalcVoteSeq(chain.BestBlockHeight())); seq >= 0; seq-- {
1563                 consensusResult, err := store.GetConsensusResult(uint64(seq))
1564                 if err != nil {
1565                         panic(err)
1566                 }
1567
1568                 consensusResults = append(consensusResults, consensusResult)
1569         }
1570         return consensusResults
1571 }