OSDN Git Service

opt mov validate match tx (#470)
authorPoseidon <shenao.78@163.com>
Tue, 24 Dec 2019 13:49:50 +0000 (21:49 +0800)
committerPaladz <yzhu101@uottawa.ca>
Tue, 24 Dec 2019 13:49:50 +0000 (21:49 +0800)
* opt mov validate match tx

* fix validate trade pair

Co-authored-by: Paladz <yzhu101@uottawa.ca>
application/mov/common/type.go
application/mov/database/mov_iterator_test.go
application/mov/database/mov_store.go
application/mov/database/mov_store_test.go
application/mov/match/match.go
application/mov/match/match_test.go
application/mov/match/order_book.go
application/mov/mock/mock.go
application/mov/mock/mock_mov_store.go
application/mov/mov_core.go

index ba60000..0ea9f28 100644 (file)
@@ -3,6 +3,7 @@ package common
 import (
        "encoding/hex"
        "fmt"
+       "math/big"
 
        "github.com/bytom/vapor/consensus/segwit"
        "github.com/bytom/vapor/errors"
@@ -20,10 +21,21 @@ type MovUtxo struct {
 
 // Order store all the order information
 type Order struct {
-       FromAssetID *bc.AssetID
-       ToAssetID   *bc.AssetID
-       Utxo        *MovUtxo
-       Rate        float64
+       FromAssetID      *bc.AssetID
+       ToAssetID        *bc.AssetID
+       Utxo             *MovUtxo
+       RatioNumerator   int64
+       RatioDenominator int64
+}
+
+func (o *Order) Rate() float64 {
+       if o.RatioDenominator == 0 {
+               return 0
+       }
+       rate := big.NewFloat(0).SetInt64(o.RatioNumerator)
+       rate.Quo(rate, big.NewFloat(0).SetInt64(o.RatioDenominator))
+       result, _ := rate.Float64()
+       return result
 }
 
 // OrderSlice is define for order's sort
@@ -32,10 +44,10 @@ type OrderSlice []*Order
 func (o OrderSlice) Len() int      { return len(o) }
 func (o OrderSlice) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
 func (o OrderSlice) Less(i, j int) bool {
-       if o[i].Rate == o[j].Rate {
+       if o[i].Rate() == o[j].Rate() {
                return hex.EncodeToString(o[i].UTXOHash().Bytes()) < hex.EncodeToString(o[j].UTXOHash().Bytes())
        }
-       return o[i].Rate < o[j].Rate
+       return o[i].Rate() < o[j].Rate()
 }
 
 // NewOrderFromOutput convert txinput to order
@@ -53,9 +65,10 @@ func NewOrderFromOutput(tx *types.Tx, outputIndex int) (*Order, error) {
 
        assetAmount := output.Source.Value
        return &Order{
-               FromAssetID: assetAmount.AssetId,
-               ToAssetID:   &contractArgs.RequestedAsset,
-               Rate:        float64(contractArgs.RatioNumerator) / float64(contractArgs.RatioDenominator),
+               FromAssetID:      assetAmount.AssetId,
+               ToAssetID:        &contractArgs.RequestedAsset,
+               RatioNumerator:   contractArgs.RatioNumerator,
+               RatioDenominator: contractArgs.RatioDenominator,
                Utxo: &MovUtxo{
                        SourceID:       output.Source.Ref,
                        Amount:         assetAmount.Amount,
@@ -78,9 +91,10 @@ func NewOrderFromInput(tx *types.Tx, inputIndex int) (*Order, error) {
        }
 
        return &Order{
-               FromAssetID: input.AssetId,
-               ToAssetID:   &contractArgs.RequestedAsset,
-               Rate:        float64(contractArgs.RatioNumerator) / float64(contractArgs.RatioDenominator),
+               FromAssetID:      input.AssetId,
+               ToAssetID:        &contractArgs.RequestedAsset,
+               RatioNumerator:   contractArgs.RatioNumerator,
+               RatioDenominator: contractArgs.RatioDenominator,
                Utxo: &MovUtxo{
                        SourceID:       &input.SourceID,
                        Amount:         input.Amount,
index 82f57dd..5df84e1 100644 (file)
@@ -15,11 +15,11 @@ var (
        asset3 = bc.NewAssetID([32]byte{3})
        asset4 = bc.NewAssetID([32]byte{4})
 
-       order1 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, Rate: 0.1}
-       order2 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, Rate: 0.2}
-       order3 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, Rate: 0.3}
-       order4 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, Rate: 0.4}
-       order5 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, Rate: 0.5}
+       order1 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 1, RatioDenominator: 10}
+       order2 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 2, RatioDenominator: 10}
+       order3 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 3, RatioDenominator: 10}
+       order4 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 4, RatioDenominator: 10}
+       order5 = &common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 5, RatioDenominator: 10}
 )
 
 func TestTradePairIterator(t *testing.T) {
index 2185072..e9b7183 100644 (file)
@@ -42,6 +42,12 @@ var (
        bestMatchStore   = append(movStore, matchStatus)
 )
 
+type orderData struct {
+       Utxo             *common.MovUtxo
+       RatioNumerator   int64
+       RatioDenominator int64
+}
+
 func calcOrderKey(fromAssetID, toAssetID *bc.AssetID, utxoHash *bc.Hash, rate float64) []byte {
        buf := make([]byte, 8)
        binary.BigEndian.PutUint64(buf, math.Float64bits(rate))
@@ -116,8 +122,8 @@ func (m *LevelDBMovStore) ListOrders(orderAfter *common.Order) ([]*common.Order,
 
        var startKey []byte
 
-       if orderAfter.Rate > 0 {
-               startKey = calcOrderKey(orderAfter.FromAssetID, orderAfter.ToAssetID, orderAfter.UTXOHash(), orderAfter.Rate)
+       if orderAfter.Rate() > 0 {
+               startKey = calcOrderKey(orderAfter.FromAssetID, orderAfter.ToAssetID, orderAfter.UTXOHash(), orderAfter.Rate())
        }
 
        itr := m.db.IteratorPrefixWithStart(orderPrefix, startKey, false)
@@ -125,16 +131,17 @@ func (m *LevelDBMovStore) ListOrders(orderAfter *common.Order) ([]*common.Order,
 
        var orders []*common.Order
        for txNum := 0; txNum < ordersNum && itr.Next(); txNum++ {
-               movUtxo := &common.MovUtxo{}
-               if err := json.Unmarshal(itr.Value(), movUtxo); err != nil {
+               orderData := &orderData{}
+               if err := json.Unmarshal(itr.Value(), orderData); err != nil {
                        return nil, err
                }
 
                orders = append(orders, &common.Order{
-                       FromAssetID: orderAfter.FromAssetID,
-                       ToAssetID:   orderAfter.ToAssetID,
-                       Rate:        getRateFromOrderKey(itr.Key()),
-                       Utxo:        movUtxo,
+                       FromAssetID:      orderAfter.FromAssetID,
+                       ToAssetID:        orderAfter.ToAssetID,
+                       Utxo:             orderData.Utxo,
+                       RatioNumerator:   orderData.RatioNumerator,
+                       RatioDenominator: orderData.RatioDenominator,
                })
        }
        return orders, nil
@@ -198,12 +205,17 @@ func (m *LevelDBMovStore) ProcessOrders(addOrders []*common.Order, delOrders []*
 
 func (m *LevelDBMovStore) addOrders(batch dbm.Batch, orders []*common.Order, tradePairsCnt map[string]*common.TradePair) error {
        for _, order := range orders {
-               data, err := json.Marshal(order.Utxo)
+               orderData := &orderData{
+                       Utxo:             order.Utxo,
+                       RatioNumerator:   order.RatioNumerator,
+                       RatioDenominator: order.RatioDenominator,
+               }
+               data, err := json.Marshal(orderData)
                if err != nil {
                        return err
                }
 
-               key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate)
+               key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate())
                batch.Set(key, data)
 
                tradePair := &common.TradePair{
@@ -250,7 +262,7 @@ func (m *LevelDBMovStore) checkMovDatabaseState(header *types.BlockHeader) error
 
 func (m *LevelDBMovStore) deleteOrders(batch dbm.Batch, orders []*common.Order, tradePairsCnt map[string]*common.TradePair) {
        for _, order := range orders {
-               key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate)
+               key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate())
                batch.Delete(key)
 
                tradePair := &common.TradePair{
index 129706e..aeb9c3f 100644 (file)
@@ -29,9 +29,10 @@ var (
 
        mockOrders = []*common.Order{
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        1.00090,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   100090,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 21},
                                Amount:         1,
@@ -40,9 +41,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00090,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   90,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 22},
                                Amount:         1,
@@ -51,9 +53,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00097,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   97,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 23},
                                Amount:         1,
@@ -62,9 +65,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00098,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   98,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 13},
                                Amount:         1,
@@ -73,9 +77,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00098,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   98,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 24},
                                Amount:         10,
@@ -84,9 +89,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00099,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   99,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 24},
                                Amount:         1,
@@ -95,9 +101,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00096,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 25},
                                Amount:         1,
@@ -106,9 +113,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00095,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   95,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 26},
                                Amount:         1,
@@ -117,9 +125,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        1.00090,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   90,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 1},
                                Amount:         1,
@@ -128,9 +137,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID1,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00090,
+                       FromAssetID:      assetID1,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   90,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 2},
                                Amount:         1,
@@ -139,9 +149,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID3,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00096,
+                       FromAssetID:      assetID3,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 33},
                                Amount:         1,
@@ -150,9 +161,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID4,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00095,
+                       FromAssetID:      assetID4,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   95,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 34},
                                Amount:         1,
@@ -161,9 +173,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID4,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00096,
+                       FromAssetID:      assetID4,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 36},
                                Amount:         1,
@@ -172,9 +185,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID5,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00096,
+                       FromAssetID:      assetID5,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   96,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 37},
                                Amount:         1,
@@ -183,9 +197,10 @@ var (
                        },
                },
                &common.Order{
-                       FromAssetID: assetID6,
-                       ToAssetID:   assetID2,
-                       Rate:        0.00098,
+                       FromAssetID:      assetID6,
+                       ToAssetID:        assetID2,
+                       RatioNumerator:   98,
+                       RatioDenominator: 100000,
                        Utxo: &common.MovUtxo{
                                SourceID:       &bc.Hash{V0: 38},
                                Amount:         1,
@@ -236,9 +251,10 @@ func TestSortOrderKey(t *testing.T) {
                {
                        orders: []*common.Order{
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        1.00090,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   100090,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 21},
                                                Amount:         1,
@@ -247,9 +263,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00090,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   90,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 22},
                                                Amount:         1,
@@ -258,9 +275,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00097,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   97,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 23},
                                                Amount:         1,
@@ -269,9 +287,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 13},
                                                Amount:         1,
@@ -280,9 +299,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 24},
                                                Amount:         10,
@@ -291,9 +311,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 25},
                                                Amount:         10,
@@ -302,9 +323,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 26},
                                                Amount:         10,
@@ -313,9 +335,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00098,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   98,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 27},
                                                Amount:         10,
@@ -324,9 +347,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00099,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   99,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 24},
                                                Amount:         1,
@@ -335,9 +359,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00096,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   96,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 25},
                                                Amount:         1,
@@ -346,9 +371,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00095,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   95,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 26},
                                                Amount:         1,
@@ -357,9 +383,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00091,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   91,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 26},
                                                Amount:         1,
@@ -368,9 +395,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00092,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   92,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 27},
                                                Amount:         1,
@@ -379,9 +407,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00093,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   93,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 28},
                                                Amount:         1,
@@ -390,9 +419,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00094,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   94,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 29},
                                                Amount:         1,
@@ -401,9 +431,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00077,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   77,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 30},
                                                Amount:         1,
@@ -412,9 +443,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        0.00088,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   88,
+                                       RatioDenominator: 100000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 31},
                                                Amount:         1,
@@ -423,9 +455,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        999999.9521,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   9999999521,
+                                       RatioDenominator: 10000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 32},
                                                Amount:         1,
@@ -434,9 +467,10 @@ func TestSortOrderKey(t *testing.T) {
                                        },
                                },
                                &common.Order{
-                                       FromAssetID: &bc.AssetID{V0: 1},
-                                       ToAssetID:   &bc.AssetID{V0: 0},
-                                       Rate:        888888.7954,
+                                       FromAssetID:      &bc.AssetID{V0: 1},
+                                       ToAssetID:        &bc.AssetID{V0: 0},
+                                       RatioNumerator:   8888887954,
+                                       RatioDenominator: 10000,
                                        Utxo: &common.MovUtxo{
                                                SourceID:       &bc.Hash{V0: 33},
                                                Amount:         1,
@@ -528,7 +562,7 @@ func TestSortOrderKey(t *testing.T) {
 
        for i, c := range cases {
                for _, order := range c.orders {
-                       key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate)
+                       key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate())
                        data, err := json.Marshal(order.Utxo)
                        if err != nil {
                                t.Fatal(err)
@@ -674,7 +708,7 @@ func TestMovStore(t *testing.T) {
                        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
+                       desc: "Add and delete the same trade pair", // Add and delete different transaction pairs
                        beforeOrders: []*common.Order{
                                mockOrders[0],
                                mockOrders[1],
@@ -816,35 +850,35 @@ func TestMovStore(t *testing.T) {
 
                var gotOrders []*common.Order
 
-               tmp, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2, Rate: 0})
+               tmp, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
                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})
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID3, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
                if err != nil {
                        t.Fatalf("case %d: ListOrders(assetID3 and assetID2)  error %v.", i, err)
                }
 
                gotOrders = append(gotOrders, tmp...)
 
-               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID4, ToAssetID: assetID2, Rate: 0})
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID4, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
                if err != nil {
                        t.Fatalf("case %d: ListOrders(assetID4 and assetID2)  error %v.", i, err)
                }
 
                gotOrders = append(gotOrders, tmp...)
 
-               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID5, ToAssetID: assetID2, Rate: 0})
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID5, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
                if err != nil {
                        t.Fatalf("case %d: ListOrders(assetID5 and assetID2)  error %v.", i, err)
                }
 
                gotOrders = append(gotOrders, tmp...)
 
-               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID6, ToAssetID: assetID2, Rate: 0})
+               tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID6, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
                if err != nil {
                        t.Fatalf("case %d: ListOrders(assetID6 and assetID2)  error %v.", i, err)
                }
index f506cf7..4c0234f 100644 (file)
@@ -34,12 +34,12 @@ func (e *Engine) HasMatchedTx(tradePairs ...*common.TradePair) bool {
                return false
        }
 
-       orders := e.peekOrders(tradePairs)
+       orders := e.orderBook.PeekOrders(tradePairs)
        if len(orders) == 0 {
                return false
        }
 
-       return isMatched(orders)
+       return IsMatched(orders)
 }
 
 // NextMatchedTx return the next matchable transaction by the specified trade pairs
@@ -50,7 +50,7 @@ func (e *Engine) NextMatchedTx(tradePairs ...*common.TradePair) (*types.Tx, erro
                return nil, errors.New("the specified trade pairs can not be matched")
        }
 
-       tx, err := e.buildMatchTx(e.peekOrders(tradePairs))
+       tx, err := e.buildMatchTx(sortOrders(e.orderBook.PeekOrders(tradePairs)))
        if err != nil {
                return nil, err
        }
@@ -145,19 +145,6 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) {
        return types.NewTx(*txData), nil
 }
 
-func (e *Engine) peekOrders(tradePairs []*common.TradePair) []*common.Order {
-       var orders []*common.Order
-       for _, tradePair := range tradePairs {
-               order := e.orderBook.PeekOrder(tradePair)
-               if order == nil {
-                       return nil
-               }
-
-               orders = append(orders, order)
-       }
-       return orders
-}
-
 // MatchedTxFee is object to record the mov tx's fee information
 type MatchedTxFee struct {
        MaxFeeAmount int64
@@ -247,13 +234,26 @@ func calcOppositeIndex(size int, selfIdx int) int {
        return (selfIdx + 1) % size
 }
 
-func isMatched(orders []*common.Order) bool {
-       rate := orders[0].Rate
-       oppositeRate := 1.0
-       for i := 1; i < len(orders); i++ {
-               oppositeRate *= orders[i].Rate
+func IsMatched(orders []*common.Order) bool {
+       sortedOrders := sortOrders(orders)
+       if len(sortedOrders) == 0 {
+               return false
+       }
+
+       rate := orderRatio(sortedOrders[0])
+       oppositeRate := big.NewFloat(0).SetInt64(1)
+       for i := 1; i < len(sortedOrders); i++ {
+               oppositeRate.Mul(oppositeRate, orderRatio(sortedOrders[i]))
        }
-       return 1/rate >= oppositeRate
+
+       one := big.NewFloat(0).SetInt64(1)
+       return one.Quo(one, rate).Cmp(oppositeRate) >= 0
+}
+
+func orderRatio(order *common.Order) *big.Float {
+       ratio := big.NewFloat(0).SetInt64(order.RatioNumerator)
+       ratio.Quo(ratio, big.NewFloat(0).SetInt64(order.RatioDenominator))
+       return ratio
 }
 
 func setMatchTxArguments(txInput *types.TxInput, isPartialTrade bool, position int, receiveAmounts uint64) {
@@ -271,15 +271,40 @@ func validateTradePairs(tradePairs []*common.TradePair) error {
                return errors.New("size of trade pairs at least 2")
        }
 
-       for i, tradePair := range tradePairs {
+       assetMap := make(map[string]bool)
+       for _, tradePair := range tradePairs {
+               assetMap[tradePair.FromAssetID.String()] = true
                if *tradePair.FromAssetID == *tradePair.ToAssetID {
                        return errors.New("from asset id can't equal to asset id")
                }
+       }
 
-               oppositeTradePair := tradePairs[calcOppositeIndex(len(tradePairs), i)]
-               if *tradePair.ToAssetID != *oppositeTradePair.FromAssetID {
-                       return errors.New("specified trade pairs is invalid")
+       for _, tradePair := range tradePairs {
+               key := tradePair.ToAssetID.String()
+               if _, ok := assetMap[key]; !ok {
+                       return errors.New("invalid trade pairs")
                }
+               delete(assetMap, key)
        }
        return nil
 }
+
+func sortOrders(orders []*common.Order) []*common.Order {
+       orderMap := make(map[bc.AssetID]*common.Order)
+       firstOrder := orders[0]
+       for i := 1; i < len(orders); i++ {
+               orderMap[*orders[i].FromAssetID] = orders[i]
+       }
+
+       sortedOrders := []*common.Order{firstOrder}
+       for order := firstOrder; *order.ToAssetID != *firstOrder.FromAssetID; {
+               nextOrder, ok := orderMap[*order.ToAssetID]
+               if !ok {
+                       return nil
+               }
+
+               sortedOrders = append(sortedOrders, nextOrder)
+               order = nextOrder
+       }
+       return sortedOrders
+}
index a73e62d..640f4cf 100644 (file)
@@ -226,7 +226,7 @@ func TestValidateTradePairs(t *testing.T) {
                        wantError: true,
                },
                {
-                       desc: "invalid case 2 of three trade pairs",
+                       desc: "valid case 2 of three trade pairs",
                        tradePairs: []*common.TradePair{
                                {
                                        FromAssetID: &mock.BTC,
@@ -241,7 +241,7 @@ func TestValidateTradePairs(t *testing.T) {
                                        ToAssetID:   &mock.EOS,
                                },
                        },
-                       wantError: true,
+                       wantError: false,
                },
        }
 
index ebfa27c..f4cd852 100644 (file)
@@ -38,7 +38,7 @@ func NewOrderBook(movStore database.MovStore, arrivalAddOrders, arrivalDelOrders
 func (o *OrderBook) AddOrder(order *common.Order) error {
        tradePairKey := order.TradePair().Key()
        orders := o.arrivalAddOrders[tradePairKey]
-       if len(orders) > 0 && order.Rate > orders[len(orders)-1].Rate {
+       if len(orders) > 0 && order.Rate() > orders[len(orders)-1].Rate() {
                return errors.New("rate of order must less than the min order in order table")
        }
 
@@ -64,12 +64,26 @@ func (o *OrderBook) PeekOrder(tradePair *common.TradePair) *common.Order {
        }
 
        arrivalOrder := o.peekArrivalOrder(tradePair)
-       if nextOrder == nil || (arrivalOrder != nil && arrivalOrder.Rate < nextOrder.Rate) {
+       if nextOrder == nil || (arrivalOrder != nil && arrivalOrder.Rate() < nextOrder.Rate()) {
                nextOrder = arrivalOrder
        }
        return nextOrder
 }
 
+// PeekOrders return the next lowest orders by given array of trade pairs
+func (o *OrderBook) PeekOrders(tradePairs []*common.TradePair) []*common.Order {
+       var orders []*common.Order
+       for _, tradePair := range tradePairs {
+               order := o.PeekOrder(tradePair)
+               if order == nil {
+                       return nil
+               }
+
+               orders = append(orders, order)
+       }
+       return orders
+}
+
 // PopOrder delete the next lowest order of given trade pair
 func (o *OrderBook) PopOrder(tradePair *common.TradePair) {
        order := o.PeekOrder(tradePair)
@@ -88,6 +102,15 @@ func (o *OrderBook) PopOrder(tradePair *common.TradePair) {
        }
 }
 
+// PopOrders delete the next lowest orders by given trade pairs
+func (o *OrderBook) PopOrders(tradePairs []*common.TradePair) []*common.Order {
+       var orders []*common.Order
+       for _, tradePair := range tradePairs {
+               o.PopOrder(tradePair)
+       }
+       return orders
+}
+
 func arrangeArrivalAddOrders(orders []*common.Order) map[string][]*common.Order {
        arrivalAddOrderMap := make(map[string][]*common.Order)
        for _, order := range orders {
index cb648e9..b810795 100644 (file)
@@ -18,9 +18,10 @@ var (
 
        Btc2EthOrders = []*common.Order{
                {
-                       FromAssetID: &BTC,
-                       ToAssetID:   &ETH,
-                       Rate:        50,
+                       FromAssetID:      &BTC,
+                       ToAssetID:        &ETH,
+                       RatioNumerator:   50,
+                       RatioDenominator: 1,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("37b8edf656e45a7addf47f5626e114a8c394d918a36f61b5a2905675a09b40ae")),
                                SourcePos:      0,
@@ -29,9 +30,10 @@ var (
                        },
                },
                {
-                       FromAssetID: &BTC,
-                       ToAssetID:   &ETH,
-                       Rate:        53,
+                       FromAssetID:      &BTC,
+                       ToAssetID:        &ETH,
+                       RatioNumerator:   53,
+                       RatioDenominator: 1,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("3ec2bbfb499a8736d377b547eee5392bcddf7ec2b287e9ed20b5938c3d84e7cd")),
                                SourcePos:      0,
@@ -40,9 +42,10 @@ var (
                        },
                },
                {
-                       FromAssetID: &BTC,
-                       ToAssetID:   &ETH,
-                       Rate:        52,
+                       FromAssetID:      &BTC,
+                       ToAssetID:        &ETH,
+                       RatioNumerator:   52,
+                       RatioDenominator: 1,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("1232bbfb499a8736d377b547eee5392bcddf7ec2b287e9ed20b5938c3d84e7cd")),
                                SourcePos:      0,
@@ -51,9 +54,10 @@ var (
                        },
                },
                {
-                       FromAssetID: &BTC,
-                       ToAssetID:   &ETH,
-                       Rate:        49,
+                       FromAssetID:      &BTC,
+                       ToAssetID:        &ETH,
+                       RatioNumerator:   49,
+                       RatioDenominator: 1,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("7872bbfb499a8736d377b547eee5392bcddf7ec2b287e9ed20b5938c3d84e7cd")),
                                SourcePos:      0,
@@ -65,9 +69,10 @@ var (
 
        Eth2BtcOrders = []*common.Order{
                {
-                       FromAssetID: &ETH,
-                       ToAssetID:   &BTC,
-                       Rate:        1 / 51.0,
+                       FromAssetID:      &ETH,
+                       ToAssetID:        &BTC,
+                       RatioNumerator:   1,
+                       RatioDenominator: 51,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("fba43ff5155209cb1769e2ec0e1d4a33accf899c740865edfc6d1de39b873b29")),
                                SourcePos:      0,
@@ -76,9 +81,10 @@ var (
                        },
                },
                {
-                       FromAssetID: &ETH,
-                       ToAssetID:   &BTC,
-                       Rate:        1 / 52.0,
+                       FromAssetID:      &ETH,
+                       ToAssetID:        &BTC,
+                       RatioNumerator:   1,
+                       RatioDenominator: 52,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("05f24bb847db823075d81786aa270748e02602199cd009c0284f928503846a5a")),
                                SourcePos:      0,
@@ -87,9 +93,10 @@ var (
                        },
                },
                {
-                       FromAssetID: &ETH,
-                       ToAssetID:   &BTC,
-                       Rate:        1 / 54.0,
+                       FromAssetID:      &ETH,
+                       ToAssetID:        &BTC,
+                       RatioNumerator:   1,
+                       RatioDenominator: 54,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("119a02980796dc352cf6475457463aef5666f66622088de3551fa73a65f0d201")),
                                SourcePos:      0,
@@ -101,9 +108,10 @@ var (
 
        Eos2EtcOrders = []*common.Order{
                {
-                       FromAssetID: &EOS,
-                       ToAssetID:   &ETC,
-                       Rate:        1 / 2.0,
+                       FromAssetID:      &EOS,
+                       ToAssetID:        &ETC,
+                       RatioNumerator:   1,
+                       RatioDenominator: 2,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("119a02980796dc352cf6475457463aef5666f66622088de3551fa73a65f0d202")),
                                SourcePos:      0,
@@ -115,9 +123,10 @@ var (
 
        Etc2EosOrders = []*common.Order{
                {
-                       FromAssetID: &ETC,
-                       ToAssetID:   &EOS,
-                       Rate:        2.0,
+                       FromAssetID:      &ETC,
+                       ToAssetID:        &EOS,
+                       RatioNumerator:   2,
+                       RatioDenominator: 1,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("119a02980796dc352cf6475457463aef5666f66622088de3551fa73a65f0d203")),
                                SourcePos:      0,
@@ -129,9 +138,10 @@ var (
 
        Eth2EosOrders = []*common.Order{
                {
-                       FromAssetID: &ETH,
-                       ToAssetID:   &EOS,
-                       Rate:        2.0,
+                       FromAssetID:      &ETH,
+                       ToAssetID:        &EOS,
+                       RatioNumerator:   2,
+                       RatioDenominator: 1,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("c1502d03946e4ea92abdb33f51638b181839bd0d8767acc2ee5c665b659c4b13")),
                                SourcePos:      0,
@@ -143,9 +153,10 @@ var (
 
        Eos2BtcOrders = []*common.Order{
                {
-                       FromAssetID: &EOS,
-                       ToAssetID:   &BTC,
-                       Rate:        1 / 100.0,
+                       FromAssetID:      &EOS,
+                       ToAssetID:        &BTC,
+                       RatioNumerator:   1,
+                       RatioDenominator: 100,
                        Utxo: &common.MovUtxo{
                                SourceID:       hashPtr(testutil.MustDecodeHash("27cf8a0877dc858968cc06396fe6aa9e02d15f3e44c862fe29fa5fd50497cf20")),
                                SourcePos:      0,
index a28fdf5..34a1bd0 100644 (file)
@@ -42,11 +42,11 @@ func (m *MovStore) ListOrders(orderAfter *common.Order) ([]*common.Order, error)
        tradePair := &common.TradePair{FromAssetID: orderAfter.FromAssetID, ToAssetID: orderAfter.ToAssetID}
        orders := m.orderMap[tradePair.Key()]
        begin := len(orders)
-       if orderAfter.Rate == 0 {
+       if orderAfter.Rate() == 0 {
                begin = 0
        } else {
                for i, order := range orders {
-                       if order.Rate == orderAfter.Rate {
+                       if order.Rate() == orderAfter.Rate() {
                                begin = i + 1
                                break
                        }
index 529f8ab..3c60e16 100644 (file)
@@ -23,9 +23,9 @@ var (
        errAmountOfFeeGreaterThanMaximum = errors.New("amount of fee greater than max fee amount")
        errAssetIDMustUniqueInMatchedTx  = errors.New("asset id must unique in matched transaction")
        errRatioOfTradeLessThanZero      = errors.New("ratio arguments must greater than zero")
-       errLengthOfInputIsIncorrect      = errors.New("length of matched tx input is not equals to actual matched tx input")
        errSpendOutputIDIsIncorrect      = errors.New("spend output id of matched tx is not equals to actual matched tx")
        errRequestAmountMath             = errors.New("request amount of order less than one or big than max of int64")
+       errNotMatchedOrder               = errors.New("order in matched tx is not matched")
 )
 
 // MovCore represent the core logic of the match module, which include generate match transactions before packing the block,
@@ -69,11 +69,6 @@ func (m *MovCore) ApplyBlock(block *types.Block) error {
        return m.movStore.ProcessOrders(addOrders, deleteOrders, &block.BlockHeader)
 }
 
-/*
-       @issue: I have two orders A and B, order A's seller program is order B and order B's seller program is order A.
-    Assume consensus node accept 0% fee and This two orders are the only two order of this trading pair, will this
-    become an infinite loop and DDoS attacks the whole network?
-*/
 // BeforeProposalBlock return all transactions than can be matched, and the number of transactions cannot exceed the given capacity.
 func (m *MovCore) BeforeProposalBlock(txs []*types.Tx, nodeProgram []byte, blockHeight uint64, gasLeft int64, isTimeout func() bool) ([]*types.Tx, error) {
        if blockHeight <= m.startBlockHeight {
@@ -287,59 +282,72 @@ func validateMatchedTxFeeAmount(tx *types.Tx) error {
        return nil
 }
 
-/*
-       @issue: the match package didn't support circle yet
-*/
 func (m *MovCore) validateMatchedTxSequence(txs []*types.Tx) error {
        orderBook, err := buildOrderBook(m.movStore, txs)
        if err != nil {
                return err
        }
 
-       matchEngine := match.NewEngine(orderBook, maxFeeRate, nil)
        for _, matchedTx := range txs {
                if !common.IsMatchedTx(matchedTx) {
                        continue
                }
 
-               tradePairs, err := getSortedTradePairsFromMatchedTx(matchedTx)
+               tradePairs, err := getTradePairsFromMatchedTx(matchedTx)
                if err != nil {
                        return err
                }
 
-               actualMatchedTx, err := matchEngine.NextMatchedTx(tradePairs...)
-               if err != nil {
-                       return err
+               orders := orderBook.PeekOrders(tradePairs)
+               if !match.IsMatched(orders) {
+                       return errNotMatchedOrder
                }
 
-               if len(matchedTx.Inputs) != len(actualMatchedTx.Inputs) {
-                       return errLengthOfInputIsIncorrect
+               if err := validateSpendOrders(matchedTx, orders); err != nil {
+                       return err
                }
 
-               spendOutputIDs := make(map[string]bool)
-               for _, input := range matchedTx.Inputs {
-                       spendOutputID, err := input.SpentOutputID()
-                       if err != nil {
-                               return err
-                       }
+               orderBook.PopOrders(tradePairs)
 
-                       spendOutputIDs[spendOutputID.String()] = true
-               }
+               for i, output := range matchedTx.Outputs {
+                       if !segwit.IsP2WMCScript(output.ControlProgram()) {
+                               continue
+                       }
 
-               for _, input := range actualMatchedTx.Inputs {
-                       spendOutputID, err := input.SpentOutputID()
+                       order, err := common.NewOrderFromOutput(matchedTx, i)
                        if err != nil {
                                return err
                        }
 
-                       if _, ok := spendOutputIDs[spendOutputID.String()]; !ok {
-                               return errSpendOutputIDIsIncorrect
+                       if err := orderBook.AddOrder(order); err != nil {
+                               return err
                        }
                }
        }
        return nil
 }
 
+
+func validateSpendOrders(matchedTx *types.Tx, orders []*common.Order) error {
+       spendOutputIDs := make(map[string]bool)
+       for _, input := range matchedTx.Inputs {
+               spendOutputID, err := input.SpentOutputID()
+               if err != nil {
+                       return err
+               }
+
+               spendOutputIDs[spendOutputID.String()] = true
+       }
+
+       for _, order := range orders {
+               outputID := order.UTXOHash().String()
+               if _, ok := spendOutputIDs[outputID]; !ok {
+                       return errSpendOutputIDIsIncorrect
+               }
+       }
+       return nil
+}
+
 func applyTransactions(txs []*types.Tx) ([]*common.Order, []*common.Order, error) {
        deleteOrderMap := make(map[string]*common.Order)
        addOrderMap := make(map[string]*common.Order)
@@ -367,9 +375,6 @@ func applyTransactions(txs []*types.Tx) ([]*common.Order, []*common.Order, error
        return addOrders, deleteOrders, nil
 }
 
-/*
-       @issue: if consensus node packed match transaction first then packed regular tx, this function's logic may make a valid block invalid
-*/
 func buildOrderBook(store database.MovStore, txs []*types.Tx) (*match.OrderBook, error) {
        var nonMatchedTxs []*types.Tx
        for _, tx := range txs {
@@ -435,34 +440,15 @@ func getDeleteOrdersFromTx(tx *types.Tx) ([]*common.Order, error) {
        return orders, nil
 }
 
-func getSortedTradePairsFromMatchedTx(tx *types.Tx) ([]*common.TradePair, error) {
-       assetMap := make(map[bc.AssetID]bc.AssetID)
-       var firstTradePair *common.TradePair
+func getTradePairsFromMatchedTx(tx *types.Tx) ([]*common.TradePair, error) {
+       var tradePairs []*common.TradePair
        for _, tx := range tx.Inputs {
                contractArgs, err := segwit.DecodeP2WMCProgram(tx.ControlProgram())
                if err != nil {
                        return nil, err
                }
 
-               assetMap[tx.AssetID()] = contractArgs.RequestedAsset
-               if firstTradePair == nil {
-                       firstTradePair = &common.TradePair{FromAssetID: tx.AssetAmount().AssetId, ToAssetID: &contractArgs.RequestedAsset}
-               }
-       }
-
-       tradePairs := []*common.TradePair{firstTradePair}
-       for tradePair := firstTradePair; *tradePair.ToAssetID != *firstTradePair.FromAssetID; {
-               nextTradePairToAssetID, ok := assetMap[*tradePair.ToAssetID]
-               if !ok {
-                       return nil, errInvalidTradePairs
-               }
-
-               tradePair = &common.TradePair{FromAssetID: tradePair.ToAssetID, ToAssetID: &nextTradePairToAssetID}
-               tradePairs = append(tradePairs, tradePair)
-       }
-
-       if len(tradePairs) != len(tx.Inputs) {
-               return nil, errInvalidTradePairs
+               tradePairs = append(tradePairs, &common.TradePair{FromAssetID: tx.AssetAmount().AssetId, ToAssetID: &contractArgs.RequestedAsset})
        }
        return tradePairs, nil
 }