OSDN Git Service

fix log
[bytom/vapor.git] / protocol / consensus_node_manager_test.go
1 package protocol
2
3 import (
4         "testing"
5
6         "github.com/vapor/consensus"
7         "github.com/vapor/crypto/ed25519/chainkd"
8         "github.com/vapor/database/storage"
9         "github.com/vapor/protocol/bc"
10         "github.com/vapor/protocol/bc/types"
11         "github.com/vapor/protocol/state"
12         "github.com/vapor/testutil"
13 )
14
15 func TestGetConsensusNodes(t *testing.T) {
16         cases := []struct {
17                 desc                   string
18                 prevSeqConsensusResult *state.ConsensusResult
19                 storedBlockHeaders     []*types.BlockHeader
20                 storedBlocks           []*types.Block
21                 prevBlockHash          bc.Hash
22                 bestBlockHeight        uint64
23                 wantConsensusNodes     []*state.ConsensusNode
24         }{
25                 {
26                         desc: "block hash in main chain",
27                         prevSeqConsensusResult: &state.ConsensusResult{
28                                 Seq: 1,
29                                 NumOfVote: map[string]uint64{
30                                         "0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825": 838063475500000,
31                                         "e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093": 474794800000000,
32                                         "1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842": 833812985000000,
33                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 285918061999999,
34                                         "b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef": 1228455289930297,
35                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 274387690000000,
36                                 },
37                                 BlockHash:   testutil.MustDecodeHash("65a92adc3c17657e4f0f032f1de83597dbbc6c29c24626d1533c8215f81c99e6"),
38                                 BlockHeight: 1200,
39                         },
40                         storedBlockHeaders: []*types.BlockHeader{
41                                 {
42                                         Height:            1200,
43                                         PreviousBlockHash: testutil.MustDecodeHash("7f5d567f2ad9de9af4af6e6cc81943abcd042e5a6329c83708e3578be3b5fc7d"),
44                                 },
45                                 {
46                                         Height:            1201,
47                                         PreviousBlockHash: testutil.MustDecodeHash("65a92adc3c17657e4f0f032f1de83597dbbc6c29c24626d1533c8215f81c99e6"),
48                                 },
49                                 {
50                                         Height:            1202,
51                                         PreviousBlockHash: testutil.MustDecodeHash("9ff85d12c91ad5500b3dfe80bb0b4d4496ab29aec37f71e839fdd0a1c92a614f"),
52                                 },
53                                 {
54                                         Height:            1203,
55                                         PreviousBlockHash: testutil.MustDecodeHash("559b02b183e275e79dcfab23c66004264127f461ff8b90b3a336b2f958bf96e2"),
56                                 },
57                                 {
58                                         Height:            1204,
59                                         PreviousBlockHash: testutil.MustDecodeHash("f77d1330abc1a58ce5909581e6f2059153e116e9044e284609e07efd5f0b239e"),
60                                 },
61                         },
62                         prevBlockHash:   testutil.MustDecodeHash("f77d1330abc1a58ce5909581e6f2059153e116e9044e284609e07efd5f0b239e"), // 1204
63                         bestBlockHeight: 1230,
64                         wantConsensusNodes: []*state.ConsensusNode{
65                                 {
66                                         XPub:    mustDecodeXPub("b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef"),
67                                         VoteNum: 1228455289930297,
68                                         Order:   0,
69                                 },
70                                 {
71                                         XPub:    mustDecodeXPub("0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825"),
72                                         VoteNum: 838063475500000,
73                                         Order:   1,
74                                 },
75                                 {
76                                         XPub:    mustDecodeXPub("1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842"),
77                                         VoteNum: 833812985000000,
78                                         Order:   2,
79                                 },
80                                 {
81                                         XPub:    mustDecodeXPub("e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093"),
82                                         VoteNum: 474794800000000,
83                                         Order:   3,
84                                 },
85                                 {
86                                         XPub:    mustDecodeXPub("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9"),
87                                         VoteNum: 285918061999999,
88                                         Order:   4,
89                                 },
90                                 {
91                                         XPub:    mustDecodeXPub("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67"),
92                                         VoteNum: 274387690000000,
93                                         Order:   5,
94                                 },
95                         },
96                 },
97                 {
98                         desc: "block hash in main chain, block height in the begin of round",
99                         prevSeqConsensusResult: &state.ConsensusResult{
100                                 Seq: 1,
101                                 NumOfVote: map[string]uint64{
102                                         "0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825": 838063475500000,
103                                         "e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093": 474794800000000,
104                                         "1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842": 833812985000000,
105                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 285918061999999,
106                                         "b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef": 1228455289930297,
107                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 274387690000000,
108                                 },
109                                 BlockHash:   testutil.MustDecodeHash("65a92adc3c17657e4f0f032f1de83597dbbc6c29c24626d1533c8215f81c99e6"),
110                                 BlockHeight: 1200,
111                         },
112                         storedBlockHeaders: []*types.BlockHeader{
113                                 {
114                                         Height:            1200,
115                                         PreviousBlockHash: testutil.MustDecodeHash("7f5d567f2ad9de9af4af6e6cc81943abcd042e5a6329c83708e3578be3b5fc7d"),
116                                 },
117                                 {
118                                         Height:            1201,
119                                         PreviousBlockHash: testutil.MustDecodeHash("65a92adc3c17657e4f0f032f1de83597dbbc6c29c24626d1533c8215f81c99e6"),
120                                 },
121                         },
122                         prevBlockHash:   testutil.MustDecodeHash("65a92adc3c17657e4f0f032f1de83597dbbc6c29c24626d1533c8215f81c99e6"), // 1201
123                         bestBlockHeight: 1230,
124                         wantConsensusNodes: []*state.ConsensusNode{
125                                 {
126                                         XPub:    mustDecodeXPub("b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef"),
127                                         VoteNum: 1228455289930297,
128                                         Order:   0,
129                                 },
130                                 {
131                                         XPub:    mustDecodeXPub("0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825"),
132                                         VoteNum: 838063475500000,
133                                         Order:   1,
134                                 },
135                                 {
136                                         XPub:    mustDecodeXPub("1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842"),
137                                         VoteNum: 833812985000000,
138                                         Order:   2,
139                                 },
140                                 {
141                                         XPub:    mustDecodeXPub("e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093"),
142                                         VoteNum: 474794800000000,
143                                         Order:   3,
144                                 },
145                                 {
146                                         XPub:    mustDecodeXPub("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9"),
147                                         VoteNum: 285918061999999,
148                                         Order:   4,
149                                 },
150                                 {
151                                         XPub:    mustDecodeXPub("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67"),
152                                         VoteNum: 274387690000000,
153                                         Order:   5,
154                                 },
155                         },
156                 },
157                 {
158                         desc: "block hash in main chain, the consensus result is incomplete",
159                         prevSeqConsensusResult: &state.ConsensusResult{
160                                 Seq: 1,
161                                 NumOfVote: map[string]uint64{
162                                         "0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825": 838063475500000,
163                                         "e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093": 474794800000000,
164                                         "1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842": 833812985000000,
165                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 285918061999999,
166                                         "b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef": 1228455289930297,
167                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 274387690000000,
168                                 },
169                                 BlockHash:      testutil.MustDecodeHash("ef24de31371b4d34363011b6c8b065b1acaad9264d9abae2253d584e0d3a8739"),
170                                 BlockHeight:    1198,
171                                 CoinbaseReward: make(map[string]uint64),
172                         },
173                         storedBlockHeaders: []*types.BlockHeader{
174                                 {
175                                         Height:            1198,
176                                         PreviousBlockHash: testutil.MustDecodeHash("4d3ecf28f3045df23764792f41af17fc20518cc8e83673dc2d0ce07bbf084d7d"),
177                                 },
178                                 {
179                                         Height:            1199,
180                                         PreviousBlockHash: testutil.MustDecodeHash("ef24de31371b4d34363011b6c8b065b1acaad9264d9abae2253d584e0d3a8739"),
181                                 },
182                                 {
183                                         Height:            1200,
184                                         PreviousBlockHash: testutil.MustDecodeHash("608d82b3660255186fb2b035cfb2ca86e986433218cd2eca2e79611e855a87d3"),
185                                 },
186                                 {
187                                         Height:            1201,
188                                         PreviousBlockHash: testutil.MustDecodeHash("73a2a6a098727877e288a4520f2d8076d700b561277ed7c3f533e3f176496888"),
189                                 },
190                         },
191                         storedBlocks: []*types.Block{
192                                 {
193                                         BlockHeader: types.BlockHeader{
194                                                 Height:            1199,
195                                                 PreviousBlockHash: testutil.MustDecodeHash("ef24de31371b4d34363011b6c8b065b1acaad9264d9abae2253d584e0d3a8739"),
196                                         },
197                                         Transactions: []*types.Tx{
198                                                 {
199                                                         TxData: types.TxData{
200                                                                 Inputs: []*types.TxInput{
201                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 1E14, 0, []byte{0, 1}),
202                                                                 },
203                                                                 Outputs: []*types.TxOutput{
204                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1E14, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
205                                                                 },
206                                                         },
207                                                 },
208                                         },
209                                 },
210                                 {
211                                         BlockHeader: types.BlockHeader{
212                                                 Height:            1200,
213                                                 PreviousBlockHash: testutil.MustDecodeHash("608d82b3660255186fb2b035cfb2ca86e986433218cd2eca2e79611e855a87d3"),
214                                         },
215                                         Transactions: []*types.Tx{
216                                                 {
217                                                         TxData: types.TxData{
218                                                                 Inputs: []*types.TxInput{
219                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 3E14, 0, []byte{0, 1}),
220                                                                 },
221                                                                 Outputs: []*types.TxOutput{
222                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 3E14, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
223                                                                 },
224                                                         },
225                                                 },
226                                         },
227                                 },
228                         },
229                         prevBlockHash:   testutil.MustDecodeHash("73a2a6a098727877e288a4520f2d8076d700b561277ed7c3f533e3f176496888"), // 1201
230                         bestBlockHeight: 1230,
231                         wantConsensusNodes: []*state.ConsensusNode{
232                                 {
233                                         XPub:    mustDecodeXPub("b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef"),
234                                         VoteNum: 1228455289930297,
235                                         Order:   0,
236                                 },
237                                 {
238                                         XPub:    mustDecodeXPub("0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825"),
239                                         VoteNum: 838063475500000,
240                                         Order:   1,
241                                 },
242                                 {
243                                         XPub:    mustDecodeXPub("1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842"),
244                                         VoteNum: 833812985000000,
245                                         Order:   2,
246                                 },
247                                 {
248                                         XPub:    mustDecodeXPub("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9"),
249                                         VoteNum: 585918061999999,
250                                         Order:   3,
251                                 },
252                                 {
253                                         XPub:    mustDecodeXPub("e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093"),
254                                         VoteNum: 474794800000000,
255                                         Order:   4,
256                                 },
257                                 {
258                                         XPub:    mustDecodeXPub("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67"),
259                                         VoteNum: 374387690000000,
260                                         Order:   5,
261                                 },
262                         },
263                 },
264                 {
265                         desc: "block hash in fork chain",
266                         prevSeqConsensusResult: &state.ConsensusResult{
267                                 Seq: 1,
268                                 NumOfVote: map[string]uint64{
269                                         "0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825": 838063475500000,
270                                         "e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093": 474794800000000,
271                                         "1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842": 833812985000000,
272                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 285918061999999,
273                                         "b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef": 1228455289930297,
274                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 274387690000000,
275                                 },
276                                 BlockHash:      testutil.MustDecodeHash("73a2a6a098727877e288a4520f2d8076d700b561277ed7c3f533e3f176496888"),
277                                 BlockHeight:    1200,
278                                 CoinbaseReward: map[string]uint64{"0001": 1E8},
279                         },
280                         storedBlockHeaders: []*types.BlockHeader{
281                                 // main chain
282                                 {
283                                         Height:            1198,
284                                         PreviousBlockHash: testutil.MustDecodeHash("4d3ecf28f3045df23764792f41af17fc20518cc8e83673dc2d0ce07bbf084d7d"),
285                                 },
286                                 {
287                                         Height:            1199,
288                                         PreviousBlockHash: testutil.MustDecodeHash("ef24de31371b4d34363011b6c8b065b1acaad9264d9abae2253d584e0d3a8739"),
289                                 },
290                                 {
291                                         Height:            1200,
292                                         PreviousBlockHash: testutil.MustDecodeHash("608d82b3660255186fb2b035cfb2ca86e986433218cd2eca2e79611e855a87d3"),
293                                 },
294                                 {
295                                         Height:            1201,
296                                         PreviousBlockHash: testutil.MustDecodeHash("73a2a6a098727877e288a4520f2d8076d700b561277ed7c3f533e3f176496888"),
297                                 },
298                                 {
299                                         Height:            1202,
300                                         PreviousBlockHash: testutil.MustDecodeHash("a5be1d1177eb027327baedb869f902f74850476d0b9432a30391a3165d3af7cc"),
301                                 },
302                                 // fork chain, fork height in 1198, rollback 1200, 1199, append 1199, 1200 
303                                 {
304                                         Height:            1199,
305                                         PreviousBlockHash: testutil.MustDecodeHash("ef24de31371b4d34363011b6c8b065b1acaad9264d9abae2253d584e0d3a8739"),
306                                         Timestamp:         1, // in order to make different hash
307                                 },
308                                 {
309                                         Height:            1200,
310                                         PreviousBlockHash: testutil.MustDecodeHash("cde3d8a99dee1cd44fb37f499c1980338a49ac1b9d5e6f693bd0a6f87c74e4d2"),
311                                 },
312                                 {
313                                         Height:            1201,
314                                         PreviousBlockHash: testutil.MustDecodeHash("f819efb4baecbeb63aff6d4b14b549f1bd35955d461abaa0058a26f74c4f62da"),
315                                 },
316                         },
317                         storedBlocks: []*types.Block{
318                                 // main chain
319                                 {
320                                         BlockHeader: types.BlockHeader{
321                                                 Height:            1199,
322                                                 PreviousBlockHash: testutil.MustDecodeHash("ef24de31371b4d34363011b6c8b065b1acaad9264d9abae2253d584e0d3a8739"),
323                                         },
324                                         Transactions: []*types.Tx{
325                                                 {
326                                                         TxData: types.TxData{
327                                                                 Inputs: []*types.TxInput{
328                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 1E14, 0, []byte{0, 1}),
329                                                                 },
330                                                                 Outputs: []*types.TxOutput{
331                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1E14, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
332                                                                 },
333                                                         },
334                                                 },
335                                         },
336                                 },
337                                 {
338                                         BlockHeader: types.BlockHeader{
339                                                 Height:            1200,
340                                                 PreviousBlockHash: testutil.MustDecodeHash("608d82b3660255186fb2b035cfb2ca86e986433218cd2eca2e79611e855a87d3"),
341                                         },
342                                         Transactions: []*types.Tx{
343                                                 {
344                                                         TxData: types.TxData{
345                                                                 Inputs: []*types.TxInput{
346                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 2E14, 0, []byte{0, 1}),
347                                                                 },
348                                                                 Outputs: []*types.TxOutput{
349                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2E14, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
350                                                                 },
351                                                         },
352                                                 },
353                                         },
354                                 },
355                                 // fork chain
356                                 {
357                                         BlockHeader: types.BlockHeader{
358                                                 Height:            1199,
359                                                 PreviousBlockHash: testutil.MustDecodeHash("ef24de31371b4d34363011b6c8b065b1acaad9264d9abae2253d584e0d3a8739"),
360                                                 Timestamp:         1, // in order to make different hash
361                                         },
362                                         Transactions: []*types.Tx{
363                                                 {
364                                                         TxData: types.TxData{
365                                                                 Inputs: []*types.TxInput{
366                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 2E14, 0, []byte{0, 1}),
367                                                                 },
368                                                                 Outputs: []*types.TxOutput{
369                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2E14, []byte{0, 1}, testutil.MustDecodeHexString("0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825")),
370                                                                 },
371                                                         },
372                                                 },
373                                         },
374                                 },
375                                 {
376                                         BlockHeader: types.BlockHeader{
377                                                 Height:            1200,
378                                                 PreviousBlockHash: testutil.MustDecodeHash("cde3d8a99dee1cd44fb37f499c1980338a49ac1b9d5e6f693bd0a6f87c74e4d2"),
379                                         },
380                                         Transactions: []*types.Tx{
381                                                 {
382                                                         TxData: types.TxData{
383                                                                 Inputs: []*types.TxInput{
384                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 5E14, 0, []byte{0, 1}),
385                                                                 },
386                                                                 Outputs: []*types.TxOutput{
387                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 5E14, []byte{0, 1}, testutil.MustDecodeHexString("b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef")),
388                                                                 },
389                                                         },
390                                                 },
391                                         },
392                                 },
393                         },
394                         prevBlockHash:   testutil.MustDecodeHash("f819efb4baecbeb63aff6d4b14b549f1bd35955d461abaa0058a26f74c4f62da"), // 1201
395                         bestBlockHeight: 1230,
396                         wantConsensusNodes: []*state.ConsensusNode{
397                                 {
398                                         XPub:    mustDecodeXPub("b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef"),
399                                         VoteNum: 1728455289930297,
400                                         Order:   0,
401                                 },
402                                 {
403                                         XPub:    mustDecodeXPub("0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825"),
404                                         VoteNum: 1038063475500000,
405                                         Order:   1,
406                                 },
407                                 {
408                                         XPub:    mustDecodeXPub("1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842"),
409                                         VoteNum: 833812985000000,
410                                         Order:   2,
411                                 },
412                                 {
413                                         XPub:    mustDecodeXPub("e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093"),
414                                         VoteNum: 474794800000000,
415                                         Order:   3,
416                                 },
417                                 {
418                                         XPub:    mustDecodeXPub("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67"),
419                                         VoteNum: 174387690000000,
420                                         Order:   4,
421                                 },
422                         },
423                 },
424                 {
425                         desc: "block hash in fork chain, the consensus result is incomplete",
426                         prevSeqConsensusResult: &state.ConsensusResult{
427                                 Seq: 1,
428                                 NumOfVote: map[string]uint64{
429                                         "0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825": 838063475500000,
430                                         "e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093": 474794800000000,
431                                         "1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842": 833812985000000,
432                                         "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 285918061999999,
433                                         "b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef": 1228455289930297,
434                                         "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 274387690000000,
435                                 },
436                                 BlockHash:      testutil.MustDecodeHash("a0239137437634c933fa1200f801783a532b88e9556a0746b75a5832aac09bfc"),
437                                 BlockHeight:    1198,
438                                 CoinbaseReward: map[string]uint64{"0001": 1E8},
439                         },
440                         storedBlockHeaders: []*types.BlockHeader{
441                                 // main chain
442                                 {
443                                         Height:            1197,
444                                         PreviousBlockHash: testutil.MustDecodeHash("dda6bc15d7de8dadbbb283e90d24bd05a9fd0f721023f53822209281c5ce1698"),
445                                 },
446                                 {
447                                         Height:            1198,
448                                         PreviousBlockHash: testutil.MustDecodeHash("b9c3d0ce5eceac94b53208360c7e100bb342a00ba70c990dc48ce959295793e6"),
449                                 },
450                                 {
451                                         Height:            1199,
452                                         PreviousBlockHash: testutil.MustDecodeHash("a0239137437634c933fa1200f801783a532b88e9556a0746b75a5832aac09bfc"),
453                                 },
454                                 {
455                                         Height:            1200,
456                                         PreviousBlockHash: testutil.MustDecodeHash("9e135b0372e670d02fb4a1d4af6b1a4cc1f33fcec3499a2e735f128b6b9ec144"),
457                                 },
458                                 {
459                                         Height:            1201,
460                                         PreviousBlockHash: testutil.MustDecodeHash("c907b3e07505e0da5cbd98e8fb45f5b5a1e3645813fb855555d085c1e104cd5b"),
461                                 },
462                                 {
463                                         Height:            1202,
464                                         PreviousBlockHash: testutil.MustDecodeHash("99fa16d4e2a01093af987ef39080eb76ed8ded7ce22d50d76b4c3e2ac660214a"),
465                                 },
466                                 // fork chain, fork height in 1197, roll back 1198, append 1198, 1199, 1200
467                                 {
468                                         Height:            1198,
469                                         PreviousBlockHash: testutil.MustDecodeHash("b9c3d0ce5eceac94b53208360c7e100bb342a00ba70c990dc48ce959295793e6"),
470                                         Timestamp:         1, // in order to make different hash
471                                 },
472                                 {
473                                         Height:            1199,
474                                         PreviousBlockHash: testutil.MustDecodeHash("dc209b2c1ead7794f81ac9cdafc136875ec9d3b8525f1482a430ce762685aece"),
475                                 },
476                                 {
477                                         Height:            1200,
478                                         PreviousBlockHash: testutil.MustDecodeHash("fe85f3a22c4c41b03904f19475ec265138aae57be05b0c3ade0be2773fd35eb2"),
479                                 },
480                                 {
481                                         Height:            1201,
482                                         PreviousBlockHash: testutil.MustDecodeHash("01f1a4eb35af3347080497c014c3b980bcfc1c836fdbe6b95f6fa0984ac14f8a"),
483                                 },
484                         },
485                         storedBlocks: []*types.Block{
486                                 // main chain
487                                 {
488                                         BlockHeader: types.BlockHeader{
489                                                 Height:            1197,
490                                                 PreviousBlockHash: testutil.MustDecodeHash("dda6bc15d7de8dadbbb283e90d24bd05a9fd0f721023f53822209281c5ce1698"),
491                                         },
492                                 },
493                                 {
494                                         BlockHeader: types.BlockHeader{
495                                                 Height:            1198,
496                                                 PreviousBlockHash: testutil.MustDecodeHash("b9c3d0ce5eceac94b53208360c7e100bb342a00ba70c990dc48ce959295793e6"),
497                                         },
498                                         Transactions: []*types.Tx{
499                                                 {
500                                                         TxData: types.TxData{
501                                                                 Inputs: []*types.TxInput{
502                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 1E14, 0, []byte{0, 1}),
503                                                                 },
504                                                                 Outputs: []*types.TxOutput{
505                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1E14, []byte{0, 1}, testutil.MustDecodeHexString("1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842")),
506                                                                 },
507                                                         },
508                                                 },
509                                         },
510                                 },
511                                 {
512                                         BlockHeader: types.BlockHeader{
513                                                 Height:            1199,
514                                                 PreviousBlockHash: testutil.MustDecodeHash("a0239137437634c933fa1200f801783a532b88e9556a0746b75a5832aac09bfc"),
515                                         },
516                                         Transactions: []*types.Tx{
517                                                 {
518                                                         TxData: types.TxData{
519                                                                 Inputs: []*types.TxInput{
520                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 1E14, 0, []byte{0, 1}),
521                                                                 },
522                                                                 Outputs: []*types.TxOutput{
523                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 1E14, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
524                                                                 },
525                                                         },
526                                                 },
527                                         },
528                                 },
529                                 {
530                                         BlockHeader: types.BlockHeader{
531                                                 Height:            1200,
532                                                 PreviousBlockHash: testutil.MustDecodeHash("9e135b0372e670d02fb4a1d4af6b1a4cc1f33fcec3499a2e735f128b6b9ec144"),
533                                         },
534                                         Transactions: []*types.Tx{
535                                                 {
536                                                         TxData: types.TxData{
537                                                                 Inputs: []*types.TxInput{
538                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 2E14, 0, []byte{0, 1}),
539                                                                 },
540                                                                 Outputs: []*types.TxOutput{
541                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 2E14, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")),
542                                                                 },
543                                                         },
544                                                 },
545                                         },
546                                 },
547                                 // fork chain
548                                 {
549                                         BlockHeader: types.BlockHeader{
550                                                 Height:            1198,
551                                                 PreviousBlockHash: testutil.MustDecodeHash("b9c3d0ce5eceac94b53208360c7e100bb342a00ba70c990dc48ce959295793e6"),
552                                                 Timestamp:         1, // in order to make different hash
553                                         },
554                                         Transactions: []*types.Tx{
555                                                 {
556                                                         TxData: types.TxData{
557                                                                 Inputs: []*types.TxInput{
558                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 5E14, 0, []byte{0, 1}),
559                                                                 },
560                                                                 Outputs: []*types.TxOutput{
561                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 5E14, []byte{0, 1}, testutil.MustDecodeHexString("1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842")),
562                                                                 },
563                                                         },
564                                                 },
565                                         },
566                                 },
567                                 {
568                                         BlockHeader: types.BlockHeader{
569                                                 Height:            1199,
570                                                 PreviousBlockHash: testutil.MustDecodeHash("dc209b2c1ead7794f81ac9cdafc136875ec9d3b8525f1482a430ce762685aece"),
571                                         },
572                                         Transactions: []*types.Tx{
573                                                 {
574                                                         TxData: types.TxData{
575                                                                 Inputs: []*types.TxInput{
576                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 3E14, 0, []byte{0, 1}),
577                                                                 },
578                                                                 Outputs: []*types.TxOutput{
579                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 3E14, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")),
580                                                                 },
581                                                         },
582                                                 },
583                                         },
584                                 },
585                                 {
586                                         BlockHeader: types.BlockHeader{
587                                                 Height:            1200,
588                                                 PreviousBlockHash: testutil.MustDecodeHash("fe85f3a22c4c41b03904f19475ec265138aae57be05b0c3ade0be2773fd35eb2"),
589                                         },
590                                         Transactions: []*types.Tx{
591                                                 {
592                                                         TxData: types.TxData{
593                                                                 Inputs: []*types.TxInput{
594                                                                         types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 5E14, 0, []byte{0, 1}),
595                                                                 },
596                                                                 Outputs: []*types.TxOutput{
597                                                                         types.NewVoteOutput(*consensus.BTMAssetID, 5E14, []byte{0, 1}, testutil.MustDecodeHexString("b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef")),
598                                                                 },
599                                                         },
600                                                 },
601                                         },
602                                 },
603                         },
604                         prevBlockHash:   testutil.MustDecodeHash("01f1a4eb35af3347080497c014c3b980bcfc1c836fdbe6b95f6fa0984ac14f8a"), // 1201
605                         bestBlockHeight: 1230,
606                         wantConsensusNodes: []*state.ConsensusNode{
607                                 {
608                                         XPub:    mustDecodeXPub("b928e46bb01e834fdf167185e31b15de7cc257af8bbdf17f9c7fefd5bb97b306d048b6bc0da2097152c1c2ff38333c756a543adbba7030a447dcc776b8ac64ef"),
609                                         VoteNum: 1728455289930297,
610                                         Order:   0,
611                                 },
612                                 {
613                                         XPub:    mustDecodeXPub("1bec3a35da038ec7a76c40986e80b5af2dcef60341970e3fc58b4db0797bd4ca9b2cbf3d7ab820832e22a80b5b86ae1427f7f706a7780089958b2862e7bc0842"),
614                                         VoteNum: 1233812985000000,
615                                         Order:   1,
616                                 },
617                                 {
618                                         XPub:    mustDecodeXPub("0f8669abbd3cc0a167156188e428f940088d5b2f36bb3449df71d2bdc5e077814ea3f68628eef279ed435f51ee26cff00f8bd28fabfd500bedb2a9e369f5c825"),
619                                         VoteNum: 838063475500000,
620                                         Order:   2,
621                                 },
622                                 {
623                                         XPub:    mustDecodeXPub("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67"),
624                                         VoteNum: 574387690000000,
625                                         Order:   3,
626                                 },
627                                 {
628                                         XPub:    mustDecodeXPub("e7f458ee8d2ba19b0fdc7410d1fd57e9c2e1a79377c661d66c55effe49d7ffc920e40510442d4a10b7bea06c09fb0b41f52601135adaaa7136204db36106c093"),
629                                         VoteNum: 474794800000000,
630                                         Order:   4,
631                                 },
632                                 {
633                                         XPub:    mustDecodeXPub("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9"),
634                                         VoteNum: 285918061999999,
635                                         Order:   5,
636                                 },
637                         },
638                 },
639         }
640
641         for i, c := range cases {
642                 store := newDummyStore()
643                 for _, header := range c.storedBlockHeaders {
644                         store.SaveBlockHeader(header)
645                 }
646
647                 for _, block := range c.storedBlocks {
648                         store.SaveBlock(block, nil)
649                 }
650
651                 store.SetConsensusResult(c.prevSeqConsensusResult)
652
653                 chain := &Chain{
654                         store:           store,
655                         bestBlockHeader: &types.BlockHeader{Height: c.bestBlockHeight},
656                 }
657                 gotConsensusNodes, err := chain.getConsensusNodes(&c.prevBlockHash)
658                 if err != nil {
659                         t.Fatal(err)
660                 }
661
662                 wantConsensusNodes := make(map[string]*state.ConsensusNode)
663                 for _, node := range c.wantConsensusNodes {
664                         wantConsensusNodes[node.XPub.String()] = node
665                 }
666
667                 if !testutil.DeepEqual(gotConsensusNodes, wantConsensusNodes) {
668                         t.Errorf("#%d (%s) got consensus nodes:%v, want consensus nodes:%v", i, c.desc, gotConsensusNodes, wantConsensusNodes)
669                 }
670         }
671 }
672
673 func mustDecodeXPub(xpub string) chainkd.XPub {
674         bytes := testutil.MustDecodeHexString(xpub)
675         var result [64]byte
676         copy(result[:], bytes)
677         return result
678 }
679
680 type dummyStore struct {
681         blockHeaders     map[string]*types.BlockHeader
682         blocks           map[string]*types.Block
683         consensusResults map[uint64]*state.ConsensusResult
684 }
685
686 func newDummyStore() *dummyStore {
687         return &dummyStore{
688                 blockHeaders:     make(map[string]*types.BlockHeader),
689                 consensusResults: make(map[uint64]*state.ConsensusResult),
690                 blocks:           make(map[string]*types.Block),
691         }
692 }
693
694 func (s *dummyStore) BlockExist(*bc.Hash) bool {
695         return false
696 }
697
698 func (s *dummyStore) GetBlock(hash *bc.Hash) (*types.Block, error) {
699         return s.blocks[hash.String()], nil
700 }
701
702 func (s *dummyStore) GetBlockHeader(hash *bc.Hash) (*types.BlockHeader, error) {
703         return s.blockHeaders[hash.String()], nil
704 }
705
706 func (s *dummyStore) GetStoreStatus() *BlockStoreState {
707         return nil
708 }
709
710 func (s *dummyStore) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) {
711         return nil, nil
712 }
713
714 func (s *dummyStore) GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error {
715         return nil
716 }
717
718 func (s *dummyStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) {
719         return nil, nil
720 }
721
722 func (s *dummyStore) GetConsensusResult(seq uint64) (*state.ConsensusResult, error) {
723         return s.consensusResults[seq], nil
724 }
725
726 func (s *dummyStore) SetConsensusResult(consensusResult *state.ConsensusResult) {
727         s.consensusResults[consensusResult.Seq] = consensusResult
728 }
729
730 func (s *dummyStore) GetMainChainHash(uint64) (*bc.Hash, error) {
731         return nil, nil
732 }
733
734 func (s *dummyStore) GetBlockHashesByHeight(uint64) ([]*bc.Hash, error) {
735         return nil, nil
736 }
737
738 func (s *dummyStore) SaveBlock(block *types.Block, _ *bc.TransactionStatus) error {
739         hash := block.Hash()
740         s.blocks[hash.String()] = block
741         return nil
742 }
743
744 func (s *dummyStore) SaveBlockHeader(header *types.BlockHeader) error {
745         hash := header.Hash()
746         s.blockHeaders[hash.String()] = header
747         return nil
748 }
749
750 func (s *dummyStore) SaveChainStatus(*types.BlockHeader, *types.BlockHeader, []*types.BlockHeader, *state.UtxoViewpoint, []*state.ConsensusResult) error {
751         return nil
752 }