OSDN Git Service

Dex database logic implementation (#404)
authorwz <mars@bytom.io>
Thu, 10 Oct 2019 08:21:31 +0000 (16:21 +0800)
committerPaladz <yzhu101@uottawa.ca>
Thu, 10 Oct 2019 08:21:31 +0000 (16:21 +0800)
* add logic

* Add logic implementation

* fix name

* fix

* fix

* fix

* fix and add test

* fix test

* fix

* fix

* fix space line

application/dex/database/dex_store.go [deleted file]
application/dex/database/dex_store_test.go [deleted file]
application/mov/common/type.go [moved from application/dex/common/type.go with 78% similarity]
application/mov/database/mov_store.go [new file with mode: 0644]
application/mov/database/mov_store_test.go [new file with mode: 0644]

diff --git a/application/dex/database/dex_store.go b/application/dex/database/dex_store.go
deleted file mode 100644 (file)
index 9035ac0..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-package database
-
-import (
-       "encoding/binary"
-       "math"
-
-       "github.com/vapor/application/dex/common"
-       dbm "github.com/vapor/database/leveldb"
-       "github.com/vapor/protocol/bc"
-)
-
-const (
-       order byte = iota
-       tradePair
-       matchStatus
-)
-
-var (
-       dexStore        = []byte("DEX:")
-       ordersPreFix    = append(dexStore, order)
-       tradePairPreFix = append(dexStore, tradePair)
-       bestMatchStore  = append(dexStore, matchStatus)
-)
-
-func calcOrdersPrefix(fromAssetID, toAssetID *bc.AssetID, utxoHash *bc.Hash, rate float64) []byte {
-       buf := make([]byte, 8)
-       binary.BigEndian.PutUint64(buf, math.Float64bits(rate))
-       key := append(ordersPreFix, fromAssetID.Bytes()...)
-       key = append(key, toAssetID.Bytes()...)
-       key = append(key, buf...)
-       return append(key, utxoHash.Bytes()...)
-}
-
-func calcTradePairPreFix(fromAssetID, toAssetID *bc.Hash) []byte {
-       key := append(ordersPreFix, fromAssetID.Bytes()...)
-       return append(key, toAssetID.Bytes()...)
-}
-
-type DexTradeOrderDB struct {
-       db dbm.DB
-}
-
-func (d *DexTradeOrderDB) GetTradePairsWithStart(start []byte) ([]common.TradePair, error) {
-       return nil, nil
-}
-
-func (d *DexTradeOrderDB) addTradePair() error {
-       return nil
-}
-
-func (d *DexTradeOrderDB) deleteTradePair() error {
-       return nil
-}
-
-func (d *DexTradeOrderDB) ProcessOrders(addOrders []*common.Order, delOreders []*common.Order, height uint64, blockHash *bc.Hash) error {
-
-       return nil
-}
-
-func (d *DexTradeOrderDB) addOrders(orders []*common.Order) error {
-       return nil
-}
-
-func (d *DexTradeOrderDB) deleteOrder(orders []*common.Order) error {
-       return nil
-}
-
-func (d *DexTradeOrderDB) ListOrders(fromAssetID, toAssetID string, rateAfter float64) ([]*common.Order, error) {
-       return nil, nil
-}
-
-func (d *DexTradeOrderDB) GetDexDatabaseState() (*common.DexDatabaseState, error) {
-       return nil, nil
-}
-
-func (d *DexTradeOrderDB) saveDexDatabaseState(state *common.DexDatabaseState) error {
-       return nil
-}
diff --git a/application/dex/database/dex_store_test.go b/application/dex/database/dex_store_test.go
deleted file mode 100644 (file)
index c72e632..0000000
+++ /dev/null
@@ -1,323 +0,0 @@
-package database
-
-import (
-       "encoding/binary"
-       "encoding/json"
-       "io/ioutil"
-       "math"
-       "os"
-       "testing"
-
-       "github.com/stretchr/testify/require"
-       "golang.org/x/crypto/sha3"
-
-       "github.com/vapor/application/dex/common"
-       "github.com/vapor/database/leveldb"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/testutil"
-)
-
-func TestSortOrderKey(t *testing.T) {
-       dirname, err := ioutil.TempDir("", "db_common_test")
-       require.Nil(t, err)
-
-       db, err := leveldb.NewGoLevelDB("testdb", dirname)
-       if err != nil {
-               t.Fatal(err)
-       }
-
-       defer func() {
-               db.Close()
-               os.RemoveAll(dirname)
-       }()
-
-       type expectedData struct {
-               rate     float64
-               utxoHash string
-       }
-
-       cases := []struct {
-               orders []common.Order
-               want   []expectedData
-       }{
-               {
-                       orders: []common.Order{
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        1.00090,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 21},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00090,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 22},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00097,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 23},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 13},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         10,
-                                               SourcePos:      1,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00099,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 24},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00096,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 25},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00095,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00091,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 26},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00092,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 27},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00093,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 28},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00094,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 29},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00077,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 30},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00088,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 31},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        999999.9521,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 32},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                               common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        888888.7954,
-                                       Utxo: &common.DexUtxo{
-                                               SourceID:       &bc.Hash{V0: 33},
-                                               Amount:         1,
-                                               SourcePos:      0,
-                                               ControlProgram: []byte("aa"),
-                                       },
-                               },
-                       },
-                       want: []expectedData{
-                               expectedData{
-                                       rate:     0.00077,
-                                       utxoHash: "7967bb8c4cca951749553e9c7787255d35a032d9e1acecefe4011c8095dc8e6f",
-                               },
-                               expectedData{
-                                       rate:     0.00088,
-                                       utxoHash: "215a6e7e3a5006151bd0b81c54fcccda0381f3a22e7b6646ed201c35f9fa6c5a",
-                               },
-                               expectedData{
-                                       rate:     0.00090,
-                                       utxoHash: "cb373d3a383d30eb2863317ea2cfb5b4b269772fbc0fb8413a2be7d7b69ec2b9",
-                               },
-                               expectedData{
-                                       rate:     0.00091,
-                                       utxoHash: "298c39d327cb4b0dcefcf701aa8d1b559f1de0148e9bcbe14da48cfa268c01ea",
-                               },
-                               expectedData{
-                                       rate:     0.00092,
-                                       utxoHash: "b2c59190fb0d948c9545c146a69b1f17503b2d280b2f3f45ecc0a7b7e2cd1784",
-                               },
-                               expectedData{
-                                       rate:     0.00093,
-                                       utxoHash: "80b44aae2b2cf57bd2cf77cb88f0d8363066f5f16a17a3e85224ecbbc6387d8b",
-                               },
-                               expectedData{
-                                       rate:     0.00094,
-                                       utxoHash: "4843adc8c4a50672a022e5f377dfd2ac11119364dc0a547be45b4a5edacef33b",
-                               },
-                               expectedData{
-                                       rate:     0.00095,
-                                       utxoHash: "298c39d327cb4b0dcefcf701aa8d1b559f1de0148e9bcbe14da48cfa268c01ea",
-                               },
-                               expectedData{
-                                       rate:     0.00096,
-                                       utxoHash: "d8d1a85303e9ac738e675b874b866e5ffbfa10e05201113404dde544055a18b9",
-                               },
-                               expectedData{
-                                       rate:     0.00097,
-                                       utxoHash: "2305be66ab9648b713a58e3807fa1cba1f84e5d11359b316e967d98e9a7667da",
-                               },
-                               expectedData{
-                                       rate:     0.00098,
-                                       utxoHash: "030dc8a868a3e534799d465ebc8209eb32d9465985dc8c35e731b124bf3ffbcf",
-                               },
-                               expectedData{
-                                       rate:     0.00098,
-                                       utxoHash: "8222a9a43b3951f247612ddce2fe36f96cd843bc0dfef86c7d0ef5335331f11f",
-                               },
-                               expectedData{
-                                       rate:     0.00099,
-                                       utxoHash: "a40bd183cd2ff2b52faac5ebc2cfc1e36104cbc92bcebac011b45792b39e380e",
-                               },
-                               expectedData{
-                                       rate:     1.0009,
-                                       utxoHash: "118b2c40848887614d99b0e7eb6c88a10b47196e6aca3ff2eeab452bfdb9cfcb",
-                               },
-                               expectedData{
-                                       rate:     888888.7954,
-                                       utxoHash: "545a5c6f7ff9be19ed07a7246277c67d661f9cc7d8956bb81ce9a4045fba3720",
-                               },
-                               expectedData{
-                                       rate:     999999.9521,
-                                       utxoHash: "d9f7725d908510268c7bdecd29cb2031baab93b9bfa69108eb0a926ba7ae18f9",
-                               },
-                       },
-               },
-       }
-
-       for i, c := range cases {
-               for _, order := range c.orders {
-                       data, err := json.Marshal(order.Utxo)
-                       if err != nil {
-                               t.Fatal(err)
-                       }
-                       utxoHash := bc.NewHash(sha3.Sum256(data))
-                       key := calcOrdersPrefix(order.FromAssetID, order.ToAssetID, &utxoHash, order.Rate)
-                       db.SetSync(key, data)
-               }
-
-               got := []expectedData{}
-
-               itr := db.IteratorPrefixWithStart(nil, nil, false)
-               for itr.Next() {
-                       key := itr.Key()
-                       pos := len(ordersPreFix) + 32*2
-                       b := [32]byte{}
-                       copy(b[:], key[pos+8:])
-                       utxoHash := bc.NewHash(b)
-                       got = append(got, expectedData{
-                               rate:     math.Float64frombits(binary.BigEndian.Uint64(key[pos : pos+8])),
-                               utxoHash: utxoHash.String(),
-                       })
-               }
-               itr.Release()
-
-               if !testutil.DeepEqual(c.want, got) {
-                       t.Errorf("case %v: got recovery status, got: %v, want: %v.", i, got, c.want)
-               }
-
-       }
-}
similarity index 78%
rename from application/dex/common/type.go
rename to application/mov/common/type.go
index 63baf2b..031e378 100644 (file)
@@ -2,7 +2,7 @@ package common
 
 import "github.com/vapor/protocol/bc"
 
-type DexUtxo struct {
+type MovUtxo struct {
        SourceID       *bc.Hash
        SourcePos      uint64
        Amount         uint64
@@ -12,17 +12,17 @@ type DexUtxo struct {
 type Order struct {
        FromAssetID *bc.AssetID
        ToAssetID   *bc.AssetID
-       Utxo        *DexUtxo
+       Utxo        *MovUtxo
        Rate        float64
 }
 
 type TradePair struct {
        FromAssetID *bc.AssetID
        ToAssetID   *bc.AssetID
-       Count       uint64
+       Count       int
 }
 
-type DexDatabaseState struct {
+type MovDatabaseState struct {
        Height uint64
        Hash   *bc.Hash
 }
diff --git a/application/mov/database/mov_store.go b/application/mov/database/mov_store.go
new file mode 100644 (file)
index 0000000..4aa831a
--- /dev/null
@@ -0,0 +1,267 @@
+package database
+
+import (
+       "encoding/binary"
+       "encoding/json"
+       "errors"
+       "math"
+
+       "github.com/vapor/application/mov/common"
+       dbm "github.com/vapor/database/leveldb"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+)
+
+const (
+       order byte = iota
+       tradePair
+       matchStatus
+
+       tradePairsNum = 1024
+       ordersNum     = 10240
+       assetIDLen    = 32
+       rateByteLen   = 8
+)
+
+var (
+       movStore         = []byte("MOV:")
+       ordersPrefix     = append(movStore, order)
+       tradePairsPrefix = append(movStore, tradePair)
+       bestMatchStore   = append(movStore, matchStatus)
+)
+
+func calcOrderKey(fromAssetID, toAssetID *bc.AssetID, utxoHash *bc.Hash, rate float64) []byte {
+       buf := make([]byte, 8)
+       binary.BigEndian.PutUint64(buf, math.Float64bits(rate))
+       key := append(ordersPrefix, fromAssetID.Bytes()...)
+       key = append(key, toAssetID.Bytes()...)
+       key = append(key, buf...)
+       return append(key, utxoHash.Bytes()...)
+}
+
+func calcTradePairKey(fromAssetID, toAssetID *bc.AssetID) []byte {
+       key := append(tradePairsPrefix, fromAssetID.Bytes()...)
+       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 {
+       b := [32]byte{}
+       pos := len(prefix) + 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
+       return math.Float64frombits(binary.BigEndian.Uint64(key[ratePos : ratePos+rateByteLen]))
+}
+
+type tradePairData struct {
+       Count int
+}
+
+type MovStore 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
+               }
+
+               db.Set(bestMatchStore, value)
+       }
+       return &MovStore{db: db}, nil
+}
+
+func (m *MovStore) ListOrders(orderAfter *common.Order) ([]*common.Order, error) {
+       if orderAfter.FromAssetID == nil || orderAfter.ToAssetID == nil {
+               return nil, errors.New("assetID is nil")
+       }
+
+       orderPrefix := append(ordersPrefix, orderAfter.FromAssetID.Bytes()...)
+       orderPrefix = append(orderPrefix, orderAfter.ToAssetID.Bytes()...)
+
+       var startKey []byte
+       if orderAfter.Rate > 0 {
+               startKey = calcOrderKey(orderAfter.FromAssetID, orderAfter.ToAssetID, calcUTXOHash(orderAfter), orderAfter.Rate)
+       }
+
+       itr := m.db.IteratorPrefixWithStart(orderPrefix, startKey, false)
+       defer itr.Release()
+
+       var orders []*common.Order
+       for txNum := 0; txNum < ordersNum && itr.Next(); txNum++ {
+               movUtxo := &common.MovUtxo{}
+               if err := json.Unmarshal(itr.Value(), movUtxo); 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)
+       }
+       return orders, nil
+}
+
+func (m *MovStore) ProcessOrders(addOrders []*common.Order, delOreders []*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)
+       if err := m.addOrders(batch, addOrders, tradePairsCnt); err != nil {
+               return err
+       }
+
+       m.deleteOrders(batch, delOreders, 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 {
+               return err
+       }
+
+       batch.Write()
+       return nil
+}
+
+func (m *MovStore) addOrders(batch dbm.Batch, orders []*common.Order, tradePairsCnt map[common.TradePair]int) error {
+       for _, order := range orders {
+               data, err := json.Marshal(order.Utxo)
+               if err != nil {
+                       return err
+               }
+
+               key := calcOrderKey(order.FromAssetID, order.ToAssetID, calcUTXOHash(order), order.Rate)
+               batch.Set(key, data)
+
+               tradePair := common.TradePair{
+                       FromAssetID: order.FromAssetID,
+                       ToAssetID:   order.ToAssetID,
+               }
+               tradePairsCnt[tradePair] += 1
+       }
+       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)
+
+               tradePair := common.TradePair{
+                       FromAssetID: order.FromAssetID,
+                       ToAssetID:   order.ToAssetID,
+               }
+               tradePairsCnt[tradePair] -= 1
+       }
+}
+
+func (m *MovStore) 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")
+}
+
+func (m *MovStore) 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, tradePairsPrefix, 0)
+               toAssetID := getAssetIDFromTradePairKey(key, tradePairsPrefix, 1)
+
+               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
+}
+
+func (m *MovStore) updateTradePairs(batch dbm.Batch, tradePairs map[common.TradePair]int) error {
+       for k, v := range tradePairs {
+               key := calcTradePairKey(k.FromAssetID, k.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 > 0 {
+                       value, err := json.Marshal(tradePairData)
+                       if err != nil {
+                               return err
+                       }
+
+                       batch.Set(key, value)
+               } else {
+                       batch.Delete(key)
+               }
+       }
+       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
+}
diff --git a/application/mov/database/mov_store_test.go b/application/mov/database/mov_store_test.go
new file mode 100644 (file)
index 0000000..7f17fc7
--- /dev/null
@@ -0,0 +1,3015 @@
+package database
+
+import (
+       "encoding/json"
+       "errors"
+       "io/ioutil"
+       "os"
+       "testing"
+
+       "github.com/stretchr/testify/require"
+
+       "github.com/vapor/application/mov/common"
+       "github.com/vapor/consensus"
+       "github.com/vapor/database/leveldb"
+       dbm "github.com/vapor/database/leveldb"
+       chainjson "github.com/vapor/encoding/json"
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+       "github.com/vapor/testutil"
+)
+
+var (
+       assetID1 = &bc.AssetID{V0: 1}
+       assetID2 = &bc.AssetID{V0: 2}
+       assetID3 = &bc.AssetID{V0: 3}
+       assetID4 = &bc.AssetID{V0: 4}
+       assetID5 = &bc.AssetID{V0: 5}
+       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[:],
+               },
+       }
+
+       hash := calcUTXOHash(order)
+       if hash.String() != wantHash {
+               t.Fatal("The function is incorrect")
+       }
+
+}
+
+func TestSortOrderKey(t *testing.T) {
+       dirname, err := ioutil.TempDir("", "db_common_test")
+       require.Nil(t, err)
+
+       db, err := leveldb.NewGoLevelDB("testdb", dirname)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       defer func() {
+               db.Close()
+               os.RemoveAll(dirname)
+       }()
+
+       type expectedData struct {
+               rate     float64
+               utxoHash string
+       }
+
+       cases := []struct {
+               orders []common.Order
+               want   []expectedData
+       }{
+               {
+                       orders: []common.Order{
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        1.00090,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 21},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00090,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 22},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00097,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 23},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00098,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 13},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00098,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 24},
+                                               Amount:         10,
+                                               SourcePos:      1,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00099,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 24},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00096,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 25},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00095,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 26},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00091,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 26},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00092,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 27},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00093,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 28},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00094,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 29},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00077,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 30},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        0.00088,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 31},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        999999.9521,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 32},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                               common.Order{
+                                       FromAssetID: &bc.AssetID{V0: 1},
+                                       ToAssetID:   &bc.AssetID{V0: 0},
+                                       Rate:        888888.7954,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 33},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                       },
+                       want: []expectedData{
+                               expectedData{
+                                       rate:     0.00077,
+                                       utxoHash: "f1b85307cf1f4eb6b193b6fc289413fdbb12bc362ced399762589b016e54dd02",
+                               },
+                               expectedData{
+                                       rate:     0.00088,
+                                       utxoHash: "49ef60af0f24962ed129a73142048ed0cb589041c629353932e3c3e0a4e822ba",
+                               },
+                               expectedData{
+                                       rate:     0.00090,
+                                       utxoHash: "67b2ac6ea71b271e72836e162811866f291ed2fab106c43519ca0c94ef8a5dce",
+                               },
+                               expectedData{
+                                       rate:     0.00091,
+                                       utxoHash: "47ff45b7b530512142981c2cee82faad63d6c9e7ffed0e72c3e42668f13b296f",
+                               },
+                               expectedData{
+                                       rate:     0.00092,
+                                       utxoHash: "b750d0b95f38043362c8335f242f97cfd3e1cada8fd171b914471a16cc0f14c6",
+                               },
+                               expectedData{
+                                       rate:     0.00093,
+                                       utxoHash: "04386ef57f0ca1be0a9be46c413900adbc0ab1e90e773959924aa73ca62edf64",
+                               },
+                               expectedData{
+                                       rate:     0.00094,
+                                       utxoHash: "c0fe6227c50da350a5e7b4ff85c18e9c901c323521067b9142acd128cf13ae82",
+                               },
+                               expectedData{
+                                       rate:     0.00095,
+                                       utxoHash: "47ff45b7b530512142981c2cee82faad63d6c9e7ffed0e72c3e42668f13b296f",
+                               },
+                               expectedData{
+                                       rate:     0.00096,
+                                       utxoHash: "bc92df1cbd20c98b0d18c9d93422a770849235867522a08e492196d16ed0a422",
+                               },
+                               expectedData{
+                                       rate:     0.00097,
+                                       utxoHash: "0cc0ded6fb337a3c5e6e4d008d6167dc58bdede43713898e914d65cda3b8499a",
+                               },
+                               expectedData{
+                                       rate:     0.00098,
+                                       utxoHash: "1fa9fae83d0a5401a4e92f80636966486e763eecca588aa11dff02b415320602",
+                               },
+                               expectedData{
+                                       rate:     0.00098,
+                                       utxoHash: "a4bc534c267d35a9eafc25cd66e0cb270a2537a51186605b7f7591bc567ab4c6",
+                               },
+                               expectedData{
+                                       rate:     0.00099,
+                                       utxoHash: "fdedf4117def659e07cc8a8ca318d21ae577a05e1a0197844b54d493bdae5854",
+                               },
+                               expectedData{
+                                       rate:     1.0009,
+                                       utxoHash: "20be3bd2d406bb7fe6627b32768fb2073e997b962a4badfa4384210fed2ab9c6",
+                               },
+                               expectedData{
+                                       rate:     888888.7954,
+                                       utxoHash: "72192f56b9525c74c6a9f0419563bc0da76b0f3d6e89d9decdb6e67786ac3909",
+                               },
+                               expectedData{
+                                       rate:     999999.9521,
+                                       utxoHash: "7886844334659b4feffc41528cf81192925d3aa4a5ccb3652200b9073b7d47c3",
+                               },
+                       },
+               },
+       }
+
+       for i, c := range cases {
+               for _, order := range c.orders {
+                       key := calcOrderKey(order.FromAssetID, order.ToAssetID, calcUTXOHash(&order), order.Rate)
+                       data, err := json.Marshal(order.Utxo)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+
+                       db.SetSync(key, data)
+               }
+
+               got := []expectedData{}
+
+               itr := db.IteratorPrefixWithStart(nil, nil, false)
+               for itr.Next() {
+                       key := itr.Key()
+                       pos := len(ordersPrefix) + assetIDLen*2
+                       b := [32]byte{}
+                       copy(b[:], key[pos+8:])
+                       utxoHash := bc.NewHash(b)
+
+                       rate := getRateFromOrderKey(key, ordersPrefix)
+                       got = append(got, expectedData{
+                               rate:     rate,
+                               utxoHash: utxoHash.String(),
+                       })
+               }
+               itr.Release()
+
+               if !testutil.DeepEqual(c.want, got) {
+                       t.Errorf("case %v: got recovery status, got: %v, want: %v.", i, got, c.want)
+               }
+
+       }
+}
+
+func TestMovStore(t *testing.T) {
+       cases := []struct {
+               desc             string
+               beforeOrders     []*common.Order
+               beforeTradePairs []*common.TradePair
+               beforeDBStatus   *common.MovDatabaseState
+               addOrders        []*common.Order
+               delOrders        []*common.Order
+               blockHeader      *types.BlockHeader
+               wantOrders       []*common.Order
+               wantTradePairs   []*common.TradePair
+               wantDBState      *common.MovDatabaseState
+       }{
+               {
+                       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{
+                                       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: 1, PreviousBlockHash: bc.Hash{V0: 524821139490765641, V1: 2484214155808702787, V2: 9108473449351508820, V3: 7972721253564512122}},
+                       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"),
+                                       },
+                               },
+                       },
+                       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,
+                               },
+                       },
+                       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"),
+                                       },
+                               },
+                       },
+                       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"),
+                                       },
+                               },
+                       },
+                       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{
+                               &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{
+               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.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:        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"),
+                                       },
+                               },
+                       },
+               },
+               {
+                       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"),
+                                       },
+                               },
+                       },
+                       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"),
+                                       },
+                               },
+                       },
+                       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"),
+                                       },
+                               },
+                       },
+               },
+       }
+
+       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)
+               movStore.updateTradePairs(batch, tradePairsCnt)
+               batch.Write()
+
+               tradePairsCnt = make(map[common.TradePair]int)
+               movStore.addOrders(batch, c.addOrders, tradePairsCnt)
+               batch.Write()
+
+               gotOrders, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2})
+               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 TestDelOrders(t *testing.T) {
+       cases := []struct {
+               desc         string
+               beforeOrders []*common.Order
+               delOrders    []*common.Order
+               wantOrders   []*common.Order
+               err          error
+       }{
+               {
+                       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"),
+                                       },
+                               },
+                               &common.Order{
+                                       FromAssetID: assetID1,
+                                       ToAssetID:   assetID2,
+                                       Rate:        0.00090,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 22},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                       },
+                       wantOrders: []*common.Order{},
+                       err:        errors.New("don't find trade pair"),
+               },
+               {
+                       desc: "Delete existing data",
+                       beforeOrders: []*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"),
+                                       },
+                               },
+                       },
+                       delOrders: []*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"),
+                                       },
+                               },
+                       },
+                       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.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:        1.00090,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 21},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                       },
+                       err: nil,
+               },
+               {
+                       desc: "Delete all data",
+                       beforeOrders: []*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.00099,
+                                       Utxo: &common.MovUtxo{
+                                               SourceID:       &bc.Hash{V0: 24},
+                                               Amount:         1,
+                                               SourcePos:      0,
+                                               ControlProgram: []byte("aa"),
+                                       },
+                               },
+                       },
+                       delOrders: []*common.Order{
+                               &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{},
+                       err:        nil,
+               },
+       }
+
+       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)
+               movStore.updateTradePairs(batch, tradePairsCnt)
+               batch.Write()
+
+               tradePairsCnt = make(map[common.TradePair]int)
+               movStore.deleteOrders(batch, c.delOrders, tradePairsCnt)
+               movStore.updateTradePairs(batch, tradePairsCnt)
+               batch.Write()
+
+               gotOrders, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2})
+               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 TestListTradePairsWithStart(t *testing.T) {
+       cases := []struct {
+               desc            string
+               storeTradePairs map[common.TradePair]int
+               query           *common.TradePair
+               wantTradePairs  []*common.TradePair
+       }{
+               {
+                       desc:           "empty",
+                       query:          &common.TradePair{},
+                       wantTradePairs: []*common.TradePair{},
+               },
+               {
+                       desc: "query from first",
+                       storeTradePairs: map[common.TradePair]int{
+                               common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}: 1,
+                               common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}: 2,
+                               common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}: 3,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}: 4,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}: 5,
+                               common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}: 6,
+                       },
+                       query: &common.TradePair{},
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
+                               &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
+                               &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
+                               &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
+                       },
+               },
+               {
+                       desc: "query from middle",
+                       storeTradePairs: map[common.TradePair]int{
+                               common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}: 1,
+                               common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}: 2,
+                               common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}: 3,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}: 4,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}: 5,
+                               common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}: 6,
+                               common.TradePair{FromAssetID: assetID6, ToAssetID: assetID8}: 7,
+                       },
+                       query: &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
+                               &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
+                               &common.TradePair{FromAssetID: assetID6, ToAssetID: assetID8, Count: 7},
+                       },
+               },
+       }
+
+       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()
+               movStore.updateTradePairs(batch, c.storeTradePairs)
+               batch.Write()
+
+               gotTradePairs, err := movStore.ListTradePairsWithStart(c.query.FromAssetID, c.query.ToAssetID)
+               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)
+               }
+
+               testDB.Close()
+               os.RemoveAll("temp")
+       }
+}
+
+func TestUpdateTradePairs(t *testing.T) {
+       cases := []struct {
+               desc             string
+               beforeTradePairs map[common.TradePair]int
+               addTradePairs    map[common.TradePair]int
+               delTradePairs    map[common.TradePair]int
+               wantTradePairs   []*common.TradePair
+       }{
+               {
+                       desc: "empty",
+                       addTradePairs: map[common.TradePair]int{
+                               common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}: 1,
+                               common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}: 2,
+                               common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}: 3,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}: 4,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}: 5,
+                               common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}: 6,
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
+                               &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
+                               &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
+                               &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
+                       },
+               },
+               {
+                       desc: "Stored data already exists",
+                       beforeTradePairs: map[common.TradePair]int{
+                               common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}: 1,
+                               common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}: 2,
+                               common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}: 3,
+                       },
+                       addTradePairs: map[common.TradePair]int{
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}: 4,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}: 5,
+                               common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}: 6,
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
+                               &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
+                               &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
+                               &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
+                       },
+               },
+               {
+                       desc: "delete some data",
+                       beforeTradePairs: map[common.TradePair]int{
+                               common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}: 1,
+                               common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}: 2,
+                               common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}: 3,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}: 4,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}: 5,
+                               common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}: 6,
+                       },
+                       delTradePairs: map[common.TradePair]int{
+                               common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}: -1,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}: -4,
+                               common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}: -2,
+                               common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}: -4,
+                       },
+                       wantTradePairs: []*common.TradePair{
+                               &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
+                               &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
+                               &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 3},
+                               &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 2},
+                       },
+               },
+       }
+
+       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()
+               movStore.updateTradePairs(batch, c.beforeTradePairs)
+               batch.Write()
+
+               movStore.updateTradePairs(batch, c.addTradePairs)
+               movStore.updateTradePairs(batch, c.delTradePairs)
+               batch.Write()
+
+               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)
+               }
+
+               testDB.Close()
+               os.RemoveAll("temp")
+       }
+}
+
+func TestCheckMovDatabaseState(t *testing.T) {
+       cases := []struct {
+               desc           string
+               beforeDBStatus *common.MovDatabaseState
+               blockHeader    *types.BlockHeader
+               err            error
+       }{
+               {
+                       desc:           "attach Block",
+                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       blockHeader:    &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       err:            nil,
+               },
+               {
+                       desc:           "error attach Block",
+                       beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
+                       blockHeader:    &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{}},
+                       err:            errors.New("the status of the block is inconsistent with that of mov-database"),
+               },
+
+               {
+                       desc:           "detach Block",
+                       beforeDBStatus: &common.MovDatabaseState{Height: 5, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
+                       blockHeader:    &types.BlockHeader{Height: 4},
+                       err:            nil,
+               },
+               {
+                       desc:           "error detach Block",
+                       beforeDBStatus: &common.MovDatabaseState{Height: 5, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
+                       blockHeader:    &types.BlockHeader{Height: 3},
+                       err:            errors.New("the status of the block is inconsistent with that of mov-database"),
+               },
+       }
+
+       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()
+               movStore.saveMovDatabaseState(batch, c.beforeDBStatus)
+               batch.Write()
+
+               if err := movStore.checkMovDatabaseState(c.blockHeader); c.err != nil && c.err.Error() != err.Error() {
+                       t.Fatalf("case %d: checkMovDatabaseState error %v.", i, err)
+               }
+
+               testDB.Close()
+               os.RemoveAll("temp")
+       }
+
+}