OSDN Git Service

add mov core test (#435)
[bytom/vapor.git] / application / mov / mov_core_test.go
1 package mov
2
3 import (
4         "math"
5         "os"
6         "testing"
7
8         "github.com/vapor/application/mov/common"
9         "github.com/vapor/application/mov/database"
10         "github.com/vapor/application/mov/mock"
11         "github.com/vapor/consensus"
12         dbm "github.com/vapor/database/leveldb"
13         "github.com/vapor/protocol/bc"
14         "github.com/vapor/protocol/bc/types"
15         "github.com/vapor/protocol/vm"
16         "github.com/vapor/testutil"
17 )
18
19 func TestApplyBlock(t *testing.T) {
20         initBlockHeader := &types.BlockHeader{Height: 1, PreviousBlockHash: bc.Hash{}}
21         cases := []struct {
22                 desc        string
23                 block       *types.Block
24                 blockFunc   testFun
25                 initOrders  []*common.Order
26                 wantOrders  []*common.Order
27                 wantDBState *common.MovDatabaseState
28                 wantError   error
29         }{
30                 {
31                         desc: "apply block has pending order transaction",
32                         block: &types.Block{
33                                 BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
34                                 Transactions: []*types.Tx{
35                                         mock.Btc2EthMakerTxs[0], mock.Eth2BtcMakerTxs[0],
36                                 },
37                         },
38                         blockFunc:   applyBlock,
39                         wantOrders:  []*common.Order{mock.MustNewOrderFromOutput(mock.Btc2EthMakerTxs[0], 0), mock.MustNewOrderFromOutput(mock.Eth2BtcMakerTxs[0], 0)},
40                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
41                 },
42                 {
43                         desc: "apply block has full matched transaction",
44                         block: &types.Block{
45                                 BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
46                                 Transactions: []*types.Tx{
47                                         mock.MatchedTxs[1],
48                                 },
49                         },
50                         blockFunc:   applyBlock,
51                         initOrders:  []*common.Order{mock.Btc2EthOrders[0], mock.Btc2EthOrders[1], mock.Eth2BtcOrders[0]},
52                         wantOrders:  []*common.Order{mock.Btc2EthOrders[1]},
53                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
54                 },
55                 {
56                         desc: "apply block has partial matched transaction",
57                         block: &types.Block{
58                                 BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
59                                 Transactions: []*types.Tx{
60                                         mock.MatchedTxs[0],
61                                 },
62                         },
63                         blockFunc:   applyBlock,
64                         initOrders:  []*common.Order{mock.Btc2EthOrders[0], mock.Eth2BtcOrders[1]},
65                         wantOrders:  []*common.Order{mock.MustNewOrderFromOutput(mock.MatchedTxs[0], 1)},
66                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
67                 },
68                 {
69                         desc: "apply block has two partial matched transaction",
70                         block: &types.Block{
71                                 BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
72                                 Transactions: []*types.Tx{
73                                         mock.MatchedTxs[2], mock.MatchedTxs[3],
74                                 },
75                         },
76                         blockFunc:   applyBlock,
77                         initOrders:  []*common.Order{mock.Btc2EthOrders[0], mock.Btc2EthOrders[1], mock.Eth2BtcOrders[2]},
78                         wantOrders:  []*common.Order{mock.MustNewOrderFromOutput(mock.MatchedTxs[3], 1)},
79                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
80                 },
81                 {
82                         desc: "apply block has partial matched transaction by pending orders from tx pool",
83                         block: &types.Block{
84                                 BlockHeader: types.BlockHeader{Height: 2, PreviousBlockHash: initBlockHeader.Hash()},
85                                 Transactions: []*types.Tx{
86                                         mock.Btc2EthMakerTxs[0],
87                                         mock.Eth2BtcMakerTxs[1],
88                                         mock.MatchedTxs[4],
89                                 },
90                         },
91                         blockFunc:   applyBlock,
92                         initOrders:  []*common.Order{},
93                         wantOrders:  []*common.Order{mock.MustNewOrderFromOutput(mock.MatchedTxs[4], 1)},
94                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: hashPtr(testutil.MustDecodeHash("88dbcde57bb2b53b107d7494f20f1f1a892307a019705980c3510890449c0020"))},
95                 },
96                 {
97                         desc: "detach block has pending order transaction",
98                         block: &types.Block{
99                                 BlockHeader: *initBlockHeader,
100                                 Transactions: []*types.Tx{
101                                         mock.Btc2EthMakerTxs[0], mock.Eth2BtcMakerTxs[1],
102                                 },
103                         },
104                         blockFunc:   detachBlock,
105                         initOrders:  []*common.Order{mock.MustNewOrderFromOutput(mock.Btc2EthMakerTxs[0], 0), mock.MustNewOrderFromOutput(mock.Eth2BtcMakerTxs[1], 0)},
106                         wantOrders:  []*common.Order{},
107                         wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
108                 },
109                 {
110                         desc: "detach block has full matched transaction",
111                         block: &types.Block{
112                                 BlockHeader: *initBlockHeader,
113                                 Transactions: []*types.Tx{
114                                         mock.MatchedTxs[1],
115                                 },
116                         },
117                         blockFunc:   detachBlock,
118                         initOrders:  []*common.Order{mock.Btc2EthOrders[1]},
119                         wantOrders:  []*common.Order{mock.Btc2EthOrders[0], mock.Btc2EthOrders[1], mock.Eth2BtcOrders[0]},
120                         wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
121                 },
122                 {
123                         desc: "detach block has partial matched transaction",
124                         block: &types.Block{
125                                 BlockHeader: *initBlockHeader,
126                                 Transactions: []*types.Tx{
127                                         mock.MatchedTxs[0],
128                                 },
129                         },
130                         blockFunc:   detachBlock,
131                         initOrders:  []*common.Order{mock.MustNewOrderFromOutput(mock.MatchedTxs[0], 1)},
132                         wantOrders:  []*common.Order{mock.Btc2EthOrders[0], mock.Eth2BtcOrders[1]},
133                         wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
134                 },
135                 {
136                         desc: "detach block has two partial matched transaction",
137                         block: &types.Block{
138                                 BlockHeader: *initBlockHeader,
139                                 Transactions: []*types.Tx{
140                                         mock.MatchedTxs[2], mock.MatchedTxs[3],
141                                 },
142                         },
143                         blockFunc:   detachBlock,
144                         initOrders:  []*common.Order{mock.MustNewOrderFromOutput(mock.MatchedTxs[3], 1)},
145                         wantOrders:  []*common.Order{mock.Btc2EthOrders[0], mock.Btc2EthOrders[1], mock.Eth2BtcOrders[2]},
146                         wantDBState: &common.MovDatabaseState{Height: 0, Hash: &bc.Hash{}},
147                 },
148         }
149
150         defer os.RemoveAll("temp")
151         for i, c := range cases {
152                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
153                 store := database.NewLevelDBMovStore(testDB)
154                 if err := store.InitDBState(0, &bc.Hash{}); err != nil {
155                         t.Fatal(err)
156                 }
157
158                 if err := store.ProcessOrders(c.initOrders, nil, initBlockHeader); err != nil {
159                         t.Fatal(err)
160                 }
161
162                 movCore := &MovCore{movStore: store}
163                 if err := c.blockFunc(movCore, c.block); err != c.wantError {
164                         t.Errorf("#%d(%s):apply block want error(%v), got error(%v)", i, c.desc, c.wantError, err)
165                 }
166
167                 gotOrders := queryAllOrders(store)
168                 if !ordersEquals(c.wantOrders, gotOrders) {
169                         t.Errorf("#%d(%s):apply block want orders(%v), got orders(%v)", i, c.desc, c.wantOrders, gotOrders)
170                 }
171
172                 dbState, err := store.GetMovDatabaseState()
173                 if err != nil {
174                         t.Fatal(err)
175                 }
176
177                 if !testutil.DeepEqual(c.wantDBState, dbState) {
178                         t.Errorf("#%d(%s):apply block want db state(%v), got db state(%v)", i, c.desc, c.wantDBState, dbState)
179                 }
180
181                 testDB.Close()
182                 os.RemoveAll("temp")
183         }
184 }
185
186 func TestValidateBlock(t *testing.T) {
187         cases := []struct {
188                 desc          string
189                 block         *types.Block
190                 verifyResults []*bc.TxVerifyResult
191                 wantError     error
192         }{
193                 {
194                         desc: "block only has maker tx",
195                         block: &types.Block{
196                                 Transactions: []*types.Tx{
197                                         mock.Eth2BtcMakerTxs[0],
198                                         mock.Btc2EthMakerTxs[0],
199                                 },
200                         },
201                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}},
202                         wantError: nil,
203                 },
204                 {
205                         desc: "block only has matched tx",
206                         block: &types.Block{
207                                 Transactions: []*types.Tx{
208                                         mock.MatchedTxs[0],
209                                         mock.MatchedTxs[1],
210                                         mock.MatchedTxs[2],
211                                 },
212                         },
213                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}, {StatusFail: false}},
214                         wantError: nil,
215                 },
216                 {
217                         desc: "block has maker tx and matched tx",
218                         block: &types.Block{
219                                 Transactions: []*types.Tx{
220                                         mock.Eth2BtcMakerTxs[0],
221                                         mock.Btc2EthMakerTxs[0],
222                                         mock.MatchedTxs[0],
223                                         mock.MatchedTxs[1],
224                                         mock.MatchedTxs[2],
225                                 },
226                         },
227                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}, {StatusFail: false}, {StatusFail: false}, {StatusFail: false}},
228                         wantError: nil,
229                 },
230                 {
231                         desc: "status fail of maker tx is true",
232                         block: &types.Block{
233                                 Transactions: []*types.Tx{
234                                         mock.Eth2BtcMakerTxs[0],
235                                         mock.Btc2EthMakerTxs[0],
236                                 },
237                         },
238                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: true}},
239                         wantError: errStatusFailMustFalse,
240                 },
241                 {
242                         desc: "status fail of matched tx is true",
243                         block: &types.Block{
244                                 Transactions: []*types.Tx{
245                                         mock.MatchedTxs[1],
246                                         mock.MatchedTxs[2],
247                                 },
248                         },
249                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: true}},
250                         wantError: errStatusFailMustFalse,
251                 },
252                 {
253                         desc: "asset id in matched tx is not unique",
254                         block: &types.Block{
255                                 Transactions: []*types.Tx{
256                                         types.NewTx(types.TxData{
257                                                 Inputs: []*types.TxInput{
258                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(0), vm.Int64Bytes(1)}, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, mock.Btc2EthOrders[0].Utxo.ControlProgram),
259                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(1), vm.Int64Bytes(1)}, *mock.Eth2BtcOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Eth2BtcOrders[0].Utxo.Amount, mock.Eth2BtcOrders[0].Utxo.SourcePos, mock.Eth2BtcOrders[0].Utxo.ControlProgram),
260                                                 },
261                                                 Outputs: []*types.TxOutput{
262                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].ToAssetID, 500, testutil.MustDecodeHexString("51")),
263                                                         types.NewIntraChainOutput(*mock.Eth2BtcOrders[0].ToAssetID, 10, testutil.MustDecodeHexString("53")),
264                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].ToAssetID, 10, []byte{0x51}),
265                                                 },
266                                         }),
267                                 },
268                         },
269                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: true}},
270                         wantError: errAssetIDMustUniqueInMatchedTx,
271                 },
272                 {
273                         desc: "common input in the matched tx",
274                         block: &types.Block{
275                                 Transactions: []*types.Tx{
276                                         types.NewTx(types.TxData{
277                                                 Inputs: []*types.TxInput{
278                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(0), vm.Int64Bytes(1)}, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, mock.Btc2EthOrders[0].Utxo.ControlProgram),
279                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(1), vm.Int64Bytes(1)}, *mock.Eth2BtcOrders[0].Utxo.SourceID, *mock.Eth2BtcOrders[0].FromAssetID, mock.Eth2BtcOrders[0].Utxo.Amount, mock.Eth2BtcOrders[0].Utxo.SourcePos, mock.Eth2BtcOrders[0].Utxo.ControlProgram),
280                                                         types.NewSpendInput(nil, testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), *consensus.BTMAssetID, 100, 0, []byte{0x51}),
281                                                 },
282                                                 Outputs: []*types.TxOutput{
283                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].ToAssetID, 500, testutil.MustDecodeHexString("51")),
284                                                         types.NewIntraChainOutput(*mock.Eth2BtcOrders[0].ToAssetID, 10, testutil.MustDecodeHexString("53")),
285                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].ToAssetID, 10, []byte{0x51}),
286                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 100, []byte{0x51}),
287                                                 },
288                                         }),
289                                 },
290                         },
291                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
292                         wantError: errInputProgramMustP2WMCScript,
293                 },
294                 {
295                         desc: "cancel order in the matched tx",
296                         block: &types.Block{
297                                 Transactions: []*types.Tx{
298                                         types.NewTx(types.TxData{
299                                                 Inputs: []*types.TxInput{
300                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(0), vm.Int64Bytes(1)}, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, mock.Btc2EthOrders[0].Utxo.ControlProgram),
301                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(1), vm.Int64Bytes(1)}, *mock.Eth2BtcOrders[0].Utxo.SourceID, *mock.Eth2BtcOrders[0].FromAssetID, mock.Eth2BtcOrders[0].Utxo.Amount, mock.Eth2BtcOrders[0].Utxo.SourcePos, mock.Eth2BtcOrders[0].Utxo.ControlProgram),
302                                                         types.NewSpendInput([][]byte{{}, {}, vm.Int64Bytes(2)}, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, mock.Btc2EthOrders[0].Utxo.ControlProgram),
303                                                 },
304                                                 Outputs: []*types.TxOutput{
305                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].ToAssetID, 500, testutil.MustDecodeHexString("51")),
306                                                         types.NewIntraChainOutput(*mock.Eth2BtcOrders[0].ToAssetID, 10, testutil.MustDecodeHexString("53")),
307                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].ToAssetID, 10, []byte{0x51}),
308                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 100, []byte{0x51}),
309                                                 },
310                                         }),
311                                 },
312                         },
313                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
314                         wantError: errExistCancelOrderInMatchedTx,
315                 },
316                 {
317                         desc: "common input in the cancel order tx",
318                         block: &types.Block{
319                                 Transactions: []*types.Tx{
320                                         types.NewTx(types.TxData{
321                                                 Inputs: []*types.TxInput{
322                                                         types.NewSpendInput([][]byte{{}, {}, vm.Int64Bytes(2)}, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, mock.Btc2EthOrders[0].Utxo.ControlProgram),
323                                                         types.NewSpendInput(nil, testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), *consensus.BTMAssetID, 100, 0, []byte{0x51}),
324                                                 },
325                                                 Outputs: []*types.TxOutput{
326                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, 10, testutil.MustDecodeHexString("51")),
327                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 100, []byte{0x51}),
328                                                 },
329                                         }),
330                                 },
331                         },
332                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
333                         wantError: errInputProgramMustP2WMCScript,
334                 },
335                 {
336                         desc: "amount of fee greater than max fee amount",
337                         block: &types.Block{
338                                 Transactions: []*types.Tx{
339                                         types.NewTx(types.TxData{
340                                                 Inputs: []*types.TxInput{
341                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(0), vm.Int64Bytes(1)}, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, mock.Btc2EthOrders[0].Utxo.ControlProgram),
342                                                         types.NewSpendInput([][]byte{vm.Int64Bytes(10), vm.Int64Bytes(1), vm.Int64Bytes(0)}, *mock.Eth2BtcOrders[2].Utxo.SourceID, *mock.Eth2BtcOrders[2].FromAssetID, mock.Eth2BtcOrders[2].Utxo.Amount, mock.Eth2BtcOrders[2].Utxo.SourcePos, mock.Eth2BtcOrders[2].Utxo.ControlProgram),
343                                                 },
344                                                 Outputs: []*types.TxOutput{
345                                                         types.NewIntraChainOutput(*mock.Btc2EthOrders[0].ToAssetID, 500, testutil.MustDecodeHexString("51")),
346                                                         types.NewIntraChainOutput(*mock.Eth2BtcOrders[2].ToAssetID, 10, testutil.MustDecodeHexString("55")),
347                                                         // re-order
348                                                         types.NewIntraChainOutput(*mock.Eth2BtcOrders[2].FromAssetID, 270, mock.Eth2BtcOrders[2].Utxo.ControlProgram),
349                                                         // fee
350                                                         types.NewIntraChainOutput(*mock.Eth2BtcOrders[2].FromAssetID, 40, []byte{0x59}),
351                                                 },
352                                         }),
353                                 },
354                         },
355                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
356                         wantError: errAmountOfFeeGreaterThanMaximum,
357                 },
358                 {
359                         desc: "ratio numerator is zero",
360                         block: &types.Block{
361                                 Transactions: []*types.Tx{
362                                         types.NewTx(types.TxData{
363                                                 Inputs:  []*types.TxInput{types.NewSpendInput(nil, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, []byte{0x51})},
364                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("51"), 0, 1))},
365                                         }),
366                                 },
367                         },
368                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
369                         wantError: errRatioOfTradeLessThanZero,
370                 },
371                 {
372                         desc: "ratio denominator is zero",
373                         block: &types.Block{
374                                 Transactions: []*types.Tx{
375                                         types.NewTx(types.TxData{
376                                                 Inputs:  []*types.TxInput{types.NewSpendInput(nil, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, []byte{0x51})},
377                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("51"), 1, 0))},
378                                         }),
379                                 },
380                         },
381                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
382                         wantError: errRatioOfTradeLessThanZero,
383                 },
384                 {
385                         desc: "ratio numerator product input amount is overflow",
386                         block: &types.Block{
387                                 Transactions: []*types.Tx{
388                                         types.NewTx(types.TxData{
389                                                 Inputs:  []*types.TxInput{types.NewSpendInput(nil, *mock.Btc2EthOrders[0].Utxo.SourceID, *mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.Btc2EthOrders[0].Utxo.SourcePos, []byte{0x51})},
390                                                 Outputs: []*types.TxOutput{types.NewIntraChainOutput(*mock.Btc2EthOrders[0].FromAssetID, mock.Btc2EthOrders[0].Utxo.Amount, mock.MustCreateP2WMCProgram(mock.ETH, testutil.MustDecodeHexString("51"), math.MaxInt64, 10))},
391                                         }),
392                                 },
393                         },
394                         verifyResults: []*bc.TxVerifyResult{{StatusFail: false}},
395                         wantError: errNumeratorOfRatioIsOverflow,
396                 },
397         }
398
399         for i, c := range cases {
400                 movCore := &MovCore{}
401                 if err := movCore.ValidateBlock(c.block, c.verifyResults); err != c.wantError {
402                         t.Errorf("#%d(%s):validate block want error(%v), got error(%v)", i, c.desc, c.wantError, err)
403                 }
404         }
405 }
406
407 type testFun func(movCore *MovCore, block *types.Block) error
408
409 func applyBlock(movCore *MovCore, block *types.Block) error {
410         return movCore.ApplyBlock(block)
411 }
412
413 func detachBlock(movCore *MovCore, block *types.Block) error {
414         return movCore.DetachBlock(block)
415 }
416
417 func queryAllOrders(store *database.LevelDBMovStore) []*common.Order {
418         var orders []*common.Order
419         tradePairIterator := database.NewTradePairIterator(store)
420         for tradePairIterator.HasNext() {
421                 orderIterator := database.NewOrderIterator(store, tradePairIterator.Next())
422                 for orderIterator.HasNext() {
423                         orders = append(orders, orderIterator.NextBatch()...)
424                 }
425         }
426         return orders
427 }
428
429 func ordersEquals(orders1 []*common.Order, orders2 []*common.Order) bool {
430         orderMap1 := make(map[string]*common.Order)
431         for _, order := range orders1 {
432                 orderMap1[order.Key()] = order
433         }
434
435         orderMap2 := make(map[string]*common.Order)
436         for _, order := range orders2 {
437                 orderMap2[order.Key()] = order
438         }
439         return testutil.DeepEqual(orderMap1, orderMap2)
440 }
441
442 func hashPtr(hash bc.Hash) *bc.Hash {
443         return &hash
444 }