OSDN Git Service

Mov (#518)
authorPaladz <yzhu101@uottawa.ca>
Mon, 23 Mar 2020 03:02:52 +0000 (11:02 +0800)
committerGitHub <noreply@github.com>
Mon, 23 Mar 2020 03:02:52 +0000 (11:02 +0800)
* magnetic program (#402)

* add dex program

* optimise

* adjust code position

* add DecodeP2DCProgram

* optimise code format

* add contract code annotation

* adjust contract

* optimise

* modify contract name

* optimse

* adjust contract

* optimise

* delete redundant code

* optimse

* optimise

* add contract tx test

* add wrong test and ring contract

* optimise

* optimise

* optimise test

* optimise

* optimise

* modify parameter name (#411)

* fix bug (#412)

* fix bug

* fix

* fix name

* fix func name

* fix

* Mov database iterator (#415)

* mov_database_iterator

* opt log

* match engine (#418)

* match engine

* opt code

* update comment

* opt code

* fix validate trade pairs

* remove magic num

* opt canNotMatched func

* refactor

* fix travis (#425)

* modify crossin transaction (#416)

* modify crossin transaction

* add test

* fix review

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* Modify federation sync (#422)

* Set chain Tx Gas 0 (#409)

* Set chain Tx Gas 0

* Fix test file err

* Revert test file modify

* add filter asset

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix a small bug

* delete unused

* mov core (#421)

* mov core

* bug fix

* opt code

* remove validate contract in validate cancel order

* fix validate

* bug fix

* bug fix

* fix ci

* fix mov database (#427)

* mov joint (#428)

* mov joint

* bug fix

* opt code

* fix ci

* format code

* fix mov (#429)

* add status fail check (#431)

* Mov merge (#430)

* Add MOV subprotol framework support

* opz code format

* opz code format

* Del unused code

* Set chain Tx Gas 0 (#409)

* Set chain Tx Gas 0

* Fix test file err

* Revert test file modify

* Modify interface function

* Opz code format

* MOV add startpoint

* mov merge

* fix ci

* opt code

* fix ci

* opt code

* fix dead lock

* opt code

* bug fix

* fix ci

* revert comment

* fix bug

* remove unuse parameter

* fix validate coinbase

* add calc matchedtx gas func

* opt code

* remove useless code

* opt validate

* block height limit for before proposal block

* merge order from pool (#432)

* merge order from pool

* bug fix order table

* bug fix order table

* bug fix

* rename

* fix order table (#434)

* add mov core test

* add calcMatchedTxFee test

* import order

* fix order table test

* fix match

* opt code

* Check mov store (#437)

* over view code of database/mov_store

* delete the duplicate code

* change the batch read number

* same change while go over the codes (#438)

* same change while go over the codes

* roll back mis edit

* add the comment (#439)

* Modify corssout tx action (#441)

* add program for crossout action

* fix

* fix sync status (#442)

* fix mov dead lock (#443)

* fix mov dead lock

* Delete LOCK

* set proposal have timeout (#444)

* set proposal have timeout

* edit for code review

* fix the roll back dead lock (#446)

* submit tx protocol verify (#447)

* fix request amount zero (#448)

* fix (#449)

* timeout level (#450)

* timeout level

* fix ci

* edit for code review

* edit for code review

* Update testnet config (#451)

* update testnet config

* update testnet param

* rollback federation config

* add op mul fraction to solve the mov exchange issue (#452)

* add op mul fraction to solve the mov exchange issue

* minor

* edit for code review

* no water

* fix mov should pay amount (#453)

* fix mov should pay amount

* opt code

* drop the useless tx (#455)

* drop the useless tx

* fix bug

* try to fix network issue (#456)

* try to fix network issue

* try fix bug

* try fix

* init version for edit sign process (#454)

* init version for edit sign process

* eleagent the code

* elegant the code

* try fix bug (#457)

* fix recursive order (#458)

* fix recursive order

* edit logic

* fix the test

* fix mov infinite loop (#461)

* fix mov infinite loop

* validate equals trade pair

* update

* update

* Fix mov issue (#462)

* fix mov infinite loop

* validate equals trade pair

* cycle match

* fix ci

* opt mov validate match tx (#470)

* opt mov validate match tx

* fix validate trade pair

Co-authored-by: Paladz <yzhu101@uottawa.ca>
* fix_open_federation_issue_asset (#478)

* fix_open_federation_issue_asset

* opt code

* complement mov test (#477)

Co-authored-by: Paladz <yzhu101@uottawa.ca>
* fix decimal (#479)

* fix decimal

* fix decimal

* bug fix

* fix decimal

* opt mov performance (#480)

* opt mov performance

* opt mov performance

* fix ci

* bug fix

* bug fix

* opt code

* remove test

* remove unknow file

* opt code

* opt code

* add comment

* opt code

* bug fix

* opt code

* use int for worker num

* fix match collector (#481)

* fix match collector

* add comment

* opt_mathch_collector (#483)

* Opt mathch collector (#482)

* opt_mathch_collector

* opt_mathch_collector

* final code review (#484)

* final code review

* edit for code review

Co-authored-by: Colt-Z <453256728@qq.com>
* Validate matched tx sequence test (#486)

* validate_matched_tx_sequence_test

* validate_matched_tx_sequence_test

* Validate matched tx sequence test (#487)

* validate_matched_tx_sequence_test

* validate_matched_tx_sequence_test

* Supplementary unit tests

* rename

* fix add order bug (#489)

* fix add order bug

* edit for code review

Co-authored-by: Colt-Z <453256728@qq.com>
* filter txpool by asset whitelis  (#488)

* add AssetWhitelist to FederationConfig

* use []*bc.AssetID for AssetWhitelist

* add (f *FederationAssetFilter) IsDust()

* fix https://github.com/Bytom/vapor/pull/488#discussion_r379226522

* fix https://github.com/Bytom/vapor/pull/488#discussion_r379226868

* fix https://github.com/Bytom/vapor/pull/488/files#r379226149

* fix https://github.com/Bytom/vapor/pull/488/files#r379225830

* convert assetID to lower-case

* golint

* add deleteBlock and then fix some tests (#491)

* add deleteBlock and then fix some tests

* add new test

* delete line

* fix one error

* change test case

* add s to word

* s

* update test cases

* update package and delete one same case

Co-authored-by: Paladz <yzhu101@uottawa.ca>
* fix init mov state (#492)

* fix init mov state

* remove Junk files

* Rollback pr2, rollback 的时候,更新 wallet 的状态, 改内核的下一个版本发 (#493)

* add rollback_func

* add wallet rollback

* update wallet finished

* add new wallet rollback flag

* fix one flag

* new design of new wallet

* update one comment

* rollback status from one wallet best hash start

* change two func name

* fix one test

* change rollback func return info

* remove ugly code

* fix ugly code

* remove ugly code

* re design reorganizeChain (#495)

* Rollback pr3 (#496)

* rollback chain

* fix test ci

* delete irrblock judge

* update rollblock

* delete test case

* fix bad delete

* change rollback

* delete one test

* add tip

* change rollback

* fix one err

* remove fmt

* remove one test

* rename

* rename variable

Co-authored-by: Poseidon <shenao.78@163.com>
* fix_add_order_of_order_book (#497)

* fix_add_order_of_order_book

* fix order book

* opt code

Co-authored-by: Paladz <yzhu101@uottawa.ca>
* fix validate tx (#499)

* add_comment_for_bbft (#502)

* fixed reward address (#504)

* match_fee_strategy (#506)

* match_fee_strategy

* rename variable

* opt code

* rename

* adjust order

* add test case

* validate reward address (#505)

* validate reward address

* fix ci

* opt code

* opt code

* opt code

* Match fee strategy (#507)

* match_fee_strategy

* rename variable

* opt code

* rename

* adjust order

* add test case

* bug fix

* bug fix

* add fee for multiple asset tesetcase

* add comment

* charge 1% fee (#509)

* charge 1% fee

* fix weird space

* edit for code review

Co-authored-by: paladz <453256728@qq.com>
* fix_mov_contract_test (#510)

* one_thousandth_fee (#508)

* one_thousandth_fee

* opt code

* update fee

* bug fix

* fix all testcase

* opt mov (#511)

* ban status fail for flash swap (#512)

* ban status fail for flash swap

* set up init check point

Co-authored-by: paladz <453256728@qq.com>
* no tricks (#513)

Co-authored-by: paladz <453256728@qq.com>
* for publish (#515)

* for publish

* fix test

Co-authored-by: paladz <453256728@qq.com>
* small fix (#517)

* small fix

* prevent timeout

* edit for golint

Co-authored-by: paladz <453256728@qq.com>
* Opt is matched (#516)

* opt is matched

* opt is matched

Co-authored-by: Paladz <yzhu101@uottawa.ca>
* rollback (#503)

* rollback

* add

* rollback test

* rollback xiugai

* delete one line

* s

* rename chainData

* reformat it

* opt code

Co-authored-by: shenao78 <shenao.78@163.com>
Co-authored-by: Paladz <yzhu101@uottawa.ca>
* last review (#519)

* last review

* edit for code review

* fix test case

Co-authored-by: paladz <453256728@qq.com>
Co-authored-by: oysheng <33340252+oysheng@users.noreply.github.com>
Co-authored-by: wz <mars@bytom.io>
Co-authored-by: Poseidon <shenao.78@163.com>
Co-authored-by: Chengcheng Zhang <943420582@qq.com>
Co-authored-by: Colt-Z <453256728@qq.com>
Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: ipqhjjybj <250657661@qq.com>
93 files changed:
.travis.yml
application/mov/common/type.go
application/mov/common/type_test.go [new file with mode: 0644]
application/mov/common/util.go [new file with mode: 0644]
application/mov/contract/contract.go [new file with mode: 0644]
application/mov/database/mov_iterator.go [new file with mode: 0644]
application/mov/database/mov_iterator_test.go [new file with mode: 0644]
application/mov/database/mov_store.go
application/mov/database/mov_store_test.go
application/mov/match/engine.go [new file with mode: 0644]
application/mov/match/engine_test.go [new file with mode: 0644]
application/mov/match/fee_strategy.go [new file with mode: 0644]
application/mov/match/order_book.go [new file with mode: 0644]
application/mov/match/order_book_test.go [new file with mode: 0644]
application/mov/match_collector.go [new file with mode: 0644]
application/mov/mock/mock.go [new file with mode: 0644]
application/mov/mock/mock_mov_store.go [new file with mode: 0644]
application/mov/mov_core.go [new file with mode: 0644]
application/mov/mov_core_test.go [new file with mode: 0644]
blockchain/txbuilder/actions.go
blockchain/txbuilder/signing_instruction.go
cmd/vapord/commands/rollback_node.go [new file with mode: 0644]
cmd/vapord/commands/root.go
cmd/vapord/commands/run_node.go
common/bytes.go
common/crossin_asset.go [new file with mode: 0644]
common/sort.go [deleted file]
config/config.go
config/federation_test.go
config/toml.go
consensus/general.go
consensus/segwit/segwit.go
database/account_store.go
database/store.go
database/store_test.go
database/utxo_view.go
database/wallet_store.go
docs/federation/sql_dump/federation_shema.sql
math/algorithm.go [new file with mode: 0644]
netsync/chainmgr/block_keeper.go
netsync/chainmgr/block_keeper_test.go
netsync/chainmgr/block_process.go
netsync/chainmgr/fast_sync.go
netsync/chainmgr/handle.go
netsync/chainmgr/msg_fetcher.go
netsync/chainmgr/storage.go
netsync/chainmgr/tx_keeper_test.go
node/node.go
proposal/blockproposer/blockproposer.go
proposal/proposal.go
proposal/proposal_test.go
protocol/asset_filter.go [new file with mode: 0644]
protocol/bbft.go
protocol/bc/bc.pb.go
protocol/bc/bc.proto
protocol/bc/crosschain_input.go
protocol/bc/entry_test.go
protocol/bc/types/block.go
protocol/bc/types/block_witness.go
protocol/bc/types/crosschain_output.go
protocol/bc/types/intrachain_output.go
protocol/bc/types/map.go
protocol/bc/types/vote_output.go
protocol/block.go
protocol/block_test.go
protocol/consensus_node_manager_test.go
protocol/protocol.go
protocol/store.go
protocol/tx.go
protocol/txpool.go
protocol/txpool_test.go
protocol/validation/tx.go
protocol/validation/tx_test.go
protocol/validation/vmcontext.go
protocol/vm/numeric.go
protocol/vm/numeric_test.go
protocol/vm/ops.go
protocol/vm/vmutil/script.go
test/accounts_test.go
test/bench_blockchain_test.go
test/mock/mempool.go
test/performance/mining_test.go
test/rollback_test.go [new file with mode: 0644]
test/util.go
test/wallet_test.go
test/wallet_test_util.go
toolbar/federation/api/handler.go
toolbar/federation/database/orm/asset.go
toolbar/federation/synchron/mainchain_keeper.go
toolbar/federation/synchron/sidechain_keeper.go
toolbar/precognitive/config/config.go
version/version.go
wallet/wallet.go

index f32dc51..436a5c6 100644 (file)
@@ -11,7 +11,7 @@ branches:
     only:
         - master
         - dev
-        - v0.1
+        - mov
 
 script:
     - make ci
index d56dac0..11d89bb 100644 (file)
@@ -1,7 +1,17 @@
 package common
 
-import "github.com/bytom/vapor/protocol/bc"
+import (
+       "encoding/hex"
+       "fmt"
+       "math/big"
 
+       "github.com/bytom/vapor/consensus/segwit"
+       "github.com/bytom/vapor/errors"
+       "github.com/bytom/vapor/protocol/bc"
+       "github.com/bytom/vapor/protocol/bc/types"
+)
+
+// MovUtxo store the utxo information for mov order
 type MovUtxo struct {
        SourceID       *bc.Hash
        SourcePos      uint64
@@ -9,19 +19,150 @@ type MovUtxo struct {
        ControlProgram []byte
 }
 
+// Order store all the order information
 type Order struct {
-       FromAssetID *bc.AssetID
-       ToAssetID   *bc.AssetID
-       Utxo        *MovUtxo
-       Rate        float64
+       FromAssetID      *bc.AssetID
+       ToAssetID        *bc.AssetID
+       Utxo             *MovUtxo
+       RatioNumerator   int64
+       RatioDenominator int64
+}
+
+// Rate return the exchange represented by float64
+func (o *Order) Rate() float64 {
+       if o.RatioDenominator == 0 {
+               return 0
+       }
+       rate := big.NewRat(o.RatioNumerator, o.RatioDenominator)
+       result, _ := rate.Float64()
+       return result
+}
+
+// cmpRate compares rate of x and y and returns -1 if x <  y, 0 if x == y, +1 if x >  y
+func (o *Order) cmpRate(other *Order) int {
+       rate := big.NewRat(o.RatioNumerator, o.RatioDenominator)
+       otherRate := big.NewRat(other.RatioNumerator, other.RatioDenominator)
+       return rate.Cmp(otherRate)
+}
+
+// Cmp first compare the rate, if rate is equals, then compare the utxo hash
+func (o *Order) Cmp(other *Order) int {
+       cmp := o.cmpRate(other)
+       if cmp == 0 {
+               if hex.EncodeToString(o.UTXOHash().Bytes()) < hex.EncodeToString(other.UTXOHash().Bytes()) {
+                       return -1
+               }
+               return 1
+       }
+       return cmp
+}
+
+// OrderSlice is define for order's sort
+type OrderSlice []*Order
+
+func (o OrderSlice) Len() int      { return len(o) }
+func (o OrderSlice) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
+func (o OrderSlice) Less(i, j int) bool {
+       return o[i].Cmp(o[j]) < 0
+}
+
+// NewOrderFromOutput convert txinput to order
+func NewOrderFromOutput(tx *types.Tx, outputIndex int) (*Order, error) {
+       outputID := tx.OutputID(outputIndex)
+       output, err := tx.IntraChainOutput(*outputID)
+       if err != nil {
+               return nil, err
+       }
+
+       contractArgs, err := segwit.DecodeP2WMCProgram(output.ControlProgram.Code)
+       if err != nil {
+               return nil, err
+       }
+
+       assetAmount := output.Source.Value
+       return &Order{
+               FromAssetID:      assetAmount.AssetId,
+               ToAssetID:        &contractArgs.RequestedAsset,
+               RatioNumerator:   contractArgs.RatioNumerator,
+               RatioDenominator: contractArgs.RatioDenominator,
+               Utxo: &MovUtxo{
+                       SourceID:       output.Source.Ref,
+                       Amount:         assetAmount.Amount,
+                       SourcePos:      uint64(outputIndex),
+                       ControlProgram: output.ControlProgram.Code,
+               },
+       }, nil
+}
+
+// NewOrderFromInput convert txoutput to order
+func NewOrderFromInput(tx *types.Tx, inputIndex int) (*Order, error) {
+       input, ok := tx.Inputs[inputIndex].TypedInput.(*types.SpendInput)
+       if !ok {
+               return nil, errors.New("input is not type of spend input")
+       }
+
+       contractArgs, err := segwit.DecodeP2WMCProgram(input.ControlProgram)
+       if err != nil {
+               return nil, err
+       }
+
+       return &Order{
+               FromAssetID:      input.AssetId,
+               ToAssetID:        &contractArgs.RequestedAsset,
+               RatioNumerator:   contractArgs.RatioNumerator,
+               RatioDenominator: contractArgs.RatioDenominator,
+               Utxo: &MovUtxo{
+                       SourceID:       &input.SourceID,
+                       Amount:         input.Amount,
+                       SourcePos:      input.SourcePosition,
+                       ControlProgram: input.ControlProgram,
+               },
+       }, nil
+}
+
+// Key return the unique key for representing this order
+func (o *Order) Key() string {
+       return fmt.Sprintf("%s:%d", o.Utxo.SourceID, o.Utxo.SourcePos)
 }
 
+// TradePair return the trade pair info
+func (o *Order) TradePair() *TradePair {
+       return &TradePair{FromAssetID: o.FromAssetID, ToAssetID: o.ToAssetID}
+}
+
+// UTXOHash calculate the utxo hash of this order
+func (o *Order) UTXOHash() *bc.Hash {
+       prog := &bc.Program{VmVersion: 1, Code: o.Utxo.ControlProgram}
+       src := &bc.ValueSource{
+               Ref:      o.Utxo.SourceID,
+               Value:    &bc.AssetAmount{AssetId: o.FromAssetID, Amount: o.Utxo.Amount},
+               Position: o.Utxo.SourcePos,
+       }
+       hash := bc.EntryID(bc.NewIntraChainOutput(src, prog, 0))
+       return &hash
+}
+
+// TradePair is the object for record trade pair info
 type TradePair struct {
        FromAssetID *bc.AssetID
        ToAssetID   *bc.AssetID
        Count       int
 }
 
+// Key return the unique key for representing this trade pair
+func (t *TradePair) Key() string {
+       return fmt.Sprintf("%s:%s", t.FromAssetID, t.ToAssetID)
+}
+
+// Reverse return the reverse trade pair object
+func (t *TradePair) Reverse() *TradePair {
+       return &TradePair{
+               FromAssetID: t.ToAssetID,
+               ToAssetID:   t.FromAssetID,
+       }
+}
+
+// MovDatabaseState is object to record DB image status
 type MovDatabaseState struct {
        Height uint64
        Hash   *bc.Hash
diff --git a/application/mov/common/type_test.go b/application/mov/common/type_test.go
new file mode 100644 (file)
index 0000000..8fe9e81
--- /dev/null
@@ -0,0 +1,27 @@
+package common
+
+import (
+       "testing"
+
+       "github.com/bytom/vapor/consensus"
+       "github.com/bytom/vapor/testutil"
+)
+
+func TestCalcUTXOHash(t *testing.T) {
+       wantHash := "d94acbac0304e054569b0a2c2ab546be293552eb83d2d84af7234a013986a906"
+       controlProgram := testutil.MustDecodeHexString("0014d6f0330717170c838e6ac4c643de61e4c035e9b7")
+       sourceID := testutil.MustDecodeHash("3cada915465af2f08c93911bce7a100498fddb5738e5400269c4d5c2b2f5b261")
+       order := Order{
+               FromAssetID: consensus.BTMAssetID,
+               Utxo: &MovUtxo{
+                       SourceID:       &sourceID,
+                       SourcePos:      1,
+                       Amount:         399551000,
+                       ControlProgram: controlProgram,
+               },
+       }
+
+       if hash := order.UTXOHash(); hash.String() != wantHash {
+               t.Fatal("The function is incorrect")
+       }
+}
diff --git a/application/mov/common/util.go b/application/mov/common/util.go
new file mode 100644 (file)
index 0000000..0077eab
--- /dev/null
@@ -0,0 +1,30 @@
+package common
+
+import (
+       "github.com/bytom/vapor/application/mov/contract"
+       "github.com/bytom/vapor/consensus/segwit"
+       "github.com/bytom/vapor/protocol/bc/types"
+)
+
+// IsMatchedTx check if this transaction has trade mov order input
+func IsMatchedTx(tx *types.Tx) bool {
+       if len(tx.Inputs) < 2 {
+               return false
+       }
+       for _, input := range tx.Inputs {
+               if input.InputType() == types.SpendInputType && segwit.IsP2WMCScript(input.ControlProgram()) && contract.IsTradeClauseSelector(input) {
+                       return true
+               }
+       }
+       return false
+}
+
+// IsCancelOrderTx check if this transaction has cancel mov order input
+func IsCancelOrderTx(tx *types.Tx) bool {
+       for _, input := range tx.Inputs {
+               if input.InputType() == types.SpendInputType && segwit.IsP2WMCScript(input.ControlProgram()) && contract.IsCancelClauseSelector(input) {
+                       return true
+               }
+       }
+       return false
+}
diff --git a/application/mov/contract/contract.go b/application/mov/contract/contract.go
new file mode 100644 (file)
index 0000000..75cd00d
--- /dev/null
@@ -0,0 +1,41 @@
+package contract
+
+import (
+       "encoding/hex"
+
+       "github.com/bytom/vapor/protocol/bc/types"
+       "github.com/bytom/vapor/protocol/vm"
+)
+
+const (
+       sizeOfCancelClauseArgs       = 3
+       sizeOfPartialTradeClauseArgs = 3
+       sizeOfFullTradeClauseArgs    = 2
+)
+
+// smart contract clause select for differnet unlock method
+const (
+       PartialTradeClauseSelector int64 = iota
+       FullTradeClauseSelector
+       CancelClauseSelector
+)
+
+// IsCancelClauseSelector check if input select cancel clause
+func IsCancelClauseSelector(input *types.TxInput) bool {
+       return len(input.Arguments()) == sizeOfCancelClauseArgs && hex.EncodeToString(input.Arguments()[len(input.Arguments())-1]) == hex.EncodeToString(vm.Int64Bytes(CancelClauseSelector))
+}
+
+// IsTradeClauseSelector check if input select is partial trade clause or full trade clause
+func IsTradeClauseSelector(input *types.TxInput) bool {
+       return IsPartialTradeClauseSelector(input) || IsFullTradeClauseSelector(input)
+}
+
+// IsPartialTradeClauseSelector check if input select partial trade clause
+func IsPartialTradeClauseSelector(input *types.TxInput) bool {
+       return len(input.Arguments()) == sizeOfPartialTradeClauseArgs && hex.EncodeToString(input.Arguments()[len(input.Arguments())-1]) == hex.EncodeToString(vm.Int64Bytes(PartialTradeClauseSelector))
+}
+
+// IsFullTradeClauseSelector check if input select full trade clause
+func IsFullTradeClauseSelector(input *types.TxInput) bool {
+       return len(input.Arguments()) == sizeOfFullTradeClauseArgs && hex.EncodeToString(input.Arguments()[len(input.Arguments())-1]) == hex.EncodeToString(vm.Int64Bytes(FullTradeClauseSelector))
+}
diff --git a/application/mov/database/mov_iterator.go b/application/mov/database/mov_iterator.go
new file mode 100644 (file)
index 0000000..b06debf
--- /dev/null
@@ -0,0 +1,104 @@
+package database
+
+import (
+       log "github.com/sirupsen/logrus"
+
+       "github.com/bytom/vapor/application/mov/common"
+       "github.com/bytom/vapor/protocol/bc"
+)
+
+// TradePairIterator wrap read trade pair from DB action
+type TradePairIterator struct {
+       movStore       MovStore
+       tradePairs     []*common.TradePair
+       tradePairIndex int
+}
+
+// NewTradePairIterator create the new TradePairIterator object
+func NewTradePairIterator(movStore MovStore) *TradePairIterator {
+       return &TradePairIterator{movStore: movStore}
+}
+
+// HasNext check if there are more trade pairs in memory or DB
+func (t *TradePairIterator) HasNext() bool {
+       tradePairSize := len(t.tradePairs)
+       if t.tradePairIndex < tradePairSize {
+               return true
+       }
+
+       var fromAssetID, toAssetID *bc.AssetID
+       if len(t.tradePairs) > 0 {
+               lastTradePair := t.tradePairs[tradePairSize-1]
+               fromAssetID, toAssetID = lastTradePair.FromAssetID, lastTradePair.ToAssetID
+       }
+
+       tradePairs, err := t.movStore.ListTradePairsWithStart(fromAssetID, toAssetID)
+       if err != nil {
+               // If the error is returned, it's an error of program itself,
+               // and cannot be recovered, so panic directly.
+               log.WithField("err", err).Fatal("fail to list trade pairs")
+       }
+
+       if len(tradePairs) == 0 {
+               return false
+       }
+
+       t.tradePairs = tradePairs
+       t.tradePairIndex = 0
+       return true
+}
+
+// Next return the next available trade pair in memory or DB
+func (t *TradePairIterator) Next() *common.TradePair {
+       if !t.HasNext() {
+               return nil
+       }
+
+       tradePair := t.tradePairs[t.tradePairIndex]
+       t.tradePairIndex++
+       return tradePair
+}
+
+// OrderIterator wrap read order from DB action
+type OrderIterator struct {
+       movStore  MovStore
+       lastOrder *common.Order
+       orders    []*common.Order
+}
+
+// NewOrderIterator create the new OrderIterator object
+func NewOrderIterator(movStore MovStore, tradePair *common.TradePair) *OrderIterator {
+       return &OrderIterator{
+               movStore:  movStore,
+               lastOrder: &common.Order{FromAssetID: tradePair.FromAssetID, ToAssetID: tradePair.ToAssetID},
+       }
+}
+
+// HasNext check if there are more orders in memory or DB
+func (o *OrderIterator) HasNext() bool {
+       if len(o.orders) == 0 {
+               orders, err := o.movStore.ListOrders(o.lastOrder)
+               if err != nil {
+                       log.WithField("err", err).Fatal("fail to list orders")
+               }
+
+               if len(orders) == 0 {
+                       return false
+               }
+
+               o.orders = orders
+               o.lastOrder = o.orders[len(o.orders)-1]
+       }
+       return true
+}
+
+// NextBatch return the next batch of orders in memory or DB
+func (o *OrderIterator) NextBatch() []*common.Order {
+       if !o.HasNext() {
+               return nil
+       }
+
+       orders := o.orders
+       o.orders = nil
+       return orders
+}
diff --git a/application/mov/database/mov_iterator_test.go b/application/mov/database/mov_iterator_test.go
new file mode 100644 (file)
index 0000000..5df84e1
--- /dev/null
@@ -0,0 +1,166 @@
+package database
+
+import (
+       "testing"
+
+       "github.com/bytom/vapor/application/mov/common"
+       "github.com/bytom/vapor/application/mov/mock"
+       "github.com/bytom/vapor/protocol/bc"
+       "github.com/bytom/vapor/testutil"
+)
+
+var (
+       asset1 = bc.NewAssetID([32]byte{1})
+       asset2 = bc.NewAssetID([32]byte{2})
+       asset3 = bc.NewAssetID([32]byte{3})
+       asset4 = bc.NewAssetID([32]byte{4})
+
+       order1 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 1, RatioDenominator: 10}
+       order2 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 2, RatioDenominator: 10}
+       order3 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 3, RatioDenominator: 10}
+       order4 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 4, RatioDenominator: 10}
+       order5 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 5, RatioDenominator: 10}
+)
+
+func TestTradePairIterator(t *testing.T) {
+       cases := []struct {
+               desc            string
+               storeTradePairs []*common.TradePair
+               wantTradePairs  []*common.TradePair
+       }{
+               {
+                       desc: "normal case",
+                       storeTradePairs: []*common.TradePair{
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset2,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset3,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset4,
+                               },
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset2,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset3,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset4,
+                               },
+                       },
+               },
+               {
+                       desc: "num of trade pairs more than one return",
+                       storeTradePairs: []*common.TradePair{
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset2,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset3,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset4,
+                               },
+                               {
+                                       FromAssetID: &asset2,
+                                       ToAssetID:   &asset1,
+                               },
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset2,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset3,
+                               },
+                               {
+                                       FromAssetID: &asset1,
+                                       ToAssetID:   &asset4,
+                               },
+                               {
+                                       FromAssetID: &asset2,
+                                       ToAssetID:   &asset1,
+                               },
+                       },
+               },
+               {
+                       desc:            "store is empty",
+                       storeTradePairs: []*common.TradePair{},
+                       wantTradePairs:  []*common.TradePair{},
+               },
+       }
+
+       for i, c := range cases {
+               store := mock.NewMovStore(c.storeTradePairs, nil)
+               var gotTradePairs []*common.TradePair
+               iterator := NewTradePairIterator(store)
+               for iterator.HasNext() {
+                       gotTradePairs = append(gotTradePairs, iterator.Next())
+               }
+               if !testutil.DeepEqual(c.wantTradePairs, gotTradePairs) {
+                       t.Errorf("#%d(%s):got trade pairs is not equals want trade pairs", i, c.desc)
+               }
+       }
+}
+
+func TestOrderIterator(t *testing.T) {
+       cases := []struct {
+               desc        string
+               tradePair   *common.TradePair
+               storeOrders []*common.Order
+               wantOrders  []*common.Order
+       }{
+               {
+                       desc:        "normal case",
+                       tradePair:   &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2},
+                       storeOrders: []*common.Order{order1, order2, order3},
+                       wantOrders:  []*common.Order{order1, order2, order3},
+               },
+               {
+                       desc:        "num of orders more than one return",
+                       tradePair:   &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2},
+                       storeOrders: []*common.Order{order1, order2, order3, order4, order5},
+                       wantOrders:  []*common.Order{order1, order2, order3, order4, order5},
+               },
+               {
+                       desc:        "only one order",
+                       tradePair:   &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2},
+                       storeOrders: []*common.Order{order1},
+                       wantOrders:  []*common.Order{order1},
+               },
+               {
+                       desc:        "store is empty",
+                       tradePair:   &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2},
+                       storeOrders: []*common.Order{},
+                       wantOrders:  []*common.Order{},
+               },
+       }
+
+       for i, c := range cases {
+               store := mock.NewMovStore(nil, c.storeOrders)
+
+               var gotOrders []*common.Order
+               iterator := NewOrderIterator(store, c.tradePair)
+               for iterator.HasNext() {
+                       gotOrders = append(gotOrders, iterator.NextBatch()...)
+               }
+               if !testutil.DeepEqual(c.wantOrders, gotOrders) {
+                       t.Errorf("#%d(%s):got orders it not equals want orders", i, c.desc)
+               }
+       }
+}
index 252886a..20d3101 100644 (file)
@@ -12,15 +12,27 @@ import (
        "github.com/bytom/vapor/protocol/bc/types"
 )
 
+// MovStore is the interface for mov's persistent storage
+type MovStore interface {
+       GetMovDatabaseState() (*common.MovDatabaseState, error)
+       InitDBState(height uint64, hash *bc.Hash) error
+       ListOrders(orderAfter *common.Order) ([]*common.Order, error)
+       ListTradePairsWithStart(fromAssetIDAfter, toAssetIDAfter *bc.AssetID) ([]*common.TradePair, error)
+       ProcessOrders(addOrders []*common.Order, delOrders []*common.Order, blockHeader *types.BlockHeader) error
+}
+
 const (
-       order byte = iota
+       order byte = iota + 1
        tradePair
        matchStatus
 
-       tradePairsNum = 1024
-       ordersNum     = 10240
-       assetIDLen    = 32
-       rateByteLen   = 8
+       fromAssetIDPos = 0
+       toAssetIDPos   = 1
+       assetIDLen     = 32
+       rateByteLen    = 8
+
+       tradePairsNum = 32
+       ordersNum     = 128
 )
 
 var (
@@ -30,6 +42,12 @@ var (
        bestMatchStore   = append(movStore, matchStatus)
 )
 
+type orderData struct {
+       Utxo             *common.MovUtxo
+       RatioNumerator   int64
+       RatioDenominator int64
+}
+
 func calcOrderKey(fromAssetID, toAssetID *bc.AssetID, utxoHash *bc.Hash, rate float64) []byte {
        buf := make([]byte, 8)
        binary.BigEndian.PutUint64(buf, math.Float64bits(rate))
@@ -44,27 +62,16 @@ func calcTradePairKey(fromAssetID, toAssetID *bc.AssetID) []byte {
        return append(key, toAssetID.Bytes()...)
 }
 
-func calcUTXOHash(order *common.Order) *bc.Hash {
-       prog := &bc.Program{VmVersion: 1, Code: order.Utxo.ControlProgram}
-       src := &bc.ValueSource{
-               Ref:      order.Utxo.SourceID,
-               Value:    &bc.AssetAmount{AssetId: order.FromAssetID, Amount: order.Utxo.Amount},
-               Position: order.Utxo.SourcePos,
-       }
-       hash := bc.EntryID(bc.NewIntraChainOutput(src, prog, 0))
-       return &hash
-}
-
-func getAssetIDFromTradePairKey(key []byte, prefix []byte, posIndex int) *bc.AssetID {
+func getAssetIDFromTradePairKey(key []byte, posIndex int) *bc.AssetID {
        b := [32]byte{}
-       pos := len(prefix) + assetIDLen*posIndex
+       pos := len(tradePairsPrefix) + assetIDLen*posIndex
        copy(b[:], key[pos:pos+assetIDLen])
        assetID := bc.NewAssetID(b)
        return &assetID
 }
 
-func getRateFromOrderKey(key []byte, prefix []byte) float64 {
-       ratePos := len(prefix) + assetIDLen*2
+func getRateFromOrderKey(key []byte) float64 {
+       ratePos := len(ordersPrefix) + assetIDLen*2
        return math.Float64frombits(binary.BigEndian.Uint64(key[ratePos : ratePos+rateByteLen]))
 }
 
@@ -72,24 +79,40 @@ type tradePairData struct {
        Count int
 }
 
-type MovStore struct {
+// LevelDBMovStore is the LevelDB implementation for MovStore
+type LevelDBMovStore struct {
        db dbm.DB
 }
 
-func NewMovStore(db dbm.DB, height uint64, hash *bc.Hash) (*MovStore, error) {
-       if value := db.Get(bestMatchStore); value == nil {
-               state := &common.MovDatabaseState{Height: height, Hash: hash}
-               value, err := json.Marshal(state)
-               if err != nil {
-                       return nil, err
-               }
+// NewLevelDBMovStore create a new LevelDBMovStore object
+func NewLevelDBMovStore(db dbm.DB) *LevelDBMovStore {
+       return &LevelDBMovStore{db: db}
+}
+
+// GetMovDatabaseState return the current DB's image status
+func (m *LevelDBMovStore) GetMovDatabaseState() (*common.MovDatabaseState, error) {
+       if value := m.db.Get(bestMatchStore); value != nil {
+               state := &common.MovDatabaseState{}
+               return state, json.Unmarshal(value, state)
+       }
+
+       return nil, errors.New("don't find state of mov-database")
+}
 
-               db.Set(bestMatchStore, value)
+// InitDBState set the DB's image status
+func (m *LevelDBMovStore) InitDBState(height uint64, hash *bc.Hash) error {
+       state := &common.MovDatabaseState{Height: height, Hash: hash}
+       value, err := json.Marshal(state)
+       if err != nil {
+               return err
        }
-       return &MovStore{db: db}, nil
+
+       m.db.Set(bestMatchStore, value)
+       return nil
 }
 
-func (m *MovStore) ListOrders(orderAfter *common.Order) ([]*common.Order, error) {
+// ListOrders return n orders after the input order
+func (m *LevelDBMovStore) ListOrders(orderAfter *common.Order) ([]*common.Order, error) {
        if orderAfter.FromAssetID == nil || orderAfter.ToAssetID == nil {
                return nil, errors.New("assetID is nil")
        }
@@ -98,8 +121,8 @@ func (m *MovStore) ListOrders(orderAfter *common.Order) ([]*common.Order, error)
        orderPrefix = append(orderPrefix, orderAfter.ToAssetID.Bytes()...)
 
        var startKey []byte
-       if orderAfter.Rate > 0 {
-               startKey = calcOrderKey(orderAfter.FromAssetID, orderAfter.ToAssetID, calcUTXOHash(orderAfter), orderAfter.Rate)
+       if orderAfter.Rate() > 0 {
+               startKey = calcOrderKey(orderAfter.FromAssetID, orderAfter.ToAssetID, orderAfter.UTXOHash(), orderAfter.Rate())
        }
 
        itr := m.db.IteratorPrefixWithStart(orderPrefix, startKey, false)
@@ -107,41 +130,71 @@ func (m *MovStore) ListOrders(orderAfter *common.Order) ([]*common.Order, error)
 
        var orders []*common.Order
        for txNum := 0; txNum < ordersNum && itr.Next(); txNum++ {
-               movUtxo := &common.MovUtxo{}
-               if err := json.Unmarshal(itr.Value(), movUtxo); err != nil {
+               orderData := &orderData{}
+               if err := json.Unmarshal(itr.Value(), orderData); err != nil {
                        return nil, err
                }
 
-               order := &common.Order{
-                       FromAssetID: orderAfter.FromAssetID,
-                       ToAssetID:   orderAfter.ToAssetID,
-                       Rate:        getRateFromOrderKey(itr.Key(), ordersPrefix),
-                       Utxo:        movUtxo,
-               }
-               orders = append(orders, order)
+               orders = append(orders, &common.Order{
+                       FromAssetID:      orderAfter.FromAssetID,
+                       ToAssetID:        orderAfter.ToAssetID,
+                       Utxo:             orderData.Utxo,
+                       RatioNumerator:   orderData.RatioNumerator,
+                       RatioDenominator: orderData.RatioDenominator,
+               })
        }
        return orders, nil
 }
 
-func (m *MovStore) ProcessOrders(addOrders []*common.Order, delOreders []*common.Order, blockHeader *types.BlockHeader) error {
+// ListTradePairsWithStart return n trade pairs after the input trade pair
+func (m *LevelDBMovStore) ListTradePairsWithStart(fromAssetIDAfter, toAssetIDAfter *bc.AssetID) ([]*common.TradePair, error) {
+       var startKey []byte
+       if fromAssetIDAfter != nil && toAssetIDAfter != nil {
+               startKey = calcTradePairKey(fromAssetIDAfter, toAssetIDAfter)
+       }
+
+       itr := m.db.IteratorPrefixWithStart(tradePairsPrefix, startKey, false)
+       defer itr.Release()
+
+       var tradePairs []*common.TradePair
+       for txNum := 0; txNum < tradePairsNum && itr.Next(); txNum++ {
+               key := itr.Key()
+               fromAssetID := getAssetIDFromTradePairKey(key, fromAssetIDPos)
+               toAssetID := getAssetIDFromTradePairKey(key, toAssetIDPos)
+
+               tradePairData := &tradePairData{}
+               if err := json.Unmarshal(itr.Value(), tradePairData); err != nil {
+                       return nil, err
+               }
+
+               tradePairs = append(tradePairs, &common.TradePair{FromAssetID: fromAssetID, ToAssetID: toAssetID, Count: tradePairData.Count})
+       }
+       return tradePairs, nil
+}
+
+// ProcessOrders update the DB's image by add new orders, delete the used order
+func (m *LevelDBMovStore) ProcessOrders(addOrders []*common.Order, delOrders []*common.Order, blockHeader *types.BlockHeader) error {
        if err := m.checkMovDatabaseState(blockHeader); err != nil {
                return err
        }
 
        batch := m.db.NewBatch()
-       tradePairsCnt := make(map[common.TradePair]int)
+       tradePairsCnt := make(map[string]*common.TradePair)
        if err := m.addOrders(batch, addOrders, tradePairsCnt); err != nil {
                return err
        }
 
-       m.deleteOrders(batch, delOreders, tradePairsCnt)
-
+       m.deleteOrders(batch, delOrders, tradePairsCnt)
        if err := m.updateTradePairs(batch, tradePairsCnt); err != nil {
                return err
        }
 
-       hash := blockHeader.Hash()
-       if err := m.saveMovDatabaseState(batch, &common.MovDatabaseState{Height: blockHeader.Height, Hash: &hash}); err != nil {
+       state, err := m.calcNextDatabaseState(blockHeader)
+       if err != nil {
+               return err
+       }
+
+       if err := m.saveMovDatabaseState(batch, state); err != nil {
                return err
        }
 
@@ -149,85 +202,103 @@ func (m *MovStore) ProcessOrders(addOrders []*common.Order, delOreders []*common
        return nil
 }
 
-func (m *MovStore) addOrders(batch dbm.Batch, orders []*common.Order, tradePairsCnt map[common.TradePair]int) error {
+func (m *LevelDBMovStore) addOrders(batch dbm.Batch, orders []*common.Order, tradePairsCnt map[string]*common.TradePair) error {
        for _, order := range orders {
-               data, err := json.Marshal(order.Utxo)
+               orderData := &orderData{
+                       Utxo:             order.Utxo,
+                       RatioNumerator:   order.RatioNumerator,
+                       RatioDenominator: order.RatioDenominator,
+               }
+               data, err := json.Marshal(orderData)
                if err != nil {
                        return err
                }
 
-               key := calcOrderKey(order.FromAssetID, order.ToAssetID, calcUTXOHash(order), order.Rate)
+               key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate())
                batch.Set(key, data)
 
-               tradePair := common.TradePair{
+               tradePair := &common.TradePair{
                        FromAssetID: order.FromAssetID,
                        ToAssetID:   order.ToAssetID,
                }
-               tradePairsCnt[tradePair] += 1
+               if _, ok := tradePairsCnt[tradePair.Key()]; !ok {
+                       tradePairsCnt[tradePair.Key()] = tradePair
+               }
+               tradePairsCnt[tradePair.Key()].Count++
        }
        return nil
 }
 
-func (m *MovStore) deleteOrders(batch dbm.Batch, orders []*common.Order, tradePairsCnt map[common.TradePair]int) {
-       for _, order := range orders {
-               key := calcOrderKey(order.FromAssetID, order.ToAssetID, calcUTXOHash(order), order.Rate)
-               batch.Delete(key)
+func (m *LevelDBMovStore) calcNextDatabaseState(blockHeader *types.BlockHeader) (*common.MovDatabaseState, error) {
+       hash := blockHeader.Hash()
+       height := blockHeader.Height
 
-               tradePair := common.TradePair{
-                       FromAssetID: order.FromAssetID,
-                       ToAssetID:   order.ToAssetID,
-               }
-               tradePairsCnt[tradePair] -= 1
+       state, err := m.GetMovDatabaseState()
+       if err != nil {
+               return nil, err
        }
-}
 
-func (m *MovStore) GetMovDatabaseState() (*common.MovDatabaseState, error) {
-       if value := m.db.Get(bestMatchStore); value != nil {
-               state := &common.MovDatabaseState{}
-               return state, json.Unmarshal(value, state)
+       if *state.Hash == hash {
+               hash = blockHeader.PreviousBlockHash
+               height = blockHeader.Height - 1
        }
 
-       return nil, errors.New("don't find state of mov-database")
+       return &common.MovDatabaseState{Height: height, Hash: &hash}, nil
 }
 
-func (m *MovStore) ListTradePairsWithStart(fromAssetIDAfter, toAssetIDAfter *bc.AssetID) ([]*common.TradePair, error) {
-       var startKey []byte
-       if fromAssetIDAfter != nil && toAssetIDAfter != nil {
-               startKey = calcTradePairKey(fromAssetIDAfter, toAssetIDAfter)
+func (m *LevelDBMovStore) checkMovDatabaseState(header *types.BlockHeader) error {
+       state, err := m.GetMovDatabaseState()
+       if err != nil {
+               return err
        }
 
-       itr := m.db.IteratorPrefixWithStart(tradePairsPrefix, startKey, false)
-       defer itr.Release()
+       if (*state.Hash == header.PreviousBlockHash && (state.Height+1) == header.Height) || *state.Hash == header.Hash() {
+               return nil
+       }
 
-       var tradePairs []*common.TradePair
-       for txNum := 0; txNum < tradePairsNum && itr.Next(); txNum++ {
-               key := itr.Key()
-               fromAssetID := getAssetIDFromTradePairKey(key, tradePairsPrefix, 0)
-               toAssetID := getAssetIDFromTradePairKey(key, tradePairsPrefix, 1)
+       return errors.New("the status of the block is inconsistent with that of mov-database")
+}
 
-               tradePairData := &tradePairData{}
-               if err := json.Unmarshal(itr.Value(), tradePairData); err != nil {
-                       return nil, err
+func (m *LevelDBMovStore) deleteOrders(batch dbm.Batch, orders []*common.Order, tradePairsCnt map[string]*common.TradePair) {
+       for _, order := range orders {
+               key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate())
+               batch.Delete(key)
+
+               tradePair := &common.TradePair{
+                       FromAssetID: order.FromAssetID,
+                       ToAssetID:   order.ToAssetID,
+               }
+               if _, ok := tradePairsCnt[tradePair.Key()]; !ok {
+                       tradePairsCnt[tradePair.Key()] = tradePair
                }
+               tradePairsCnt[tradePair.Key()].Count--
+       }
+}
 
-               tradePairs = append(tradePairs, &common.TradePair{FromAssetID: fromAssetID, ToAssetID: toAssetID, Count: tradePairData.Count})
+func (m *LevelDBMovStore) saveMovDatabaseState(batch dbm.Batch, state *common.MovDatabaseState) error {
+       value, err := json.Marshal(state)
+       if err != nil {
+               return err
        }
-       return tradePairs, nil
+
+       batch.Set(bestMatchStore, value)
+       return nil
 }
 
-func (m *MovStore) updateTradePairs(batch dbm.Batch, tradePairs map[common.TradePair]int) error {
-       for k, v := range tradePairs {
-               key := calcTradePairKey(k.FromAssetID, k.ToAssetID)
+func (m *LevelDBMovStore) updateTradePairs(batch dbm.Batch, tradePairs map[string]*common.TradePair) error {
+       for _, v := range tradePairs {
+               key := calcTradePairKey(v.FromAssetID, v.ToAssetID)
                tradePairData := &tradePairData{}
                if value := m.db.Get(key); value != nil {
                        if err := json.Unmarshal(value, tradePairData); err != nil {
                                return err
                        }
-               } else if v < 0 {
-                       return errors.New("don't find trade pair")
                }
 
-               tradePairData.Count += v
+               if tradePairData.Count += v.Count; tradePairData.Count < 0 {
+                       return errors.New("negative trade count")
+               }
+
                if tradePairData.Count > 0 {
                        value, err := json.Marshal(tradePairData)
                        if err != nil {
@@ -241,27 +312,3 @@ func (m *MovStore) updateTradePairs(batch dbm.Batch, tradePairs map[common.Trade
        }
        return nil
 }
-
-func (m *MovStore) checkMovDatabaseState(header *types.BlockHeader) error {
-       state, err := m.GetMovDatabaseState()
-       if err != nil {
-               return err
-       }
-
-       blockHash := header.Hash()
-       if (state.Hash.String() == header.PreviousBlockHash.String() && (state.Height+1) == header.Height) || state.Hash.String() == blockHash.String() {
-               return nil
-       }
-
-       return errors.New("the status of the block is inconsistent with that of mov-database")
-}
-
-func (m *MovStore) saveMovDatabaseState(batch dbm.Batch, state *common.MovDatabaseState) error {
-       value, err := json.Marshal(state)
-       if err != nil {
-               return err
-       }
-
-       batch.Set(bestMatchStore, value)
-       return nil
-}
index f212ae0..aeb9c3f 100644 (file)
@@ -10,10 +10,8 @@ import (
        "github.com/stretchr/testify/require"
 
        "github.com/bytom/vapor/application/mov/common"
-       "github.com/bytom/vapor/consensus"
        "github.com/bytom/vapor/database/leveldb"
        dbm "github.com/bytom/vapor/database/leveldb"
-       chainjson "github.com/bytom/vapor/encoding/json"
        "github.com/bytom/vapor/protocol/bc"
        "github.com/bytom/vapor/protocol/bc/types"
        "github.com/bytom/vapor/testutil"
@@ -28,31 +26,203 @@ var (
        assetID6 = &bc.AssetID{V0: 6}
        assetID7 = &bc.AssetID{V0: 7}
        assetID8 = &bc.AssetID{V0: 8}
-)
 
-func TestCalcUTXOHash(t *testing.T) {
-       wantHash := "7cbaf92f950f2a6bededd6cc5ec08c924505f5365b0a8af963e1d52912c99667"
-       controlProgramStr := "0014ab5acbea076f269bfdc8ededbed7d0a13e6e0b19"
-
-       var controlProgram chainjson.HexBytes
-       controlProgram.UnmarshalText([]byte(controlProgramStr))
-
-       sourceID := testutil.MustDecodeHash("ca2faf5fcbf8ee2b43560a32594f608528b12a1fe79cee85252564f886f91060")
-       order := &common.Order{
-               FromAssetID: consensus.BTMAssetID,
-               Utxo: &common.MovUtxo{
-                       SourceID:       &sourceID,
-                       SourcePos:      0,
-                       Amount:         31249300000,
-                       ControlProgram: controlProgram[:],
+       mockOrders = []*common.Order{
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   100090,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 21},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   90,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 22},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   97,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 23},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   98,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 13},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   98,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 24},
+                               Amount:         10,
+                               SourcePos:      1,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   99,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 24},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 25},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   95,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 26},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   90,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 1},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   90,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 2},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID3,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 33},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID4,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   95,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 34},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID4,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 36},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID5,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 37},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
+               },
+               &common.Order{
+                       FromAssetID:      assetID6,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   98,
+                       RatioDenominator: 100000,
+                       Utxo: &common.MovUtxo{
+                               SourceID:       &bc.Hash{V0: 38},
+                               Amount:         1,
+                               SourcePos:      0,
+                               ControlProgram: []byte("aa"),
+                       },
                },
        }
+)
+
+func TestGetAssetIDFromTradePairKey(t *testing.T) {
+       b := calcTradePairKey(assetID1, assetID2)
+       gotA := getAssetIDFromTradePairKey(b, fromAssetIDPos)
+       gotB := getAssetIDFromTradePairKey(b, toAssetIDPos)
 
-       hash := calcUTXOHash(order)
-       if hash.String() != wantHash {
-               t.Fatal("The function is incorrect")
+       if *gotA != *assetID1 {
+               t.Fatalf("got wrong from asset id got %s, want %s", gotA.String(), assetID1.String())
        }
 
+       if *gotB != *assetID2 {
+               t.Fatalf("got wrong to asset id got %s, want %s", gotB.String(), assetID2.String())
+       }
 }
 
 func TestSortOrderKey(t *testing.T) {
@@ -75,15 +245,16 @@ func TestSortOrderKey(t *testing.T) {
        }
 
        cases := []struct {
-               orders []common.Order
+               orders []*common.Order
                want   []expectedData
        }{
                {
-                       orders: []common.Order{
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        1.00090,
+                       orders: []*common.Order{
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   100090,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 21},
                                                Amount:         1,
@@ -91,10 +262,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00090,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   90,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 22},
                                                Amount:         1,
@@ -102,10 +274,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00097,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   97,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 23},
                                                Amount:         1,
@@ -113,10 +286,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 13},
                                                Amount:         1,
@@ -124,10 +298,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 24},
                                                Amount:         10,
@@ -135,10 +310,47 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00099,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 25},
+                                               Amount:         10,
+                                               SourcePos:      1,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 26},
+                                               Amount:         10,
+                                               SourcePos:      1,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 27},
+                                               Amount:         10,
+                                               SourcePos:      1,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   99,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 24},
                                                Amount:         1,
@@ -146,10 +358,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00096,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   96,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 25},
                                                Amount:         1,
@@ -157,10 +370,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00095,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   95,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 26},
                                                Amount:         1,
@@ -168,10 +382,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00091,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   91,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 26},
                                                Amount:         1,
@@ -179,10 +394,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00092,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   92,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 27},
                                                Amount:         1,
@@ -190,10 +406,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00093,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   93,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 28},
                                                Amount:         1,
@@ -201,10 +418,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00094,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   94,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 29},
                                                Amount:         1,
@@ -212,10 +430,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00077,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   77,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 30},
                                                Amount:         1,
@@ -223,10 +442,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00088,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   88,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 31},
                                                Amount:         1,
@@ -234,10 +454,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        999999.9521,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   9999999521,
+                                       RatioDenominator: 10000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 32},
                                                Amount:         1,
@@ -245,10 +466,11 @@ func TestSortOrderKey(t *testing.T) {
                                                ControlProgram: []byte("aa"),
                                        },
                                },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        888888.7954,
+                               &common.Order{
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   8888887954,
+                                       RatioDenominator: 10000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 33},
                                                Amount:         1,
@@ -300,10 +522,22 @@ func TestSortOrderKey(t *testing.T) {
                                },
                                expectedData{
                                        rate:     0.00098,
+                                       utxoHash: "14b51a6103f75d9cacdf0f9551467588c687ed3b029e25c646d276720569e227",
+                               },
+                               expectedData{
+                                       rate:     0.00098,
                                        utxoHash: "1fa9fae83d0a5401a4e92f80636966486e763eecca588aa11dff02b415320602",
                                },
                                expectedData{
                                        rate:     0.00098,
+                                       utxoHash: "6687d18ddbe4e7381a844e393ca3032a412285c9da6988eff182106e28ba09ca",
+                               },
+                               expectedData{
+                                       rate:     0.00098,
+                                       utxoHash: "841b1de7c871dfe6e2d1886809d9ae12ec45e570233b03879305232b096fda43",
+                               },
+                               expectedData{
+                                       rate:     0.00098,
                                        utxoHash: "a4bc534c267d35a9eafc25cd66e0cb270a2537a51186605b7f7591bc567ab4c6",
                                },
                                expectedData{
@@ -328,7 +562,7 @@ func TestSortOrderKey(t *testing.T) {
 
        for i, c := range cases {
                for _, order := range c.orders {
-                       key := calcOrderKey(order.FromAssetID, order.ToAssetID, calcUTXOHash(&order), order.Rate)
+                       key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate())
                        data, err := json.Marshal(order.Utxo)
                        if err != nil {
                                t.Fatal(err)
@@ -338,7 +572,6 @@ func TestSortOrderKey(t *testing.T) {
                }
 
                got := []expectedData{}
-
                itr := db.IteratorPrefixWithStart(nil, nil, false)
                for itr.Next() {
                        key := itr.Key()
@@ -347,9 +580,8 @@ func TestSortOrderKey(t *testing.T) {
                        copy(b[:], key[pos+8:])
                        utxoHash := bc.NewHash(b)
 
-                       rate := getRateFromOrderKey(key, ordersPrefix)
                        got = append(got, expectedData{
-                               rate:     rate,
+                               rate:     getRateFromOrderKey(key),
                                utxoHash: utxoHash.String(),
                        })
                }
@@ -358,7 +590,6 @@ func TestSortOrderKey(t *testing.T) {
                if !testutil.DeepEqual(c.want, got) {
                        t.Errorf("case %v: got recovery status, got: %v, want: %v.", i, got, c.want)
                }
-
        }
 }
 
@@ -378,1584 +609,210 @@ func TestMovStore(t *testing.T) {
                {
                        desc: "add order",
                        addOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       blockHeader: &types.BlockHeader{Height: 1, PreviousBlockHash: bc.Hash{V0: 524821139490765641, V1: 2484214155808702787, V2: 9108473449351508820, V3: 7972721253564512122}},
+                       wantOrders: []*common.Order{
+                               mockOrders[1],
+                               mockOrders[7],
+                               mockOrders[6],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[0],
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 8},
+                       },
+                       wantDBState: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+               },
+               {
+                       desc: "del some order",
+                       beforeOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       beforeTradePairs: []*common.TradePair{
+                               &common.TradePair{
                                        FromAssetID: assetID1,
                                        ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
+                                       Count:       8,
                                },
-                               &common.Order{
+                       },
+                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       delOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                       },
+                       blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       wantOrders: []*common.Order{
+                               mockOrders[7],
+                               mockOrders[6],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 5},
+                       },
+                       wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
+               },
+               {
+                       desc: "del all order",
+                       beforeOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       beforeTradePairs: []*common.TradePair{
+                               &common.TradePair{
                                        FromAssetID: assetID1,
                                        ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
+                                       Count:       8,
                                },
-                               &common.Order{
+                       },
+                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       delOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       blockHeader:    &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       wantOrders:     []*common.Order{},
+                       wantTradePairs: []*common.TradePair{},
+                       wantDBState:    &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
+               },
+               {
+                       desc: "Add and delete the same trade pair", // Add and delete different transaction pairs
+                       beforeOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       beforeTradePairs: []*common.TradePair{
+                               &common.TradePair{
                                        FromAssetID: assetID1,
                                        ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
+                                       Count:       8,
                                },
                        },
-                       blockHeader: &types.BlockHeader{Height: 1, PreviousBlockHash: bc.Hash{V0: 524821139490765641, V1: 2484214155808702787, V2: 9108473449351508820, V3: 7972721253564512122}},
+                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       addOrders: []*common.Order{
+                               mockOrders[8],
+                               mockOrders[9],
+                       },
+                       delOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
                        wantOrders: []*common.Order{
-                               &common.Order{
+                               mockOrders[9],
+                               mockOrders[8],
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 2},
+                       },
+                       wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
+               },
+               {
+                       desc: "Add and delete different transaction pairs",
+                       beforeOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                               mockOrders[10],
+                               mockOrders[11],
+                       },
+                       beforeTradePairs: []*common.TradePair{
+                               &common.TradePair{
                                        FromAssetID: assetID1,
                                        ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
+                                       Count:       8,
                                },
-                               &common.Order{
-                                       FromAssetID: assetID1,
+                               &common.TradePair{
+                                       FromAssetID: assetID3,
                                        ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
+                                       Count:       1,
                                },
-                               &common.Order{
-                                       FromAssetID: assetID1,
+                               &common.TradePair{
+                                       FromAssetID: assetID4,
                                        ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       wantTradePairs: []*common.TradePair{
-                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 8},
-                       },
-                       wantDBState: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
-               },
-               {
-                       desc: "del some order",
-                       beforeOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       beforeTradePairs: []*common.TradePair{
-                               &common.TradePair{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Count:       8,
+                                       Count:       1,
                                },
                        },
                        beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       addOrders: []*common.Order{
+                               mockOrders[12],
+                               mockOrders[13],
+                               mockOrders[14],
+                       },
                        delOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                               mockOrders[10],
                        },
                        blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
                        wantOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
+                               mockOrders[11],
+                               mockOrders[12],
+                               mockOrders[13],
+                               mockOrders[14],
                        },
                        wantTradePairs: []*common.TradePair{
-                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 5},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID2, Count: 2},
+                               &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID2, Count: 1},
+                               &common.TradePair{FromAssetID: assetID6, ToAssetID: assetID2, Count: 1},
                        },
                        wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
                },
-               {
-                       desc: "del all order",
-                       beforeOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       beforeTradePairs: []*common.TradePair{
-                               &common.TradePair{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Count:       8,
-                               },
-                       },
-                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
-                       delOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       blockHeader:    &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
-                       wantOrders:     []*common.Order{},
-                       wantTradePairs: []*common.TradePair{},
-                       wantDBState:    &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
-               },
-               {
-                       desc: "Add and delete the same trade pair", //Add and delete different transaction pairs
-                       beforeOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       beforeTradePairs: []*common.TradePair{
-                               &common.TradePair{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Count:       8,
-                               },
-                       },
-                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
-                       addOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 1},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 2},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       delOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
-                       wantOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 2},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 1},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       wantTradePairs: []*common.TradePair{
-                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 2},
-                       },
-                       wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
-               },
-               {
-                       desc: "Add and delete different transaction pairs",
-                       beforeOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID3,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 33},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID4,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 34},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       beforeTradePairs: []*common.TradePair{
-                               &common.TradePair{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Count:       8,
-                               },
-                               &common.TradePair{
-                                       FromAssetID: assetID3,
-                                       ToAssetID:   assetID2,
-                                       Count:       1,
-                               },
-                               &common.TradePair{
-                                       FromAssetID: assetID4,
-                                       ToAssetID:   assetID2,
-                                       Count:       1,
-                               },
-                       },
-                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
-                       addOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID4,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 36},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID5,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 37},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID6,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 38},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       delOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID3,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 33},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
-                       wantOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID4,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 34},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID4,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 36},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID5,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 37},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID6,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 38},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       wantTradePairs: []*common.TradePair{
-                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID2, Count: 2},
-                               &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID2, Count: 1},
-                               &common.TradePair{FromAssetID: assetID6, ToAssetID: assetID2, Count: 1},
-                       },
-                       wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
-               },
-       }
-
-       initBlockHeader := &types.BlockHeader{
-               Height:  0,
-               Version: 1,
-       }
-
-       height := initBlockHeader.Height
-       hash := initBlockHeader.Hash()
-
-       defer os.RemoveAll("temp")
-       for i, c := range cases {
-               testDB := dbm.NewDB("testdb", "leveldb", "temp")
-               movStore, err := NewMovStore(testDB, height, &hash)
-               if err != nil {
-                       t.Fatalf("case %d: NewMovStore error %v.", i, err)
-               }
-
-               batch := movStore.db.NewBatch()
-               tradePairsCnt := make(map[common.TradePair]int)
-               movStore.addOrders(batch, c.beforeOrders, tradePairsCnt)
-               if len(c.beforeOrders) > 0 {
-                       tradePairsCnt = make(map[common.TradePair]int)
-                       for _, tradePair := range c.beforeTradePairs {
-                               tradePairsCnt[*tradePair] = tradePair.Count
-                       }
-                       movStore.updateTradePairs(batch, tradePairsCnt)
-                       movStore.saveMovDatabaseState(batch, c.beforeDBStatus)
-               }
-               batch.Write()
-
-               if err := movStore.ProcessOrders(c.addOrders, c.delOrders, c.blockHeader); err != nil {
-                       t.Fatalf("case %d: ProcessOrders error %v.", i, err)
-               }
-
-               var gotOrders []*common.Order
-
-               tmp, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2, Rate: 0})
-               if err != nil {
-                       t.Fatalf("case %d: ListOrders(assetID1 and assetID2) error %v.", i, err)
-               }
-
-               gotOrders = append(gotOrders, tmp...)
-
-               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID3, ToAssetID: assetID2, Rate: 0})
-               if err != nil {
-                       t.Fatalf("case %d: ListOrders(assetID3 and assetID2)  error %v.", i, err)
-               }
-
-               gotOrders = append(gotOrders, tmp...)
-
-               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID4, ToAssetID: assetID2, Rate: 0})
-               if err != nil {
-                       t.Fatalf("case %d: ListOrders(assetID4 and assetID2)  error %v.", i, err)
-               }
-
-               gotOrders = append(gotOrders, tmp...)
-
-               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID5, ToAssetID: assetID2, Rate: 0})
-               if err != nil {
-                       t.Fatalf("case %d: ListOrders(assetID5 and assetID2)  error %v.", i, err)
-               }
-
-               gotOrders = append(gotOrders, tmp...)
-
-               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID6, ToAssetID: assetID2, Rate: 0})
-               if err != nil {
-                       t.Fatalf("case %d: ListOrders(assetID6 and assetID2)  error %v.", i, err)
-               }
-
-               gotOrders = append(gotOrders, tmp...)
-
-               if !testutil.DeepEqual(gotOrders, c.wantOrders) {
-                       t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
-               }
-
-               gotTradePairs, err := movStore.ListTradePairsWithStart(nil, nil)
-               if err != nil {
-                       t.Fatalf("case %d: ListTradePairsWithStart error %v.", i, err)
-               }
-
-               if !testutil.DeepEqual(gotTradePairs, c.wantTradePairs) {
-                       t.Fatalf("case %d: got tradePairs, gotTradePairs: %v, wantTradePairs: %v.", i, gotTradePairs, c.wantTradePairs)
-               }
-
-               gotDBState, err := movStore.GetMovDatabaseState()
-               if err != nil {
-                       t.Fatalf("case %d: GetMovDatabaseState error %v.", i, err)
-               }
-
-               if !testutil.DeepEqual(gotDBState, c.wantDBState) {
-                       t.Fatalf("case %d: got tradePairs, gotDBState: %v, wantDBStatus: %v.", i, gotDBState, c.wantDBState)
-               }
-
-               testDB.Close()
-               os.RemoveAll("temp")
-       }
-}
-
-func TestListOrders(t *testing.T) {
-       cases := []struct {
-               desc        string
-               storeOrders []*common.Order
-               query       *common.Order
-               wantOrders  []*common.Order
-       }{
-               {
-                       desc:       "empty",
-                       query:      &common.Order{FromAssetID: assetID1, ToAssetID: assetID2},
-                       wantOrders: []*common.Order{},
-               },
-               {
-                       desc: "query from first",
-                       storeOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       query: &common.Order{FromAssetID: assetID1, ToAssetID: assetID2},
-                       wantOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-               },
-               {
-                       desc: "query from middle",
-                       storeOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       query: &common.Order{
-                               FromAssetID: assetID1,
-                               ToAssetID:   assetID2,
-                               Rate:        0.00098,
-                               Utxo: &common.MovUtxo{
-                                       SourceID:       &bc.Hash{V0: 13},
-                                       Amount:         1,
-                                       SourcePos:      0,
-                                       ControlProgram: []byte("aa"),
-                               },
-                       },
-                       wantOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-               },
        }
 
        initBlockHeader := &types.BlockHeader{
@@ -1969,404 +826,239 @@ func TestListOrders(t *testing.T) {
        defer os.RemoveAll("temp")
        for i, c := range cases {
                testDB := dbm.NewDB("testdb", "leveldb", "temp")
-               movStore, err := NewMovStore(testDB, height, &hash)
-               if err != nil {
-                       t.Fatalf("case %d: NewMovStore error %v.", i, err)
+               movStore := NewLevelDBMovStore(testDB)
+               if err := movStore.InitDBState(height, &hash); err != nil {
+                       t.Fatalf("case %d: InitDBState error %v.", i, err)
                }
 
                batch := movStore.db.NewBatch()
-               tradePairsCnt := make(map[common.TradePair]int)
-               movStore.addOrders(batch, c.storeOrders, tradePairsCnt)
-               movStore.updateTradePairs(batch, tradePairsCnt)
+               tradePairsCnt := make(map[string]*common.TradePair)
+               movStore.addOrders(batch, c.beforeOrders, tradePairsCnt)
+               if len(c.beforeOrders) > 0 {
+                       tradePairsCnt = make(map[string]*common.TradePair)
+                       for _, tradePair := range c.beforeTradePairs {
+                               tradePairsCnt[tradePair.Key()] = tradePair
+                       }
+                       movStore.updateTradePairs(batch, tradePairsCnt)
+                       movStore.saveMovDatabaseState(batch, c.beforeDBStatus)
+               }
                batch.Write()
 
-               gotOrders, err := movStore.ListOrders(c.query)
+               if err := movStore.ProcessOrders(c.addOrders, c.delOrders, c.blockHeader); err != nil {
+                       t.Fatalf("case %d: ProcessOrders error %v.", i, err)
+               }
+
+               var gotOrders []*common.Order
+
+               tmp, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
                if err != nil {
-                       t.Fatalf("case %d: ListOrders error %v.", i, err)
+                       t.Fatalf("case %d: ListOrders(assetID1 and assetID2) error %v.", i, err)
                }
 
-               if !testutil.DeepEqual(gotOrders, c.wantOrders) {
-                       t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
+               gotOrders = append(gotOrders, tmp...)
+
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID3, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
+               if err != nil {
+                       t.Fatalf("case %d: ListOrders(assetID3 and assetID2)  error %v.", i, err)
                }
 
-               testDB.Close()
-               os.RemoveAll("temp")
-       }
-}
+               gotOrders = append(gotOrders, tmp...)
 
-func TestAddOrders(t *testing.T) {
-       cases := []struct {
-               desc         string
-               beforeOrders []*common.Order
-               addOrders    []*common.Order
-               wantOrders   []*common.Order
-       }{
-               {
-                       desc: "empty",
-                       addOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       wantOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID4, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
+               if err != nil {
+                       t.Fatalf("case %d: ListOrders(assetID4 and assetID2)  error %v.", i, err)
+               }
+
+               gotOrders = append(gotOrders, tmp...)
+
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID5, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
+               if err != nil {
+                       t.Fatalf("case %d: ListOrders(assetID5 and assetID2)  error %v.", i, err)
+               }
+
+               gotOrders = append(gotOrders, tmp...)
+
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID6, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
+               if err != nil {
+                       t.Fatalf("case %d: ListOrders(assetID6 and assetID2)  error %v.", i, err)
+               }
+
+               gotOrders = append(gotOrders, tmp...)
+
+               if !testutil.DeepEqual(gotOrders, c.wantOrders) {
+                       t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
+               }
+
+               gotTradePairs, err := movStore.ListTradePairsWithStart(nil, nil)
+               if err != nil {
+                       t.Fatalf("case %d: ListTradePairsWithStart error %v.", i, err)
+               }
+
+               if !testutil.DeepEqual(gotTradePairs, c.wantTradePairs) {
+                       t.Fatalf("case %d: got tradePairs, gotTradePairs: %v, wantTradePairs: %v.", i, gotTradePairs, c.wantTradePairs)
+               }
+
+               gotDBState, err := movStore.GetMovDatabaseState()
+               if err != nil {
+                       t.Fatalf("case %d: GetMovDatabaseState error %v.", i, err)
+               }
+
+               if !testutil.DeepEqual(gotDBState, c.wantDBState) {
+                       t.Fatalf("case %d: got tradePairs, gotDBState: %v, wantDBStatus: %v.", i, gotDBState, c.wantDBState)
+               }
+
+               testDB.Close()
+               os.RemoveAll("temp")
+       }
+}
+
+func TestListOrders(t *testing.T) {
+       cases := []struct {
+               desc        string
+               storeOrders []*common.Order
+               query       *common.Order
+               wantOrders  []*common.Order
+       }{
+               {
+                       desc:       "empty",
+                       query:      &common.Order{FromAssetID: assetID1, ToAssetID: assetID2},
+                       wantOrders: []*common.Order{},
+               },
+               {
+                       desc: "query from first",
+                       storeOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                               mockOrders[10],
+                       },
+                       query: &common.Order{FromAssetID: assetID1, ToAssetID: assetID2},
+                       wantOrders: []*common.Order{
+                               mockOrders[1],
+                               mockOrders[7],
+                               mockOrders[6],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[0],
                        },
                },
                {
-                       desc: "Stored data already exists",
-                       beforeOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
+                       desc: "query from middle",
+                       storeOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       query: mockOrders[3],
+                       wantOrders: []*common.Order{
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[0],
                        },
+               },
+       }
+
+       initBlockHeader := &types.BlockHeader{
+               Height:  0,
+               Version: 1,
+       }
+
+       height := initBlockHeader.Height
+       hash := initBlockHeader.Hash()
+
+       defer os.RemoveAll("temp")
+       for i, c := range cases {
+               testDB := dbm.NewDB("testdb", "leveldb", "temp")
+               movStore := NewLevelDBMovStore(testDB)
+               if err := movStore.InitDBState(height, &hash); err != nil {
+                       t.Fatalf("case %d: InitDBState error %v.", i, err)
+               }
+
+               batch := movStore.db.NewBatch()
+               tradePairsCnt := make(map[string]*common.TradePair)
+               movStore.addOrders(batch, c.storeOrders, tradePairsCnt)
+               movStore.updateTradePairs(batch, tradePairsCnt)
+               batch.Write()
+
+               gotOrders, err := movStore.ListOrders(c.query)
+               if err != nil {
+                       t.Fatalf("case %d: ListOrders error %v.", i, err)
+               }
+
+               if !testutil.DeepEqual(gotOrders, c.wantOrders) {
+                       t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
+               }
+
+               testDB.Close()
+               os.RemoveAll("temp")
+       }
+}
+
+func TestAddOrders(t *testing.T) {
+       cases := []struct {
+               desc         string
+               beforeOrders []*common.Order
+               addOrders    []*common.Order
+               wantOrders   []*common.Order
+       }{
+               {
+                       desc: "empty",
                        addOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
                        },
-                       wantOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00095,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00096,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00097,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00098,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        0.00099,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
+                       wantOrders: []*common.Order{
+                               mockOrders[1],
+                               mockOrders[7],
+                               mockOrders[6],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[0],
+                       },
+               },
+               {
+                       desc: "Stored data already exists",
+                       beforeOrders: []*common.Order{
+                               mockOrders[0],
+                               mockOrders[1],
+                               mockOrders[2],
+                               mockOrders[3],
+                       },
+                       addOrders: []*common.Order{
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[6],
+                               mockOrders[7],
+                       },
+                       wantOrders: []*common.Order{
+                               mockOrders[1],
+                               mockOrders[7],
+                               mockOrders[6],
+                               mockOrders[2],
+                               mockOrders[3],
+                               mockOrders[4],
+                               mockOrders[5],
+                               mockOrders[0],
                        },
                },
        }
@@ -2382,18 +1074,18 @@ func TestAddOrders(t *testing.T) {
        defer os.RemoveAll("temp")
        for i, c := range cases {
                testDB := dbm.NewDB("testdb", "leveldb", "temp")
-               movStore, err := NewMovStore(testDB, height, &hash)
-               if err != nil {
-                       t.Fatalf("case %d: NewMovStore error %v.", i, err)
+               movStore := NewLevelDBMovStore(testDB)
+               if err := movStore.InitDBState(height, &hash); err != nil {
+                       t.Fatalf("case %d: InitDBState error %v.", i, err)
                }
 
                batch := movStore.db.NewBatch()
-               tradePairsCnt := make(map[common.TradePair]int)
+               tradePairsCnt := make(map[string]*common.TradePair)
                movStore.addOrders(batch, c.beforeOrders, tradePairsCnt)
                movStore.updateTradePairs(batch, tradePairsCnt)
                batch.Write()
 
-               tradePairsCnt = make(map[common.TradePair]int)
+               tradePairsCnt = make(map[string]*common.TradePair)
                movStore.addOrders(batch, c.addOrders, tradePairsCnt)
                batch.Write()
 
@@ -2422,28 +1114,8 @@ func TestDelOrders(t *testing.T) {
                {
                        desc: "empty",
                        delOrders: []*common.Order{
-                               &common.Order{
-                                       FromAssetID: assetID1,
-                                       ToAssetID:   assetID2,
-                                       Rate:        1.00090,
-                                       Utxo: &common.MovUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-    &nbs