Skip to content

Commit

Permalink
Merge pull request ethereum#522 from ngtuna/tomoX-backup
Browse files Browse the repository at this point in the history
correct insert order flow, error handling
  • Loading branch information
ngtuna authored May 29, 2019
2 parents 4119577 + c55b6b2 commit 25510ca
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 69 deletions.
57 changes: 37 additions & 20 deletions tomox/orderbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type OrderBook struct {
Item *OrderBookItem

Key []byte
slot *big.Int
Slot *big.Int
}

// NewOrderBook : return new order book
Expand Down Expand Up @@ -88,7 +88,7 @@ func NewOrderBook(name string, db OrderDao) *OrderBook {
orderBook := &OrderBook{
db: db,
Item: item,
slot: slot,
Slot: slot,
Key: key,
}

Expand All @@ -111,8 +111,14 @@ func NewOrderBook(name string, db OrderDao) *OrderBook {

func (orderBook *OrderBook) Save() error {

orderBook.Asks.Save()
orderBook.Bids.Save()
if err := orderBook.Asks.Save(); err != nil {
log.Error("can't save orderbook asks", "err", err)
return err
}
if err := orderBook.Bids.Save(); err != nil {
log.Error("can't save orderbook bids", "err", err)
return err
}

return orderBook.db.Put(orderBook.Key, orderBook.Item)
}
Expand All @@ -123,8 +129,22 @@ func (orderBook *OrderBook) Commit() error {
}

func (orderBook *OrderBook) Restore() error {
orderBook.Asks.Restore()
orderBook.Bids.Restore()
if err := orderBook.Asks.Restore(); err != nil {
log.Error("can't restore orderbook asks", "err", err)
return err
}
if err := orderBook.Bids.Restore(); err != nil {
log.Error("can't restore orderbook bids", "err", err)
return err
}
if err := orderBook.PendingAsks.Restore(); err != nil {
log.Error("can't restore orderbook pending asks", "err", err)
return err
}
if err := orderBook.PendingBids.Restore(); err != nil {
log.Error("can't restore orderbook pending bids", "err", err)
return err
}

val, err := orderBook.db.Get(orderBook.Key, orderBook.Item)
if err == nil {
Expand All @@ -136,12 +156,12 @@ func (orderBook *OrderBook) Restore() error {

func (orderBook *OrderBook) GetOrderIDFromBook(key []byte) uint64 {
orderSlot := new(big.Int).SetBytes(key)
return Sub(orderSlot, orderBook.slot).Uint64()
return Sub(orderSlot, orderBook.Slot).Uint64()
}

func (orderBook *OrderBook) GetOrderIDFromKey(key []byte) []byte {
orderSlot := new(big.Int).SetBytes(key)
return common.BigToHash(Add(orderBook.slot, orderSlot)).Bytes()
return common.BigToHash(Add(orderBook.Slot, orderSlot)).Bytes()
}

func (orderBook *OrderBook) GetOrder(key []byte) *Order {
Expand Down Expand Up @@ -361,8 +381,7 @@ func (orderBook *OrderBook) CancelOrder(order *OrderItem) error {
return fmt.Errorf("Can't cancel order as it doesn't exist - order: %v", order)
}
orderInDB.Item.Status = Cancel
_, err = orderBook.Bids.RemoveOrder(orderInDB)
if err != nil {
if err := orderBook.Bids.RemoveOrder(orderInDB); err != nil {
return err
}
} else {
Expand All @@ -371,8 +390,7 @@ func (orderBook *OrderBook) CancelOrder(order *OrderItem) error {
return fmt.Errorf("Can't cancel order as it doesn't exist - order: %v", order)
}
orderInDB.Item.Status = Cancel
_, err = orderBook.Asks.RemoveOrder(orderInDB)
if err != nil {
if err = orderBook.Asks.RemoveOrder(orderInDB); err != nil {
return err
}
}
Expand Down Expand Up @@ -426,27 +444,26 @@ func (orderBook *OrderBook) VolumeAtPrice(side string, price *big.Int) *big.Int

// Save order pending into orderbook tree.
func (orderBook *OrderBook) SaveOrderPending(order *OrderItem) error {
quantityToTrade := order.Quantity
side := order.Side
zero := Zero()

orderBook.UpdateTime()
// if we do not use auto-increment orderid, we must set price slot to avoid conflict
orderBook.Item.NextOrderID++

if side == Bid {
if quantityToTrade.Cmp(zero) > 0 {
if order.Side == Bid {
if order.Quantity.Cmp(zero) > 0 {
order.OrderID = orderBook.Item.NextOrderID
order.Quantity = quantityToTrade
return orderBook.PendingBids.InsertOrder(order)
}
} else {
if quantityToTrade.Cmp(zero) > 0 {
if order.Quantity.Cmp(zero) > 0 {
order.OrderID = orderBook.Item.NextOrderID
order.Quantity = quantityToTrade
return orderBook.PendingAsks.InsertOrder(order)
}
}
// save changes to orderbook
if err := orderBook.Save(); err != nil {
return err
}

return nil
}
11 changes: 6 additions & 5 deletions tomox/orderlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func NewOrderListWithItem(item *OrderListItem, orderTree *OrderTree) *OrderList
// priceKey will be slot of order tree + plus price key
// we can use orderList slot as orderbook slot to store sequential of orders
if orderTree.orderBook != nil {
orderList.slot = orderTree.orderBook.slot
orderList.slot = orderTree.orderBook.Slot
} else {
orderList.slot = new(big.Int).SetBytes(crypto.Keccak256(key))
}
Expand Down Expand Up @@ -213,8 +213,7 @@ func (orderList *OrderList) AppendOrder(order *Order) error {
}

// save into database first
err := orderList.SaveOrder(order)
if err != nil {
if err := orderList.SaveOrder(order); err != nil {
return err
}

Expand All @@ -226,12 +225,14 @@ func (orderList *OrderList) AppendOrder(order *Order) error {
if tailOrder != nil {
tailOrder.Item.NextOrder = order.Key
orderList.Item.TailOrder = order.Key
orderList.SaveOrder(tailOrder)
if err := orderList.SaveOrder(tailOrder); err != nil {
return err
}
}
}
orderList.Item.Length++
orderList.Item.Volume = Add(orderList.Item.Volume, order.Item.Quantity)
return orderList.Save()
return nil
}

func (orderList *OrderList) DeleteOrder(order *Order) error {
Expand Down
42 changes: 25 additions & 17 deletions tomox/ordertree.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ func (orderTree *OrderTree) OrderExist(key []byte, price *big.Int) bool {
return orderList.OrderExist(key)
}

// InsertOrder : insert new order using quote data as map
func (orderTree *OrderTree) InsertOrder(order *OrderItem) error {

price := order.Price
Expand All @@ -220,30 +219,41 @@ func (orderTree *OrderTree) InsertOrder(order *OrderItem) error {

if !orderTree.PriceExist(price) {
// create and save
log.Debug("CREATE price list", "price list", price.String())
log.Debug("create price list", "detail", price.String())
orderList = orderTree.CreatePrice(price)
} else {
orderList = orderTree.PriceList(price)
}

// order will be insert if there is a follow orderList key
// order will be inserted to order list
if orderList != nil {

order := NewOrder(order, orderList.Key)

if orderList.OrderExist(order.Key) {
orderTree.RemoveOrder(order)
if err := orderTree.RemoveOrder(order); err != nil {
return err
}
}

// append order to order list
if err := orderList.AppendOrder(order); err != nil {
return err
}

orderList.AppendOrder(order)
orderList.Save()
orderList.SaveOrder(order)
// snapshot order list
if err := orderList.Save(); err != nil {
return err
}
orderTree.Item.Volume = Add(orderTree.Item.Volume, order.Item.Quantity)

// increase num of orders, should be big.Int ?
// increase num of orders. FIXME: should be big.Int ?
orderTree.Item.NumOrders++

return orderTree.Save()
// finally, snapshot order tree
if err := orderTree.Save(); err != nil {
return err
}
}

return nil
Expand Down Expand Up @@ -310,18 +320,16 @@ func (orderTree *OrderTree) RemoveOrderFromOrderList(order *Order, orderList *Or
return orderTree.Save()
}

func (orderTree *OrderTree) RemoveOrder(order *Order) (*OrderList, error) {
var err error
// get orderList by price, if there is orderlist, we will update it
func (orderTree *OrderTree) RemoveOrder(order *Order) (error) {
// get orderList by price. If there is orderlist existed, update it
orderList := orderTree.PriceList(order.Item.Price)
if orderList != nil {

err = orderTree.RemoveOrderFromOrderList(order, orderList)

if err := orderTree.RemoveOrderFromOrderList(order, orderList); err != nil {
return err
}
}

return orderList, err

return nil
}

func (orderTree *OrderTree) getOrderListItem(bytes []byte) *OrderListItem {
Expand Down
57 changes: 30 additions & 27 deletions tomox/tomox.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/sync/syncmap"
"gopkg.in/fatih/set.v0"
"math/big"
)

const (
Expand Down Expand Up @@ -427,20 +429,17 @@ func (tomox *TomoX) postEvent(envelope *Envelope, isP2P bool) error {
}

if order.Status == Cancel {
err := tomox.CancelOrder(order)
if err != nil {
log.Error("Can't cancel order", "err", err)
if err := tomox.CancelOrder(order); err != nil {
log.Error("Can't cancel order", "order", order, "err", err)
return err
}
log.Debug("Cancelled order", "detail", order)
log.Debug("Cancelled order", "order", order)
} else {
log.Info("Save order", "detail", order)
trades, orderInBook, err := tomox.ProcessOrder(order)
if err != nil {
log.Error("Can't process order", "err", err)
if err := tomox.InsertOrder(order); err != nil {
log.Error("Can't insert order", "order", order, "err", err)
return err
}
log.Info("Orderbook result", "Trade", trades, "OrderInBook", orderInBook)
log.Debug("Inserted order", "order", order)
}
return nil
}
Expand Down Expand Up @@ -592,10 +591,18 @@ func (tomox *TomoX) getAndCreateIfNotExisted(pairName string) (*OrderBook, error
if !tomox.hasOrderBook(name) {
// then create one
ob := NewOrderBook(name, tomox.db)
if ob != nil {
ob.Restore()
tomox.Orderbooks[name] = ob
tomox.Orderbooks[name] = ob
} else {
key := crypto.Keccak256([]byte(strings.ToLower(pairName)))
slot := new(big.Int).SetBytes(key)
ob := &OrderBook{
Key: key,
Slot: slot,
}
if err := ob.Restore(); err != nil {
return nil, err
}
tomox.Orderbooks[name] = ob
}

// return from map
Expand All @@ -611,33 +618,29 @@ func (tomox *TomoX) GetOrder(pairName, orderID string) *Order {
return ob.GetOrder(key)
}

func (tomox *TomoX) ProcessOrder(order *OrderItem) ([]map[string]string, *OrderItem, error) {
ob, _ := tomox.getAndCreateIfNotExisted(order.PairName)
var trades []map[string]string
var orderInBook *OrderItem
func (tomox *TomoX) InsertOrder(order *OrderItem) (error) {
ob, err := tomox.getAndCreateIfNotExisted(order.PairName)
if err != nil {
return err
}

if ob != nil {
// insert
if order.OrderID == 0 {
// Save order into orderbook tree.
log.Info("Process saved")
err := ob.SaveOrderPending(order)
if err != nil {
log.Error("Error Save Order Pending", "error", err)
if err := ob.SaveOrderPending(order); err != nil {
return err
}
//log.Info("Process order")
//trades, orderInBook = ob.ProcessOrder(order, true)
} else {
log.Info("Update order")
err := ob.UpdateOrder(order)
if err != nil {
if err := ob.UpdateOrder(order); err != nil {
log.Error("Update order failed", "order", order, "err", err)
return trades, orderInBook, err
return err
}
}
}

return trades, orderInBook, nil
return nil
}

func (tomox *TomoX) CancelOrder(order *OrderItem) error {
Expand Down Expand Up @@ -694,7 +697,7 @@ func (tomox *TomoX) ProcessOrderPending() {
if order != nil {
order.Item.OrderID = zero.Uint64()
log.Info("Process order pending", "orderPending", order.Item)
tomox.ProcessOrder(order.Item)
ob.ProcessOrder(order.Item, true)
}
}
}

0 comments on commit 25510ca

Please sign in to comment.