X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=application%2Fdex%2Fdatabase%2Fdex_store.go;fp=application%2Fdex%2Fdatabase%2Fdex_store.go;h=a9b53511fc71be846c4988d8dd20f10e1ac9f0c1;hb=892ea3f5ac43e1205a27e602b653ff394dd936a5;hp=5fab9a4e807912bc71382cc20cc132b54196d82c;hpb=33473e3c1d65186bea96497d96be2cf730908d73;p=bytom%2Fvapor.git diff --git a/application/dex/database/dex_store.go b/application/dex/database/dex_store.go index 5fab9a4e..a9b53511 100644 --- a/application/dex/database/dex_store.go +++ b/application/dex/database/dex_store.go @@ -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