OSDN Git Service

Add logic implementation
[bytom/vapor.git] / application / dex / database / dex_store.go
index 5fab9a4..a9b5351 100644 (file)
@@ -38,80 +38,73 @@ func calcOrdersKey(fromAssetID, toAssetID *bc.AssetID, utxoHash *bc.Hash, rate f
 }
 
 func calcTradePairKey(fromAssetID, toAssetID *bc.AssetID) []byte {
-       key := append(ordersPreFix, fromAssetID.Bytes()...)
+       key := append(tradePairPreFix, fromAssetID.Bytes()...)
        return append(key, toAssetID.Bytes()...)
 }
 
-type DexTradeOrderDB struct {
+type DexStore struct {
        db dbm.DB
 }
 
-func (d *DexTradeOrderDB) GetTradePairsWithStart(fromAssetID, toAssetID *bc.AssetID) ([]*common.TradePair, error) {
-       startKey := []byte{}
-       if fromAssetID != nil && toAssetID != nil {
-               startKey = calcTradePairKey(fromAssetID, toAssetID)
+func NewDexStore(db dbm.DB) *DexStore {
+       return &DexStore{db: db}
+}
+
+func (d *DexStore) ListOrders(fromAssetID, toAssetID *bc.AssetID, rateAfter float64) ([]*common.Order, error) {
+       if fromAssetID == nil || toAssetID == nil {
+               return nil, errors.New("assetID is nil")
        }
+       ordersPreFixLen := len(ordersPreFix)
+       orders := []*common.Order{}
 
-       tradePairs := []*common.TradePair{}
-       preFixLen := len(tradePairPreFix)
-       itr := d.db.IteratorPrefixWithStart(tradePairPreFix, startKey, false)
+       orderPreFix := append(ordersPreFix, fromAssetID.Bytes()...)
+       orderPreFix = append(orderPreFix, toAssetID.Bytes()...)
+
+       var startKey []byte
+       if rateAfter > 0 {
+               buf := make([]byte, 8)
+               binary.BigEndian.PutUint64(buf, math.Float64bits(rateAfter))
+               copy(startKey, orderPreFix)
+               startKey = append(startKey, buf...)
+       }
+
+       itr := d.db.IteratorPrefixWithStart(orderPreFix, startKey, false)
        defer itr.Release()
 
-       for txNum := tradePairsNum; itr.Next() && txNum > 0; {
+       for txNum := ordersNum; itr.Next() && txNum > 0; {
                key := itr.Key()
                b := [32]byte{}
-               fromAssetIDPos := preFixLen
+               fromAssetIDPos := ordersPreFixLen
                copy(b[:], key[fromAssetIDPos:fromAssetIDPos+32])
                fromAssetID := bc.NewAssetID(b)
 
-               toAssetIDPos := preFixLen + 32
+               toAssetIDPos := ordersPreFixLen + 32
                copy(b[:], key[toAssetIDPos:toAssetIDPos+32])
                toAssetID := bc.NewAssetID(b)
 
-               count := binary.BigEndian.Uint64(itr.Value())
-
-               tradePairs = append(tradePairs, &common.TradePair{FromAssetID: &fromAssetID, ToAssetID: &toAssetID, Count: count})
-
-               txNum--
-       }
-
-       return tradePairs, nil
-}
-
-func (d *DexTradeOrderDB) addTradePair(fromAssetID, toAssetID *bc.AssetID) error {
-       count := uint64(0)
-       key := calcTradePairKey(fromAssetID, toAssetID)
-       if value := d.db.Get(key); value != nil {
-               count = binary.BigEndian.Uint64(value)
-       }
-
-       count++
-
-       value := [8]byte{}
-       binary.BigEndian.PutUint64(value[:], count)
-       d.db.Set(key, value[:])
-       return nil
-}
+               ratePos := ordersPreFixLen + 32*2
+               rate := math.Float64frombits(binary.BigEndian.Uint64(key[ratePos : ratePos+8]))
 
-func (d *DexTradeOrderDB) deleteTradePair(fromAssetID, toAssetID *bc.AssetID) error {
-       key := calcTradePairKey(fromAssetID, toAssetID)
-       if value := d.db.Get(key); value != nil {
-               count := binary.BigEndian.Uint64(value) - 1
+               dexUtxo := &common.DexUtxo{}
+               if err := json.Unmarshal(itr.Value(), dexUtxo); err != nil {
+                       return nil, err
+               }
 
-               if count > 0 {
-                       value := [8]byte{}
-                       binary.BigEndian.PutUint64(value[:], count)
-                       d.db.Set(key, value[:])
-               } else {
-                       d.db.Delete(key)
+               order := &common.Order{
+                       FromAssetID: &fromAssetID,
+                       ToAssetID:   &toAssetID,
+                       Rate:        rate,
+                       Utxo:        dexUtxo,
                }
-               return nil
+
+               orders = append(orders, order)
+               txNum--
        }
 
-       return errors.New("don't find trade pair")
+       return orders, nil
 }
 
-func (d *DexTradeOrderDB) ProcessOrders(addOrders []*common.Order, delOreders []*common.Order, height uint64, blockHash *bc.Hash) error {
+func (d *DexStore) ProcessOrders(addOrders []*common.Order, delOreders []*common.Order, height uint64, blockHash *bc.Hash) error {
        batch := d.db.NewBatch()
 
        if err := d.addOrders(batch, addOrders); err != nil {
@@ -130,104 +123,140 @@ func (d *DexTradeOrderDB) ProcessOrders(addOrders []*common.Order, delOreders []
        return nil
 }
 
-func (d *DexTradeOrderDB) addOrders(batch dbm.Batch, orders []*common.Order) error {
+func (d *DexStore) addOrders(batch dbm.Batch, orders []*common.Order) error {
+       tradePairMap := make(map[common.TradePair]uint64)
        for _, order := range orders {
                data, err := json.Marshal(order.Utxo)
                if err != nil {
                        return err
                }
+
                utxoHash := bc.NewHash(sha3.Sum256(data))
                key := calcOrdersKey(order.FromAssetID, order.ToAssetID, &utxoHash, order.Rate)
                batch.Set(key, data)
 
-               if err := d.addTradePair(order.FromAssetID, order.ToAssetID); err != nil {
-                       return err
+               tradePair := common.TradePair{
+                       FromAssetID: order.FromAssetID,
+                       ToAssetID:   order.ToAssetID,
                }
+               tradePairMap[tradePair] += 1
+       }
+
+       if err := d.addTradePair(batch, tradePairMap); err != nil {
+               return err
        }
        return nil
 }
 
-func (d *DexTradeOrderDB) deleteOrder(batch dbm.Batch, orders []*common.Order) error {
+func (d *DexStore) deleteOrder(batch dbm.Batch, orders []*common.Order) error {
+       tradePairMap := make(map[common.TradePair]uint64)
        for _, order := range orders {
                data, err := json.Marshal(order.Utxo)
                if err != nil {
                        return err
                }
+
                utxoHash := bc.NewHash(sha3.Sum256(data))
                key := calcOrdersKey(order.FromAssetID, order.ToAssetID, &utxoHash, order.Rate)
                batch.Delete(key)
-
-               if err := d.deleteTradePair(order.FromAssetID, order.ToAssetID); err != nil {
-                       return err
+               tradePair := common.TradePair{
+                       FromAssetID: order.FromAssetID,
+                       ToAssetID:   order.ToAssetID,
                }
+               tradePairMap[tradePair] += 1
+       }
+
+       if err := d.deleteTradePair(batch, tradePairMap); err != nil {
+               return err
        }
        return nil
 }
 
-func (d *DexTradeOrderDB) ListOrders(fromAssetID, toAssetID *bc.AssetID, rateAfter float64) ([]*common.Order, error) {
-       ordersPreFixLen := len(ordersPreFix)
-       orders := []*common.Order{}
+func (d *DexStore) GetDexDatabaseState() (*common.DexDatabaseState, error) {
+       value := d.db.Get(bestMatchStore)
+       if value != nil {
+               return nil, errors.New("don't find state of dex-database")
+       }
 
-       orderPreFix := append(ordersPreFix, fromAssetID.Bytes()...)
-       orderPreFix = append(orderPreFix, toAssetID.Bytes()...)
+       state := &common.DexDatabaseState{}
+       if err := json.Unmarshal(value, state); err != nil {
+               return nil, err
+       }
 
-       startKey := []byte{}
-       buf := make([]byte, 8)
-       binary.BigEndian.PutUint64(buf, math.Float64bits(rateAfter))
-       copy(startKey, orderPreFix)
-       startKey = append(startKey, buf...)
+       return state, nil
+}
 
-       itr := d.db.IteratorPrefixWithStart(orderPreFix, startKey, false)
+func (d *DexStore) ListTradePairsWithStart(fromAssetID, toAssetID *bc.AssetID) ([]*common.TradePair, error) {
+       var startKey []byte
+       if fromAssetID != nil && toAssetID != nil {
+               startKey = calcTradePairKey(fromAssetID, toAssetID)
+       }
+
+       tradePairs := []*common.TradePair{}
+       preFixLen := len(tradePairPreFix)
+       itr := d.db.IteratorPrefixWithStart(tradePairPreFix, startKey, false)
        defer itr.Release()
 
-       for txNum := ordersNum; itr.Next() && txNum > 0; {
+       for txNum := tradePairsNum; itr.Next() && txNum > 0; {
                key := itr.Key()
                b := [32]byte{}
-               fromAssetIDPos := ordersPreFixLen
+               fromAssetIDPos := preFixLen
                copy(b[:], key[fromAssetIDPos:fromAssetIDPos+32])
                fromAssetID := bc.NewAssetID(b)
 
-               toAssetIDPos := ordersPreFixLen + 32
+               toAssetIDPos := preFixLen + 32
                copy(b[:], key[toAssetIDPos:toAssetIDPos+32])
                toAssetID := bc.NewAssetID(b)
 
-               ratePos := ordersPreFixLen + 32*2
-               rate := math.Float64frombits(binary.BigEndian.Uint64(key[ratePos : ratePos+8]))
-
-               dexUtxo := &common.DexUtxo{}
-               if err := json.Unmarshal(itr.Value(), dexUtxo); err != nil {
-                       return nil, err
-               }
+               count := binary.BigEndian.Uint64(itr.Value())
 
-               order := &common.Order{
-                       FromAssetID: &fromAssetID,
-                       ToAssetID:   &toAssetID,
-                       Rate:        rate,
-                       Utxo:        dexUtxo,
-               }
+               tradePairs = append(tradePairs, &common.TradePair{FromAssetID: &fromAssetID, ToAssetID: &toAssetID, Count: count})
 
-               orders = append(orders, order)
                txNum--
        }
 
-       return orders, nil
+       return tradePairs, nil
 }
 
-func (d *DexTradeOrderDB) GetDexDatabaseState() (*common.DexDatabaseState, error) {
-       value := d.db.Get(bestMatchStore)
-       if value != nil {
-               return nil, errors.New("don't find state of dex-database")
+func (d *DexStore) addTradePair(batch dbm.Batch, tradePairMap map[common.TradePair]uint64) error {
+       for k, v := range tradePairMap {
+               count := uint64(0)
+               key := calcTradePairKey(k.FromAssetID, k.ToAssetID)
+               if value := d.db.Get(key); value != nil {
+                       count = binary.BigEndian.Uint64(value)
+               }
+
+               count += v
+
+               value := [8]byte{}
+               binary.BigEndian.PutUint64(value[:], count)
+               batch.Set(key, value[:])
        }
+       return nil
+}
 
-       state := &common.DexDatabaseState{}
-       if err := json.Unmarshal(value, state); err != nil {
-               return nil, err
+func (d *DexStore) deleteTradePair(batch dbm.Batch, tradePairMap map[common.TradePair]uint64) error {
+       for k, v := range tradePairMap {
+               key := calcTradePairKey(k.FromAssetID, k.ToAssetID)
+               value := d.db.Get(key)
+               if value == nil {
+                       return errors.New("don't find trade pair")
+               }
+               count := binary.BigEndian.Uint64(value) - v
+
+               if count > 0 {
+                       value := [8]byte{}
+                       binary.BigEndian.PutUint64(value[:], count)
+                       batch.Set(key, value[:])
+               } else {
+                       batch.Delete(key)
+               }
        }
 
-       return state, nil
+       return nil
 }
 
-func (d *DexTradeOrderDB) saveDexDatabaseState(batch dbm.Batch, state *common.DexDatabaseState) error {
+func (d *DexStore) saveDexDatabaseState(batch dbm.Batch, state *common.DexDatabaseState) error {
        value, err := json.Marshal(state)
        if err != nil {
                return err