mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
all: remove mongodb support in XDCx (#1679)
* all: remove SDK node * cmd: remove XDCXDBEngineFlag * cmd: remove XDCXDBConnectionUrlFlag * cmd, XDCx: remove XDCXDBReplicaSetNameFlag * XDCx: remove ConnectionUrl * all: remove mongodb support * cmd: remove XDCXEnabledFlag
This commit is contained in:
parent
0c96e76992
commit
71e8e27f84
12 changed files with 15 additions and 2097 deletions
328
XDCx/XDCx.go
328
XDCx/XDCx.go
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxDAO"
|
||||
|
|
@ -30,11 +29,8 @@ var (
|
|||
)
|
||||
|
||||
type Config struct {
|
||||
DataDir string `toml:",omitempty"`
|
||||
DBEngine string `toml:",omitempty"`
|
||||
DBName string `toml:",omitempty"`
|
||||
ConnectionUrl string `toml:",omitempty"`
|
||||
ReplicaSetName string `toml:",omitempty"`
|
||||
DataDir string `toml:",omitempty"`
|
||||
DBName string `toml:",omitempty"`
|
||||
}
|
||||
|
||||
// DefaultConfig represents (shocker!) the default configuration.
|
||||
|
|
@ -45,7 +41,6 @@ var DefaultConfig = Config{
|
|||
type XDCX struct {
|
||||
// Order related
|
||||
db XDCxDAO.XDCXDAO
|
||||
mongodb XDCxDAO.XDCXDAO
|
||||
Triegc *prque.Prque[int64, common.Hash] // Priority queue mapping block numbers to tries to gc
|
||||
StateCache tradingstate.Database // State database to reuse between imports (contains state cache) *XDCx_state.TradingStateDB
|
||||
|
||||
|
|
@ -60,16 +55,6 @@ func NewLDBEngine(cfg *Config) *XDCxDAO.BatchDatabase {
|
|||
return batchDB
|
||||
}
|
||||
|
||||
func NewMongoDBEngine(cfg *Config) *XDCxDAO.MongoDatabase {
|
||||
mongoDB, err := XDCxDAO.NewMongoDatabase(nil, cfg.DBName, cfg.ConnectionUrl, cfg.ReplicaSetName, 0)
|
||||
|
||||
if err != nil {
|
||||
log.Crit("Failed to init mongodb engine", "err", err)
|
||||
}
|
||||
|
||||
return mongoDB
|
||||
}
|
||||
|
||||
func New(stack *node.Node, cfg *Config) *XDCX {
|
||||
XDCX := &XDCX{
|
||||
Triegc: prque.New[int64, common.Hash](nil),
|
||||
|
|
@ -79,30 +64,16 @@ func New(stack *node.Node, cfg *Config) *XDCX {
|
|||
|
||||
// default DBEngine: levelDB
|
||||
XDCX.db = NewLDBEngine(cfg)
|
||||
XDCX.sdkNode = false
|
||||
|
||||
if cfg.DBEngine == "mongodb" { // this is an add-on DBEngine for SDK nodes
|
||||
XDCX.mongodb = NewMongoDBEngine(cfg)
|
||||
XDCX.sdkNode = true
|
||||
}
|
||||
|
||||
XDCX.StateCache = tradingstate.NewDatabase(XDCX.db)
|
||||
|
||||
return XDCX
|
||||
}
|
||||
|
||||
func (XDCx *XDCX) IsSDKNode() bool {
|
||||
return XDCx.sdkNode
|
||||
}
|
||||
|
||||
func (XDCx *XDCX) GetLevelDB() XDCxDAO.XDCXDAO {
|
||||
return XDCx.db
|
||||
}
|
||||
|
||||
func (XDCx *XDCX) GetMongoDB() XDCxDAO.XDCXDAO {
|
||||
return XDCx.mongodb
|
||||
}
|
||||
|
||||
func (XDCx *XDCX) ProcessOrderPending(header *types.Header, coinbase common.Address, chain consensus.ChainContext, pending map[common.Address]types.OrderTransactions, statedb *state.StateDB, XDCXstatedb *tradingstate.TradingStateDB) ([]tradingstate.TxDataMatch, map[common.Hash]tradingstate.MatchingResult) {
|
||||
txMatches := []tradingstate.TxDataMatch{}
|
||||
matchingResults := map[common.Hash]tradingstate.MatchingResult{}
|
||||
|
|
@ -250,259 +221,6 @@ func (XDCx *XDCX) ConvertXDCToToken(chain consensus.ChainContext, statedb *state
|
|||
return tokenQuantity, tokenPriceInXDC, nil
|
||||
}
|
||||
|
||||
// there are 3 tasks need to complete to update data in SDK nodes after matching
|
||||
// 1. txMatchData.Order: order has been processed. This order should be put to `orders` collection with status sdktypes.OrderStatusOpen
|
||||
// 2. txMatchData.Trades: includes information of matched orders.
|
||||
// a. PutObject them to `trades` collection
|
||||
// b. Update status of regrading orders to sdktypes.OrderStatusFilled
|
||||
func (XDCx *XDCX) SyncDataToSDKNode(takerOrderInTx *tradingstate.OrderItem, txHash common.Hash, txMatchTime time.Time, statedb *state.StateDB, trades []map[string]string, rejectedOrders []*tradingstate.OrderItem, dirtyOrderCount *uint64) error {
|
||||
var (
|
||||
// originTakerOrder: order get from db, nil if it doesn't exist
|
||||
// takerOrderInTx: order decoded from txdata
|
||||
// updatedTakerOrder: order with new status, filledAmount, CreatedAt, UpdatedAt. This will be inserted to db
|
||||
originTakerOrder, updatedTakerOrder *tradingstate.OrderItem
|
||||
makerDirtyHashes []string
|
||||
makerDirtyFilledAmount map[string]*big.Int
|
||||
err error
|
||||
)
|
||||
db := XDCx.GetMongoDB()
|
||||
db.InitBulk()
|
||||
if takerOrderInTx.Status == tradingstate.OrderStatusCancelled && len(rejectedOrders) > 0 {
|
||||
// cancel order is rejected -> nothing change
|
||||
log.Debug("Cancel order is rejected", "order", tradingstate.ToJSON(takerOrderInTx))
|
||||
return nil
|
||||
}
|
||||
// 1. put processed takerOrderInTx to db
|
||||
lastState := tradingstate.OrderHistoryItem{}
|
||||
val, err := db.GetObject(takerOrderInTx.Hash, &tradingstate.OrderItem{})
|
||||
if err == nil && val != nil {
|
||||
originTakerOrder = val.(*tradingstate.OrderItem)
|
||||
lastState = tradingstate.OrderHistoryItem{
|
||||
TxHash: originTakerOrder.TxHash,
|
||||
FilledAmount: tradingstate.CloneBigInt(originTakerOrder.FilledAmount),
|
||||
Status: originTakerOrder.Status,
|
||||
UpdatedAt: originTakerOrder.UpdatedAt,
|
||||
}
|
||||
}
|
||||
if originTakerOrder != nil {
|
||||
updatedTakerOrder = originTakerOrder
|
||||
} else {
|
||||
updatedTakerOrder = takerOrderInTx
|
||||
updatedTakerOrder.FilledAmount = new(big.Int)
|
||||
}
|
||||
|
||||
if takerOrderInTx.Status != tradingstate.OrderStatusCancelled {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusOpen
|
||||
} else {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusCancelled
|
||||
updatedTakerOrder.ExtraData = takerOrderInTx.ExtraData
|
||||
}
|
||||
updatedTakerOrder.TxHash = txHash
|
||||
if updatedTakerOrder.CreatedAt.IsZero() {
|
||||
updatedTakerOrder.CreatedAt = txMatchTime
|
||||
}
|
||||
if txMatchTime.Before(updatedTakerOrder.UpdatedAt) || (txMatchTime.Equal(updatedTakerOrder.UpdatedAt) && *dirtyOrderCount == 0) {
|
||||
log.Debug("Ignore old orders/trades taker", "txHash", txHash.Hex(), "txTime", txMatchTime.UnixNano(), "updatedAt", updatedTakerOrder.UpdatedAt.UnixNano())
|
||||
return nil
|
||||
}
|
||||
*dirtyOrderCount++
|
||||
|
||||
XDCx.UpdateOrderCache(updatedTakerOrder.BaseToken, updatedTakerOrder.QuoteToken, updatedTakerOrder.Hash, txHash, lastState)
|
||||
updatedTakerOrder.UpdatedAt = txMatchTime
|
||||
|
||||
// 2. put trades to db and update status to FILLED
|
||||
log.Debug("Got trades", "number", len(trades), "txhash", txHash.Hex())
|
||||
makerDirtyFilledAmount = make(map[string]*big.Int)
|
||||
for _, trade := range trades {
|
||||
// 2.a. put to trades
|
||||
if trade == nil {
|
||||
continue
|
||||
}
|
||||
tradeRecord := &tradingstate.Trade{}
|
||||
quantity := tradingstate.ToBigInt(trade[tradingstate.TradeQuantity])
|
||||
price := tradingstate.ToBigInt(trade[tradingstate.TradePrice])
|
||||
if price.Sign() <= 0 || quantity.Sign() <= 0 {
|
||||
return fmt.Errorf("trade misses important information. tradedPrice %v, tradedQuantity %v", price, quantity)
|
||||
}
|
||||
tradeRecord.Amount = quantity
|
||||
tradeRecord.PricePoint = price
|
||||
tradeRecord.BaseToken = updatedTakerOrder.BaseToken
|
||||
tradeRecord.QuoteToken = updatedTakerOrder.QuoteToken
|
||||
tradeRecord.Status = tradingstate.TradeStatusSuccess
|
||||
tradeRecord.Taker = updatedTakerOrder.UserAddress
|
||||
tradeRecord.Maker = common.HexToAddress(trade[tradingstate.TradeMaker])
|
||||
tradeRecord.TakerOrderHash = updatedTakerOrder.Hash
|
||||
tradeRecord.MakerOrderHash = common.HexToHash(trade[tradingstate.TradeMakerOrderHash])
|
||||
tradeRecord.TxHash = txHash
|
||||
tradeRecord.TakerOrderSide = updatedTakerOrder.Side
|
||||
tradeRecord.TakerExchange = updatedTakerOrder.ExchangeAddress
|
||||
tradeRecord.MakerExchange = common.HexToAddress(trade[tradingstate.TradeMakerExchange])
|
||||
|
||||
tradeRecord.MakeFee, _ = new(big.Int).SetString(trade[tradingstate.MakerFee], 10)
|
||||
tradeRecord.TakeFee, _ = new(big.Int).SetString(trade[tradingstate.TakerFee], 10)
|
||||
|
||||
// set makerOrderType, takerOrderType
|
||||
tradeRecord.MakerOrderType = trade[tradingstate.MakerOrderType]
|
||||
tradeRecord.TakerOrderType = updatedTakerOrder.Type
|
||||
|
||||
if tradeRecord.CreatedAt.IsZero() {
|
||||
tradeRecord.CreatedAt = txMatchTime
|
||||
}
|
||||
tradeRecord.UpdatedAt = txMatchTime
|
||||
tradeRecord.Hash = tradeRecord.ComputeHash()
|
||||
|
||||
log.Debug("TRADE history", "amount", tradeRecord.Amount, "pricepoint", tradeRecord.PricePoint,
|
||||
"taker", tradeRecord.Taker.Hex(), "maker", tradeRecord.Maker.Hex(), "takerOrder", tradeRecord.TakerOrderHash.Hex(), "makerOrder", tradeRecord.MakerOrderHash.Hex(),
|
||||
"takerFee", tradeRecord.TakeFee, "makerFee", tradeRecord.MakeFee)
|
||||
if err := db.PutObject(tradeRecord.Hash, tradeRecord); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to store tradeRecord %s", err.Error())
|
||||
}
|
||||
|
||||
// 2.b. update status and filledAmount
|
||||
filledAmount := quantity
|
||||
// maker dirty order
|
||||
makerFilledAmount := big.NewInt(0)
|
||||
if amount, ok := makerDirtyFilledAmount[trade[tradingstate.TradeMakerOrderHash]]; ok {
|
||||
makerFilledAmount = tradingstate.CloneBigInt(amount)
|
||||
}
|
||||
makerFilledAmount = new(big.Int).Add(makerFilledAmount, filledAmount)
|
||||
makerDirtyFilledAmount[trade[tradingstate.TradeMakerOrderHash]] = makerFilledAmount
|
||||
makerDirtyHashes = append(makerDirtyHashes, trade[tradingstate.TradeMakerOrderHash])
|
||||
|
||||
//updatedTakerOrder = XDCx.updateMatchedOrder(updatedTakerOrder, filledAmount, txMatchTime, txHash)
|
||||
// update filledAmount, status of takerOrder
|
||||
updatedTakerOrder.FilledAmount = new(big.Int).Add(updatedTakerOrder.FilledAmount, filledAmount)
|
||||
if updatedTakerOrder.FilledAmount.Cmp(updatedTakerOrder.Quantity) < 0 && updatedTakerOrder.Type == tradingstate.Limit {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusPartialFilled
|
||||
} else {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusFilled
|
||||
}
|
||||
}
|
||||
|
||||
// for Market orders
|
||||
// filledAmount > 0 : FILLED
|
||||
// otherwise: REJECTED
|
||||
if updatedTakerOrder.Type == tradingstate.Market {
|
||||
if updatedTakerOrder.FilledAmount.Sign() > 0 {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusFilled
|
||||
} else {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusRejected
|
||||
}
|
||||
}
|
||||
log.Debug("PutObject processed takerOrder",
|
||||
"userAddr", updatedTakerOrder.UserAddress.Hex(), "side", updatedTakerOrder.Side,
|
||||
"price", updatedTakerOrder.Price, "quantity", updatedTakerOrder.Quantity, "filledAmount", updatedTakerOrder.FilledAmount, "status", updatedTakerOrder.Status,
|
||||
"hash", updatedTakerOrder.Hash.Hex(), "txHash", updatedTakerOrder.TxHash.Hex())
|
||||
if err := db.PutObject(updatedTakerOrder.Hash, updatedTakerOrder); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to put processed takerOrder. Hash: %s Error: %s", updatedTakerOrder.Hash.Hex(), err.Error())
|
||||
}
|
||||
items := db.GetListItemByHashes(makerDirtyHashes, &tradingstate.OrderItem{})
|
||||
if items != nil {
|
||||
makerOrders := items.([]*tradingstate.OrderItem)
|
||||
log.Debug("Maker dirty orders", "len", len(makerOrders), "txhash", txHash.Hex())
|
||||
for _, o := range makerOrders {
|
||||
if txMatchTime.Before(o.UpdatedAt) {
|
||||
log.Debug("Ignore old orders/trades maker", "txHash", txHash.Hex(), "txTime", txMatchTime.UnixNano(), "updatedAt", updatedTakerOrder.UpdatedAt.UnixNano())
|
||||
continue
|
||||
}
|
||||
lastState = tradingstate.OrderHistoryItem{
|
||||
TxHash: o.TxHash,
|
||||
FilledAmount: tradingstate.CloneBigInt(o.FilledAmount),
|
||||
Status: o.Status,
|
||||
UpdatedAt: o.UpdatedAt,
|
||||
}
|
||||
XDCx.UpdateOrderCache(o.BaseToken, o.QuoteToken, o.Hash, txHash, lastState)
|
||||
o.TxHash = txHash
|
||||
o.UpdatedAt = txMatchTime
|
||||
o.FilledAmount = new(big.Int).Add(o.FilledAmount, makerDirtyFilledAmount[o.Hash.Hex()])
|
||||
if o.FilledAmount.Cmp(o.Quantity) < 0 {
|
||||
o.Status = tradingstate.OrderStatusPartialFilled
|
||||
} else {
|
||||
o.Status = tradingstate.OrderStatusFilled
|
||||
}
|
||||
log.Debug("PutObject processed makerOrder",
|
||||
"userAddr", o.UserAddress.Hex(), "side", o.Side,
|
||||
"price", o.Price, "quantity", o.Quantity, "filledAmount", o.FilledAmount, "status", o.Status,
|
||||
"hash", o.Hash.Hex(), "txHash", o.TxHash.Hex())
|
||||
if err := db.PutObject(o.Hash, o); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to put processed makerOrder. Hash: %s Error: %s", o.Hash.Hex(), err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. put rejected orders to db and update status REJECTED
|
||||
log.Debug("Got rejected orders", "number", len(rejectedOrders), "rejectedOrders", rejectedOrders)
|
||||
|
||||
if len(rejectedOrders) > 0 {
|
||||
var rejectedHashes []string
|
||||
// updateRejectedOrders
|
||||
for _, rejectedOrder := range rejectedOrders {
|
||||
rejectedHashes = append(rejectedHashes, rejectedOrder.Hash.Hex())
|
||||
if updatedTakerOrder.Hash == rejectedOrder.Hash && !txMatchTime.Before(updatedTakerOrder.UpdatedAt) {
|
||||
// cache order history for handling reorg
|
||||
orderHistoryRecord := tradingstate.OrderHistoryItem{
|
||||
TxHash: updatedTakerOrder.TxHash,
|
||||
FilledAmount: tradingstate.CloneBigInt(updatedTakerOrder.FilledAmount),
|
||||
Status: updatedTakerOrder.Status,
|
||||
UpdatedAt: updatedTakerOrder.UpdatedAt,
|
||||
}
|
||||
XDCx.UpdateOrderCache(updatedTakerOrder.BaseToken, updatedTakerOrder.QuoteToken, updatedTakerOrder.Hash, txHash, orderHistoryRecord)
|
||||
// if whole order is rejected, status = REJECTED
|
||||
// otherwise, status = FILLED
|
||||
if updatedTakerOrder.FilledAmount.Sign() > 0 {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusFilled
|
||||
} else {
|
||||
updatedTakerOrder.Status = tradingstate.OrderStatusRejected
|
||||
}
|
||||
updatedTakerOrder.TxHash = txHash
|
||||
updatedTakerOrder.UpdatedAt = txMatchTime
|
||||
if err := db.PutObject(updatedTakerOrder.Hash, updatedTakerOrder); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to reject takerOrder. Hash: %s Error: %s", updatedTakerOrder.Hash.Hex(), err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
items := db.GetListItemByHashes(rejectedHashes, &tradingstate.OrderItem{})
|
||||
if items != nil {
|
||||
dirtyRejectedOrders := items.([]*tradingstate.OrderItem)
|
||||
for _, order := range dirtyRejectedOrders {
|
||||
if txMatchTime.Before(order.UpdatedAt) {
|
||||
log.Debug("Ignore old orders/trades reject", "txHash", txHash.Hex(), "txTime", txMatchTime.UnixNano(), "updatedAt", updatedTakerOrder.UpdatedAt.UnixNano())
|
||||
continue
|
||||
}
|
||||
// cache order history for handling reorg
|
||||
orderHistoryRecord := tradingstate.OrderHistoryItem{
|
||||
TxHash: order.TxHash,
|
||||
FilledAmount: tradingstate.CloneBigInt(order.FilledAmount),
|
||||
Status: order.Status,
|
||||
UpdatedAt: order.UpdatedAt,
|
||||
}
|
||||
XDCx.UpdateOrderCache(order.BaseToken, order.QuoteToken, order.Hash, txHash, orderHistoryRecord)
|
||||
dirtyFilledAmount, ok := makerDirtyFilledAmount[order.Hash.Hex()]
|
||||
if ok && dirtyFilledAmount != nil {
|
||||
order.FilledAmount = new(big.Int).Add(order.FilledAmount, dirtyFilledAmount)
|
||||
}
|
||||
// if whole order is rejected, status = REJECTED
|
||||
// otherwise, status = FILLED
|
||||
if order.FilledAmount.Sign() > 0 {
|
||||
order.Status = tradingstate.OrderStatusFilled
|
||||
} else {
|
||||
order.Status = tradingstate.OrderStatusRejected
|
||||
}
|
||||
order.TxHash = txHash
|
||||
order.UpdatedAt = txMatchTime
|
||||
if err = db.PutObject(order.Hash, order); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to update rejectedOder to sdkNode %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.CommitBulk(); err != nil {
|
||||
return fmt.Errorf("SDKNode fail to commit bulk update orders, trades at txhash %s . Error: %s", txHash.Hex(), err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (XDCx *XDCX) GetTradingState(block *types.Block, author common.Address) (*tradingstate.TradingStateDB, error) {
|
||||
root, err := XDCx.GetTradingStateRoot(block, author)
|
||||
if err != nil {
|
||||
|
|
@ -559,45 +277,3 @@ func (XDCx *XDCX) UpdateOrderCache(baseToken, quoteToken common.Address, orderHa
|
|||
}
|
||||
XDCx.orderCache.Add(txhash, orderCacheAtTxHash)
|
||||
}
|
||||
|
||||
func (XDCx *XDCX) RollbackReorgTxMatch(txhash common.Hash) error {
|
||||
db := XDCx.GetMongoDB()
|
||||
db.InitBulk()
|
||||
|
||||
items := db.GetListItemByTxHash(txhash, &tradingstate.OrderItem{})
|
||||
if items != nil {
|
||||
for _, order := range items.([]*tradingstate.OrderItem) {
|
||||
orderCacheAtTxHash, ok := XDCx.orderCache.Get(txhash)
|
||||
log.Debug("XDCx reorg: rollback order", "txhash", txhash.Hex(), "order", tradingstate.ToJSON(order), "orderHistoryItem", orderCacheAtTxHash)
|
||||
if !ok || orderCacheAtTxHash == nil {
|
||||
log.Debug("XDCx reorg: remove order due to no orderCache", "order", tradingstate.ToJSON(order))
|
||||
if err := db.DeleteObject(order.Hash, &tradingstate.OrderItem{}); err != nil {
|
||||
log.Crit("SDKNode: failed to remove reorg order", "err", err.Error(), "order", tradingstate.ToJSON(order))
|
||||
}
|
||||
continue
|
||||
}
|
||||
orderHistoryItem := orderCacheAtTxHash[tradingstate.GetOrderHistoryKey(order.BaseToken, order.QuoteToken, order.Hash)]
|
||||
if (orderHistoryItem == tradingstate.OrderHistoryItem{}) {
|
||||
log.Debug("XDCx reorg: remove order due to empty orderHistory", "order", tradingstate.ToJSON(order))
|
||||
if err := db.DeleteObject(order.Hash, &tradingstate.OrderItem{}); err != nil {
|
||||
log.Crit("SDKNode: failed to remove reorg order", "err", err.Error(), "order", tradingstate.ToJSON(order))
|
||||
}
|
||||
continue
|
||||
}
|
||||
order.TxHash = orderHistoryItem.TxHash
|
||||
order.Status = orderHistoryItem.Status
|
||||
order.FilledAmount = tradingstate.CloneBigInt(orderHistoryItem.FilledAmount)
|
||||
order.UpdatedAt = orderHistoryItem.UpdatedAt
|
||||
log.Debug("XDCx reorg: update order to the last orderHistoryItem", "order", tradingstate.ToJSON(order), "orderHistoryItem", orderHistoryItem)
|
||||
if err := db.PutObject(order.Hash, order); err != nil {
|
||||
log.Crit("SDKNode: failed to update reorg order", "err", err.Error(), "order", tradingstate.ToJSON(order))
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Debug("XDCx reorg: DeleteTradeByTxHash", "txhash", txhash.Hex())
|
||||
db.DeleteItemByTxHash(txhash, &tradingstate.Trade{})
|
||||
if err := db.CommitBulk(); err != nil {
|
||||
return fmt.Errorf("failed to RollbackTradingData. %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -784,37 +784,5 @@ func (XDCx *XDCX) UpdateMediumPriceBeforeEpoch(epochNumber uint64, tradingStateD
|
|||
}
|
||||
tradingStateDB.SetMediumPrice(orderbook, tradingstate.Zero, tradingstate.Zero)
|
||||
}
|
||||
if XDCx.IsSDKNode() {
|
||||
if err := XDCx.LogEpochPrice(epochNumber, epochPriceResult); err != nil {
|
||||
log.Error("failed to update epochPrice", "err", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// put average price of epoch to mongodb for tracking liquidation trades
|
||||
// epochPriceResult: a map of epoch average price, key is orderbook hash , value is epoch average price
|
||||
// orderbook hash genereted from baseToken, quoteToken at XDPoSChain/XDCx/tradingstate/common.go:214
|
||||
func (XDCx *XDCX) LogEpochPrice(epochNumber uint64, epochPriceResult map[common.Hash]*big.Int) error {
|
||||
db := XDCx.GetMongoDB()
|
||||
db.InitBulk()
|
||||
|
||||
for orderbook, price := range epochPriceResult {
|
||||
if price.Sign() <= 0 {
|
||||
continue
|
||||
}
|
||||
epochPriceItem := &tradingstate.EpochPriceItem{
|
||||
Epoch: epochNumber,
|
||||
Orderbook: orderbook,
|
||||
Price: price,
|
||||
}
|
||||
epochPriceItem.Hash = epochPriceItem.ComputeHash()
|
||||
if err := db.PutObject(epochPriceItem.Hash, epochPriceItem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := db.CommitBulk(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// This file is part of the Core XDPoSChain infrastructure
|
||||
// https://XDPoSChain.com
|
||||
// Package XDCxDAO provides an interface to work with XDCx database, including leveldb for masternode and mongodb for SDK node
|
||||
|
||||
package XDCxDAO
|
||||
|
||||
import (
|
||||
|
|
@ -15,15 +16,7 @@ type XDCXDAO interface {
|
|||
// for both leveldb and mongodb
|
||||
IsEmptyKey(key []byte) bool
|
||||
Close() error
|
||||
|
||||
// mongodb methods
|
||||
HasObject(hash common.Hash, val interface{}) (bool, error)
|
||||
GetObject(hash common.Hash, val interface{}) (interface{}, error)
|
||||
PutObject(hash common.Hash, val interface{}) error
|
||||
DeleteObject(hash common.Hash, val interface{}) error // won't return error if key not found
|
||||
GetListItemByTxHash(txhash common.Hash, val interface{}) interface{}
|
||||
GetListItemByHashes(hashes []string, val interface{}) interface{}
|
||||
DeleteItemByTxHash(txhash common.Hash, val interface{})
|
||||
|
||||
// basic XDCx
|
||||
InitBulk()
|
||||
|
|
|
|||
|
|
@ -52,26 +52,10 @@ func (db *BatchDatabase) IsEmptyKey(key []byte) bool {
|
|||
return len(key) == 0 || bytes.Equal(key, db.emptyKey)
|
||||
}
|
||||
|
||||
func (db *BatchDatabase) HasObject(hash common.Hash, val interface{}) (bool, error) {
|
||||
// for mongodb only
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (db *BatchDatabase) GetObject(hash common.Hash, val interface{}) (interface{}, error) {
|
||||
// for mongodb only
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *BatchDatabase) PutObject(hash common.Hash, val interface{}) error {
|
||||
// for mongodb only
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *BatchDatabase) DeleteObject(hash common.Hash, val interface{}) error {
|
||||
// for mongodb only
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *BatchDatabase) Put(key []byte, val []byte) error {
|
||||
return db.db.Put(key, val)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,920 +0,0 @@
|
|||
package XDCxDAO
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/globalsign/mgo"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
const (
|
||||
ordersCollection = "orders"
|
||||
tradesCollection = "trades"
|
||||
lendingItemsCollection = "lending_items"
|
||||
lendingTradesCollection = "lending_trades"
|
||||
lendingTopUpCollection = "lending_topups"
|
||||
lendingRepayCollection = "lending_repays"
|
||||
lendingRecallCollection = "lending_recalls"
|
||||
epochPriceCollection = "epoch_prices"
|
||||
)
|
||||
|
||||
type MongoDatabase struct {
|
||||
Session *mgo.Session
|
||||
dbName string
|
||||
emptyKey []byte
|
||||
cacheItems *lru.Cache[string, interface{}] // Cache for reading
|
||||
orderBulk *mgo.Bulk
|
||||
tradeBulk *mgo.Bulk
|
||||
epochPriceBulk *mgo.Bulk
|
||||
lendingItemBulk *mgo.Bulk
|
||||
topUpBulk *mgo.Bulk
|
||||
recallBulk *mgo.Bulk
|
||||
repayBulk *mgo.Bulk
|
||||
lendingTradeBulk *mgo.Bulk
|
||||
}
|
||||
|
||||
// InitSession initializes a new session with mongodb
|
||||
func NewMongoDatabase(session *mgo.Session, dbName string, mongoURL string, replicaSetName string, cacheLimit int) (*MongoDatabase, error) {
|
||||
if session == nil {
|
||||
// in case of multiple database instances
|
||||
hosts := strings.Split(mongoURL, ",")
|
||||
dbInfo := &mgo.DialInfo{
|
||||
Addrs: hosts,
|
||||
Database: dbName,
|
||||
ReplicaSetName: replicaSetName,
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
ns, err := mgo.DialWithInfo(dbInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
session = ns
|
||||
}
|
||||
itemCacheLimit := defaultCacheLimit
|
||||
if cacheLimit > 0 {
|
||||
itemCacheLimit = cacheLimit
|
||||
}
|
||||
|
||||
db := &MongoDatabase{
|
||||
Session: session,
|
||||
dbName: dbName,
|
||||
cacheItems: lru.NewCache[string, interface{}](itemCacheLimit),
|
||||
}
|
||||
if err := db.EnsureIndexes(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) IsEmptyKey(key []byte) bool {
|
||||
return len(key) == 0 || bytes.Equal(key, db.emptyKey)
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) getCacheKey(key []byte) string {
|
||||
return hex.EncodeToString(key)
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) HasObject(hash common.Hash, val interface{}) (bool, error) {
|
||||
if db.IsEmptyKey(hash.Bytes()) {
|
||||
return false, nil
|
||||
}
|
||||
cacheKey := db.getCacheKey(hash.Bytes())
|
||||
if db.cacheItems.Contains(cacheKey) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
sc := db.Session.Copy()
|
||||
defer sc.Close()
|
||||
var (
|
||||
count int
|
||||
err error
|
||||
)
|
||||
query := bson.M{"hash": hash.Hex()}
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
// Find key in ordersCollection collection
|
||||
count, err = sc.DB(db.dbName).C(ordersCollection).Find(query).Limit(1).Count()
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if count == 1 {
|
||||
return true, nil
|
||||
}
|
||||
case *tradingstate.Trade:
|
||||
// Find key in tradesCollection collection
|
||||
count, err = sc.DB(db.dbName).C(tradesCollection).Find(query).Limit(1).Count()
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if count == 1 {
|
||||
return true, nil
|
||||
}
|
||||
case *lendingstate.LendingItem:
|
||||
// Find key in lendingItemsCollection collection
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
count, err = sc.DB(db.dbName).C(lendingRepayCollection).Find(query).Limit(1).Count()
|
||||
case lendingstate.TopUp:
|
||||
count, err = sc.DB(db.dbName).C(lendingTopUpCollection).Find(query).Limit(1).Count()
|
||||
case lendingstate.Recall:
|
||||
count, err = sc.DB(db.dbName).C(lendingRecallCollection).Find(query).Limit(1).Count()
|
||||
default:
|
||||
count, err = sc.DB(db.dbName).C(lendingItemsCollection).Find(query).Limit(1).Count()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if count == 1 {
|
||||
return true, nil
|
||||
}
|
||||
case *lendingstate.LendingTrade:
|
||||
// Find key in lendingTradesCollection collection
|
||||
count, err = sc.DB(db.dbName).C(lendingTradesCollection).Find(query).Limit(1).Count()
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if count == 1 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) GetObject(hash common.Hash, val interface{}) (interface{}, error) {
|
||||
if db.IsEmptyKey(hash.Bytes()) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
cacheKey := db.getCacheKey(hash.Bytes())
|
||||
if cached, ok := db.cacheItems.Get(cacheKey); ok {
|
||||
return cached, nil
|
||||
} else {
|
||||
sc := db.Session.Copy()
|
||||
defer sc.Close()
|
||||
|
||||
query := bson.M{"hash": hash.Hex()}
|
||||
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
var oi *tradingstate.OrderItem
|
||||
err := sc.DB(db.dbName).C(ordersCollection).Find(query).One(&oi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.cacheItems.Add(cacheKey, oi)
|
||||
return oi, nil
|
||||
case *tradingstate.Trade:
|
||||
var t *tradingstate.Trade
|
||||
err := sc.DB(db.dbName).C(tradesCollection).Find(query).One(&t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.cacheItems.Add(cacheKey, t)
|
||||
return t, nil
|
||||
case *lendingstate.LendingItem:
|
||||
var li *lendingstate.LendingItem
|
||||
var err error
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
err = sc.DB(db.dbName).C(lendingRepayCollection).Find(query).One(&li)
|
||||
case lendingstate.TopUp:
|
||||
err = sc.DB(db.dbName).C(lendingTopUpCollection).Find(query).One(&li)
|
||||
case lendingstate.Recall:
|
||||
err = sc.DB(db.dbName).C(lendingRecallCollection).Find(query).One(&li)
|
||||
default:
|
||||
err = sc.DB(db.dbName).C(lendingItemsCollection).Find(query).One(&li)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.cacheItems.Add(cacheKey, li)
|
||||
return li, nil
|
||||
case *lendingstate.LendingTrade:
|
||||
var t *lendingstate.LendingTrade
|
||||
err := sc.DB(db.dbName).C(lendingTradesCollection).Find(query).One(&t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.cacheItems.Add(cacheKey, t)
|
||||
return t, nil
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) PutObject(hash common.Hash, val interface{}) error {
|
||||
cacheKey := db.getCacheKey(hash.Bytes())
|
||||
db.cacheItems.Add(cacheKey, val)
|
||||
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.Trade:
|
||||
// PutObject trade into tradesCollection collection
|
||||
db.tradeBulk.Insert(item)
|
||||
case *tradingstate.OrderItem:
|
||||
// PutObject order into ordersCollection collection
|
||||
if item.Status == tradingstate.OrderStatusOpen {
|
||||
db.orderBulk.Insert(item)
|
||||
} else {
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.orderBulk.Upsert(query, item)
|
||||
}
|
||||
return nil
|
||||
case *tradingstate.EpochPriceItem:
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.epochPriceBulk.Upsert(query, item)
|
||||
return nil
|
||||
case *lendingstate.LendingTrade:
|
||||
// PutObject LendingTrade into tradesCollection collection
|
||||
if existed, err := db.HasObject(hash, val); err == nil && existed {
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.lendingTradeBulk.Upsert(query, item)
|
||||
} else {
|
||||
db.lendingTradeBulk.Insert(item)
|
||||
}
|
||||
case *lendingstate.LendingItem:
|
||||
// PutObject order into ordersCollection collection
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
if item.Status != lendingstate.LendingStatusReject {
|
||||
item.Status = lendingstate.Repay
|
||||
}
|
||||
db.repayBulk.Insert(item)
|
||||
return nil
|
||||
case lendingstate.TopUp:
|
||||
if item.Status != lendingstate.LendingStatusReject {
|
||||
item.Status = lendingstate.TopUp
|
||||
}
|
||||
db.topUpBulk.Insert(item)
|
||||
return nil
|
||||
case lendingstate.Recall:
|
||||
if item.Status != lendingstate.LendingStatusReject {
|
||||
item.Status = lendingstate.Recall
|
||||
}
|
||||
db.recallBulk.Insert(item)
|
||||
return nil
|
||||
default:
|
||||
if item.Status == lendingstate.LendingStatusOpen {
|
||||
db.lendingItemBulk.Insert(item)
|
||||
} else {
|
||||
query := bson.M{"hash": item.Hash.Hex()}
|
||||
db.lendingItemBulk.Upsert(query, item)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
default:
|
||||
log.Error("PutObject: unknown type of object", "val", val)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) DeleteObject(hash common.Hash, val interface{}) error {
|
||||
cacheKey := db.getCacheKey(hash.Bytes())
|
||||
db.cacheItems.Remove(cacheKey)
|
||||
|
||||
sc := db.Session.Copy()
|
||||
defer sc.Close()
|
||||
|
||||
query := bson.M{"hash": hash.Hex()}
|
||||
|
||||
found, err := db.HasObject(hash, val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if found {
|
||||
var err error
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
err = sc.DB(db.dbName).C(ordersCollection).Remove(query)
|
||||
if err != nil && err != mgo.ErrNotFound {
|
||||
return fmt.Errorf("failed to delete orderItem. Err: %v", err)
|
||||
}
|
||||
case *tradingstate.Trade:
|
||||
err = sc.DB(db.dbName).C(tradesCollection).Remove(query)
|
||||
if err != nil && err != mgo.ErrNotFound {
|
||||
return fmt.Errorf("failed to delete XDCx trade. Err: %v", err)
|
||||
}
|
||||
case *lendingstate.LendingItem:
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
err = sc.DB(db.dbName).C(lendingRepayCollection).Remove(query)
|
||||
case lendingstate.TopUp:
|
||||
err = sc.DB(db.dbName).C(lendingTopUpCollection).Remove(query)
|
||||
case lendingstate.Recall:
|
||||
err = sc.DB(db.dbName).C(lendingRecallCollection).Remove(query)
|
||||
default:
|
||||
err = sc.DB(db.dbName).C(lendingItemsCollection).Remove(query)
|
||||
}
|
||||
if err != nil && err != mgo.ErrNotFound {
|
||||
return fmt.Errorf("failed to delete lendingItem. Err: %v", err)
|
||||
}
|
||||
case *lendingstate.LendingTrade:
|
||||
err = sc.DB(db.dbName).C(lendingTradesCollection).Remove(query)
|
||||
if err != nil && err != mgo.ErrNotFound {
|
||||
return fmt.Errorf("failed to delete lendingTrade. Err: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) InitBulk() {
|
||||
sc := db.Session
|
||||
db.orderBulk = sc.DB(db.dbName).C(ordersCollection).Bulk()
|
||||
db.tradeBulk = sc.DB(db.dbName).C(tradesCollection).Bulk()
|
||||
db.epochPriceBulk = sc.DB(db.dbName).C(epochPriceCollection).Bulk()
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) InitLendingBulk() {
|
||||
sc := db.Session
|
||||
db.lendingItemBulk = sc.DB(db.dbName).C(lendingItemsCollection).Bulk()
|
||||
db.lendingTradeBulk = sc.DB(db.dbName).C(lendingTradesCollection).Bulk()
|
||||
db.topUpBulk = sc.DB(db.dbName).C(lendingTopUpCollection).Bulk()
|
||||
db.repayBulk = sc.DB(db.dbName).C(lendingRepayCollection).Bulk()
|
||||
db.recallBulk = sc.DB(db.dbName).C(lendingRecallCollection).Bulk()
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) CommitBulk() error {
|
||||
if _, err := db.orderBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
if _, err := db.tradeBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
if _, err := db.epochPriceBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) CommitLendingBulk() error {
|
||||
if _, err := db.lendingItemBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
if _, err := db.lendingTradeBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
if _, err := db.topUpBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
if _, err := db.repayBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
if _, err := db.recallBulk.Run(); err != nil && !mgo.IsDup(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) Put(key []byte, val []byte) error {
|
||||
// for levelDB only
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) Delete(key []byte) error {
|
||||
// for levelDB only
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) Has(key []byte) (bool, error) {
|
||||
// for levelDB only
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) Get(key []byte) ([]byte, error) {
|
||||
// for levelDB only
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) DeleteItemByTxHash(txhash common.Hash, val interface{}) {
|
||||
sc := db.Session.Copy()
|
||||
defer sc.Close()
|
||||
|
||||
query := bson.M{"txHash": txhash.Hex()}
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete order", "txhash", txhash, "err", err)
|
||||
}
|
||||
case *tradingstate.Trade:
|
||||
if err := sc.DB(db.dbName).C(tradesCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete trade", "txhash", txhash, "err", err)
|
||||
}
|
||||
case *lendingstate.LendingItem:
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
if err := sc.DB(db.dbName).C(lendingRepayCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete repayItem", "txhash", txhash, "err", err)
|
||||
}
|
||||
return
|
||||
case lendingstate.TopUp:
|
||||
if err := sc.DB(db.dbName).C(lendingTopUpCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete topupItem", "txhash", txhash, "err", err)
|
||||
}
|
||||
return
|
||||
case lendingstate.Recall:
|
||||
if err := sc.DB(db.dbName).C(lendingRecallCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete recallItem", "txhash", txhash, "err", err)
|
||||
}
|
||||
return
|
||||
default:
|
||||
if err := sc.DB(db.dbName).C(lendingItemsCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete lendingItem", "txhash", txhash, "err", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
case *lendingstate.LendingTrade:
|
||||
if err := sc.DB(db.dbName).C(lendingTradesCollection).Remove(query); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("DeleteItemByTxHash: failed to delete lendingTrade", "txhash", txhash, "err", err)
|
||||
}
|
||||
default:
|
||||
log.Error("DeleteItemByTxHash: Unknown object type", "txhash", txhash, "object", val)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) GetListItemByTxHash(txhash common.Hash, val interface{}) interface{} {
|
||||
sc := db.Session.Copy()
|
||||
defer sc.Close()
|
||||
|
||||
query := bson.M{"txHash": txhash.Hex()}
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
result := []*tradingstate.OrderItem{}
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByTxHash (orders)", "err", err, "Txhash", txhash)
|
||||
}
|
||||
return result
|
||||
case *tradingstate.Trade:
|
||||
result := []*tradingstate.Trade{}
|
||||
if err := sc.DB(db.dbName).C(tradesCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByTxHash (trades)", "err", err, "Txhash", txhash)
|
||||
}
|
||||
return result
|
||||
case *lendingstate.LendingItem:
|
||||
result := []*lendingstate.LendingItem{}
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
if err := sc.DB(db.dbName).C(lendingRepayCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByTxHash (repayItems)", "err", err, "txhash", txhash)
|
||||
}
|
||||
return result
|
||||
case lendingstate.TopUp:
|
||||
if err := sc.DB(db.dbName).C(lendingTopUpCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByTxHash (topupItems)", "err", err, "txhash", txhash)
|
||||
}
|
||||
return result
|
||||
case lendingstate.Recall:
|
||||
if err := sc.DB(db.dbName).C(lendingRecallCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByTxHash (recallItems)", "err", err, "txhash", txhash)
|
||||
}
|
||||
return result
|
||||
default:
|
||||
if err := sc.DB(db.dbName).C(lendingItemsCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByTxHash (lendingItems)", "err", err, "txhash", txhash)
|
||||
}
|
||||
return result
|
||||
}
|
||||
case *lendingstate.LendingTrade:
|
||||
result := []*lendingstate.LendingTrade{}
|
||||
if err := sc.DB(db.dbName).C(lendingTradesCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByTxHash (lendingTrades)", "err", err, "Txhash", txhash)
|
||||
}
|
||||
return result
|
||||
default:
|
||||
log.Error("GetListItemByTxHash: Unknown object type", "txhash", txhash, "object", val)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) GetListItemByHashes(hashes []string, val interface{}) interface{} {
|
||||
sc := db.Session.Copy()
|
||||
defer sc.Close()
|
||||
|
||||
query := bson.M{"hash": bson.M{"$in": hashes}}
|
||||
|
||||
switch item := val.(type) {
|
||||
case *tradingstate.OrderItem:
|
||||
result := []*tradingstate.OrderItem{}
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByHashes (orders)", "err", err, "hashes", hashes)
|
||||
}
|
||||
return result
|
||||
case *tradingstate.Trade:
|
||||
result := []*tradingstate.Trade{}
|
||||
if err := sc.DB(db.dbName).C(tradesCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByHashes (trades)", "err", err, "hashes", hashes)
|
||||
}
|
||||
return result
|
||||
case *lendingstate.LendingItem:
|
||||
result := []*lendingstate.LendingItem{}
|
||||
switch item.Type {
|
||||
case lendingstate.Repay:
|
||||
if err := sc.DB(db.dbName).C(lendingRepayCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByHashes (repayItems)", "err", err, "hashes", hashes)
|
||||
}
|
||||
return result
|
||||
case lendingstate.TopUp:
|
||||
if err := sc.DB(db.dbName).C(lendingTopUpCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByHashes (topupItems)", "err", err, "hashes", hashes)
|
||||
}
|
||||
return result
|
||||
case lendingstate.Recall:
|
||||
if err := sc.DB(db.dbName).C(lendingRecallCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByHashes (recallItems)", "err", err, "hashes", hashes)
|
||||
}
|
||||
return result
|
||||
default:
|
||||
if err := sc.DB(db.dbName).C(lendingItemsCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByHashes (lendingItems)", "err", err, "hashes", hashes)
|
||||
}
|
||||
return result
|
||||
}
|
||||
case *lendingstate.LendingTrade:
|
||||
result := []*lendingstate.LendingTrade{}
|
||||
if err := sc.DB(db.dbName).C(lendingTradesCollection).Find(query).All(&result); err != nil && err != mgo.ErrNotFound {
|
||||
log.Error("failed to GetListItemByHashes (lendingTrades)", "err", err, "hashes", hashes)
|
||||
}
|
||||
return result
|
||||
default:
|
||||
log.Error("GetListItemByHashes: Unknown object type", "hashes", hashes, "object", val)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) EnsureIndexes() error {
|
||||
orderHashIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_order_hash",
|
||||
}
|
||||
orderTxHashIndex := mgo.Index{
|
||||
Key: []string{"txHash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_order_tx_hash",
|
||||
}
|
||||
tradeHashIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_trade_hash",
|
||||
}
|
||||
tradeTxHashIndex := mgo.Index{
|
||||
Key: []string{"txHash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_trade_tx_hash",
|
||||
}
|
||||
lendingItemHashIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_item_hash",
|
||||
}
|
||||
lendingItemTxHashIndex := mgo.Index{
|
||||
Key: []string{"txHash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_item_tx_hash",
|
||||
}
|
||||
lendingTradeHashIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_trade_hash",
|
||||
}
|
||||
lendingTradeTxHashIndex := mgo.Index{
|
||||
Key: []string{"txHash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_trade_tx_hash",
|
||||
}
|
||||
repayHashIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_repay_hash",
|
||||
}
|
||||
repayTxHashIndex := mgo.Index{
|
||||
Key: []string{"txHash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_repay_tx_hash",
|
||||
}
|
||||
|
||||
repayUniqueIndex := mgo.Index{
|
||||
Key: []string{"txHash", "hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_repay_unique",
|
||||
}
|
||||
|
||||
recallHashIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_recall_hash",
|
||||
}
|
||||
recallTxHashIndex := mgo.Index{
|
||||
Key: []string{"txHash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_recall_tx_hash",
|
||||
}
|
||||
|
||||
recallUniqueIndex := mgo.Index{
|
||||
Key: []string{"txHash", "hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_recall_unique",
|
||||
}
|
||||
|
||||
topupHashIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_topup_hash",
|
||||
}
|
||||
topupTxHashIndex := mgo.Index{
|
||||
Key: []string{"txHash"},
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_topup_tx_hash",
|
||||
}
|
||||
|
||||
topUpUniqueIndex := mgo.Index{
|
||||
Key: []string{"txHash", "hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_lending_topup_unique",
|
||||
}
|
||||
|
||||
epochPriceIndex := mgo.Index{
|
||||
Key: []string{"hash"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
Background: true,
|
||||
Sparse: true,
|
||||
Name: "index_epoch_price",
|
||||
}
|
||||
|
||||
sc := db.Session.Copy()
|
||||
defer sc.Close()
|
||||
|
||||
indexes, _ := sc.DB(db.dbName).C(ordersCollection).Indexes()
|
||||
if !existingIndex(orderHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).EnsureIndex(orderHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", orderHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(orderTxHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(ordersCollection).EnsureIndex(orderTxHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", orderTxHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
indexes, _ = sc.DB(db.dbName).C(tradesCollection).Indexes()
|
||||
if !existingIndex(tradeHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(tradesCollection).EnsureIndex(tradeHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", tradeHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(tradeTxHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(tradesCollection).EnsureIndex(tradeTxHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", tradeTxHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
indexes, _ = sc.DB(db.dbName).C(lendingItemsCollection).Indexes()
|
||||
if !existingIndex(lendingItemHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingItemsCollection).EnsureIndex(lendingItemHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", lendingItemHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(lendingItemTxHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingItemsCollection).EnsureIndex(lendingItemTxHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", lendingItemTxHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
indexes, _ = sc.DB(db.dbName).C(lendingTradesCollection).Indexes()
|
||||
if !existingIndex(lendingTradeHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingTradesCollection).EnsureIndex(lendingTradeHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", lendingTradeHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(lendingTradeTxHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingTradesCollection).EnsureIndex(lendingTradeTxHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", lendingTradeTxHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
indexes, _ = sc.DB(db.dbName).C(lendingRepayCollection).Indexes()
|
||||
if !existingIndex(repayHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingRepayCollection).EnsureIndex(repayHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", repayHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(repayTxHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingRepayCollection).EnsureIndex(repayTxHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", repayTxHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !existingIndex(repayUniqueIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingRepayCollection).EnsureIndex(repayUniqueIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", repayUniqueIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
indexes, _ = sc.DB(db.dbName).C(lendingRecallCollection).Indexes()
|
||||
if !existingIndex(recallHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingRecallCollection).EnsureIndex(recallHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", recallHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(recallTxHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingRecallCollection).EnsureIndex(recallTxHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", recallTxHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(recallUniqueIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingRecallCollection).EnsureIndex(repayUniqueIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", repayUniqueIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
indexes, _ = sc.DB(db.dbName).C(lendingTopUpCollection).Indexes()
|
||||
if !existingIndex(topupHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingTopUpCollection).EnsureIndex(topupHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", topupHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
if !existingIndex(topupTxHashIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingTopUpCollection).EnsureIndex(topupTxHashIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", topupTxHashIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !existingIndex(topUpUniqueIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(lendingTopUpCollection).EnsureIndex(repayUniqueIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", repayUniqueIndex.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
indexes, _ = sc.DB(db.dbName).C(epochPriceCollection).Indexes()
|
||||
if !existingIndex(epochPriceIndex.Name, indexes) {
|
||||
if err := sc.DB(db.dbName).C(epochPriceCollection).EnsureIndex(epochPriceIndex); err != nil {
|
||||
return fmt.Errorf("failed to create index %s . Err: %v", epochPriceIndex.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) Close() error {
|
||||
if db.Session != nil {
|
||||
db.Session.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasAncient returns an error as we don't have a backing chain freezer.
|
||||
func (db *MongoDatabase) HasAncient(kind string, number uint64) (bool, error) {
|
||||
return false, errNotSupported
|
||||
}
|
||||
|
||||
// Ancient returns an error as we don't have a backing chain freezer.
|
||||
func (db *MongoDatabase) Ancient(kind string, number uint64) ([]byte, error) {
|
||||
return nil, errNotSupported
|
||||
}
|
||||
|
||||
// Ancients returns an error as we don't have a backing chain freezer.
|
||||
func (db *MongoDatabase) Ancients() (uint64, error) {
|
||||
return 0, errNotSupported
|
||||
}
|
||||
|
||||
// AncientSize returns an error as we don't have a backing chain freezer.
|
||||
func (db *MongoDatabase) AncientSize(kind string) (uint64, error) {
|
||||
return 0, errNotSupported
|
||||
}
|
||||
|
||||
// AppendAncient returns an error as we don't have a backing chain freezer.
|
||||
func (db *MongoDatabase) AppendAncient(number uint64, hash, header, body, receipts, td []byte) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
// TruncateAncients returns an error as we don't have a backing chain freezer.
|
||||
func (db *MongoDatabase) TruncateAncients(items uint64) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
// Sync returns an error as we don't have a backing chain freezer.
|
||||
func (db *MongoDatabase) Sync() error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
|
||||
panic("NewIterator from XDCxDAO mongodb is not supported")
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) Stat(property string) (string, error) {
|
||||
return "", errNotSupported
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) Compact(start []byte, limit []byte) error {
|
||||
return errNotSupported
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) NewBatch() ethdb.Batch {
|
||||
// for levelDB only
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *MongoDatabase) NewBatchWithSize(size int) ethdb.Batch {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Batch struct {
|
||||
collection string
|
||||
}
|
||||
|
||||
func (b *Batch) Put(key, value []byte) error {
|
||||
// for levelDB only
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Batch) Write() error {
|
||||
// for levelDB only
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Batch) ValueSize() int {
|
||||
// for levelDB only
|
||||
return int(0)
|
||||
}
|
||||
func (b *Batch) Reset() {
|
||||
// for levelDB only
|
||||
}
|
||||
|
||||
func existingIndex(indexName string, indexes []mgo.Index) bool {
|
||||
if len(indexes) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, index := range indexes {
|
||||
if index.Name == indexName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -3,10 +3,8 @@ package XDCxlending
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
|
|
@ -56,10 +54,6 @@ func (l *Lending) GetLevelDB() XDCxDAO.XDCXDAO {
|
|||
return l.XDCx.GetLevelDB()
|
||||
}
|
||||
|
||||
func (l *Lending) GetMongoDB() XDCxDAO.XDCXDAO {
|
||||
return l.XDCx.GetMongoDB()
|
||||
}
|
||||
|
||||
func (l *Lending) ProcessOrderPending(header *types.Header, coinbase common.Address, chain consensus.ChainContext, pending map[common.Address]types.LendingTransactions, statedb *state.StateDB, lendingStatedb *lendingstate.LendingStateDB, tradingStateDb *tradingstate.TradingStateDB) ([]*lendingstate.LendingItem, map[common.Hash]lendingstate.MatchingResult) {
|
||||
lendingItems := []*lendingstate.LendingItem{}
|
||||
matchingResults := map[common.Hash]lendingstate.MatchingResult{}
|
||||
|
|
@ -151,474 +145,6 @@ func (l *Lending) ProcessOrderPending(header *types.Header, coinbase common.Addr
|
|||
return lendingItems, matchingResults
|
||||
}
|
||||
|
||||
// there are 3 tasks need to complete (for SDK nodes) after matching
|
||||
// 1. Put takerLendingItem to database
|
||||
// 2.a Update status, filledAmount of makerLendingItem
|
||||
// 2.b. Put lendingTrade to database
|
||||
// 3. Update status of rejected items
|
||||
func (l *Lending) SyncDataToSDKNode(chain consensus.ChainContext, statedb *state.StateDB, block *types.Block, takerLendingItem *lendingstate.LendingItem, txHash common.Hash, txMatchTime time.Time, trades []*lendingstate.LendingTrade, rejectedItems []*lendingstate.LendingItem, dirtyOrderCount *uint64) error {
|
||||
var (
|
||||
// originTakerLendingItem: item getting from database
|
||||
originTakerLendingItem, updatedTakerLendingItem *lendingstate.LendingItem
|
||||
makerDirtyHashes []string
|
||||
makerDirtyFilledAmount map[string]*big.Int
|
||||
err error
|
||||
)
|
||||
db := l.GetMongoDB()
|
||||
db.InitLendingBulk()
|
||||
if takerLendingItem.Status == lendingstate.LendingStatusCancelled && len(rejectedItems) > 0 {
|
||||
// cancel order is rejected -> nothing change
|
||||
log.Debug("Cancel order is rejected", "order", lendingstate.ToJSON(takerLendingItem))
|
||||
return nil
|
||||
}
|
||||
// 1. put processed takerLendingItem to database
|
||||
lastState := lendingstate.LendingItemHistoryItem{}
|
||||
// Typically, takerItem has never existed in database
|
||||
// except cancel case: in this case, item existed in database with status = OPEN, then use send another lendingItem to cancel it
|
||||
val, err := db.GetObject(takerLendingItem.Hash, &lendingstate.LendingItem{Type: takerLendingItem.Type})
|
||||
if err == nil && val != nil {
|
||||
originTakerLendingItem = val.(*lendingstate.LendingItem)
|
||||
lastState = lendingstate.LendingItemHistoryItem{
|
||||
TxHash: originTakerLendingItem.TxHash,
|
||||
FilledAmount: lendingstate.CloneBigInt(originTakerLendingItem.FilledAmount),
|
||||
Status: originTakerLendingItem.Status,
|
||||
UpdatedAt: originTakerLendingItem.UpdatedAt,
|
||||
}
|
||||
}
|
||||
if originTakerLendingItem != nil {
|
||||
updatedTakerLendingItem = originTakerLendingItem
|
||||
} else {
|
||||
updatedTakerLendingItem = takerLendingItem
|
||||
updatedTakerLendingItem.FilledAmount = new(big.Int)
|
||||
}
|
||||
|
||||
if takerLendingItem.Status == lendingstate.LendingStatusNew {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusOpen
|
||||
} else if takerLendingItem.Status == lendingstate.LendingStatusCancelled {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusCancelled
|
||||
updatedTakerLendingItem.ExtraData = takerLendingItem.ExtraData
|
||||
}
|
||||
updatedTakerLendingItem.TxHash = txHash
|
||||
if updatedTakerLendingItem.CreatedAt.IsZero() {
|
||||
updatedTakerLendingItem.CreatedAt = txMatchTime
|
||||
}
|
||||
if txMatchTime.Before(updatedTakerLendingItem.UpdatedAt) || (txMatchTime.Equal(updatedTakerLendingItem.UpdatedAt) && *dirtyOrderCount == 0) {
|
||||
log.Debug("Ignore old lendingItem/lendingTrades taker", "txHash", txHash.Hex(), "txTime", txMatchTime.UnixNano(), "updatedAt", updatedTakerLendingItem.UpdatedAt.UnixNano())
|
||||
return nil
|
||||
}
|
||||
*dirtyOrderCount++
|
||||
|
||||
l.UpdateLendingItemCache(updatedTakerLendingItem.LendingToken, updatedTakerLendingItem.CollateralToken, updatedTakerLendingItem.Hash, txHash, lastState)
|
||||
updatedTakerLendingItem.UpdatedAt = txMatchTime
|
||||
|
||||
// 2. put trades to database and update status
|
||||
log.Debug("Got lendingTrades", "number", len(trades), "txhash", txHash.Hex())
|
||||
makerDirtyFilledAmount = make(map[string]*big.Int)
|
||||
|
||||
tradeList := map[common.Hash]*lendingstate.LendingTrade{}
|
||||
for _, tradeRecord := range trades {
|
||||
// 2.a. put to trades
|
||||
if tradeRecord == nil {
|
||||
continue
|
||||
}
|
||||
if updatedTakerLendingItem.Type == lendingstate.Repay || updatedTakerLendingItem.Type == lendingstate.TopUp || updatedTakerLendingItem.Type == lendingstate.Recall {
|
||||
// repay, topup: assign hash = trade.hash
|
||||
updatedTakerLendingItem.Hash = tradeRecord.Hash
|
||||
updatedTakerLendingItem.CollateralToken = tradeRecord.CollateralToken
|
||||
updatedTakerLendingItem.FilledAmount = updatedTakerLendingItem.Quantity
|
||||
updatedTakerLendingItem.Interest = new(big.Int).SetUint64(tradeRecord.Interest)
|
||||
switch updatedTakerLendingItem.Type {
|
||||
case lendingstate.TopUp:
|
||||
updatedTakerLendingItem.Status = lendingstate.TopUp
|
||||
extraData, _ := json.Marshal(struct {
|
||||
Price *big.Int
|
||||
}{
|
||||
Price: new(big.Int).Div(new(big.Int).Mul(tradeRecord.LiquidationPrice, tradeRecord.DepositRate), tradeRecord.LiquidationRate),
|
||||
})
|
||||
updatedTakerLendingItem.ExtraData = string(extraData)
|
||||
// manual topUp item
|
||||
updatedTakerLendingItem.AutoTopUp = false
|
||||
case lendingstate.Repay:
|
||||
updatedTakerLendingItem.Status = lendingstate.Repay
|
||||
paymentBalance := lendingstate.CalculateTotalRepayValue(block.Time(), tradeRecord.LiquidationTime, tradeRecord.Term, tradeRecord.Interest, tradeRecord.Amount)
|
||||
updatedTakerLendingItem.Quantity = paymentBalance
|
||||
updatedTakerLendingItem.FilledAmount = paymentBalance
|
||||
// manual repay item
|
||||
updatedTakerLendingItem.AutoTopUp = false
|
||||
case lendingstate.Recall:
|
||||
updatedTakerLendingItem.Status = lendingstate.Recall
|
||||
// manual recall item
|
||||
updatedTakerLendingItem.AutoTopUp = false
|
||||
}
|
||||
|
||||
log.Debug("UpdateLendingTrade:", "type", updatedTakerLendingItem.Type, "hash", tradeRecord.Hash.Hex(), "status", tradeRecord.Status, "tradeId", tradeRecord.TradeId)
|
||||
tradeList[tradeRecord.Hash] = tradeRecord
|
||||
continue
|
||||
|
||||
}
|
||||
if tradeRecord.CreatedAt.IsZero() {
|
||||
tradeRecord.CreatedAt = txMatchTime
|
||||
}
|
||||
tradeRecord.UpdatedAt = txMatchTime
|
||||
tradeRecord.TxHash = txHash
|
||||
tradeRecord.Hash = tradeRecord.ComputeHash()
|
||||
tradeList[tradeRecord.Hash] = tradeRecord
|
||||
|
||||
// 2.b. update status and filledAmount
|
||||
filledAmount := new(big.Int)
|
||||
if tradeRecord.Amount != nil {
|
||||
filledAmount = lendingstate.CloneBigInt(tradeRecord.Amount)
|
||||
}
|
||||
// maker dirty order
|
||||
makerFilledAmount := big.NewInt(0)
|
||||
var makerOrderHash common.Hash
|
||||
if updatedTakerLendingItem.Side == lendingstate.Borrowing {
|
||||
makerOrderHash = tradeRecord.InvestingOrderHash
|
||||
} else {
|
||||
makerOrderHash = tradeRecord.BorrowingOrderHash
|
||||
}
|
||||
if amount, ok := makerDirtyFilledAmount[makerOrderHash.Hex()]; ok {
|
||||
makerFilledAmount = lendingstate.CloneBigInt(amount)
|
||||
}
|
||||
makerFilledAmount = new(big.Int).Add(makerFilledAmount, filledAmount)
|
||||
makerDirtyFilledAmount[makerOrderHash.Hex()] = makerFilledAmount
|
||||
makerDirtyHashes = append(makerDirtyHashes, makerOrderHash.Hex())
|
||||
|
||||
if updatedTakerLendingItem.Type == lendingstate.Limit || updatedTakerLendingItem.Type == lendingstate.Market {
|
||||
//updatedTakerOrder = l.updateMatchedOrder(updatedTakerOrder, filledAmount, txMatchTime, txHash)
|
||||
// update filledAmount, status of takerOrder
|
||||
updatedTakerLendingItem.FilledAmount = new(big.Int).Add(updatedTakerLendingItem.FilledAmount, filledAmount)
|
||||
if updatedTakerLendingItem.FilledAmount.Cmp(updatedTakerLendingItem.Quantity) < 0 && updatedTakerLendingItem.Type == lendingstate.Limit {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusPartialFilled
|
||||
} else {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusFilled
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := l.UpdateLendingTrade(tradeList, txHash, txMatchTime); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// for Market orders
|
||||
// filledAmount > 0 : FILLED
|
||||
// otherwise: REJECTED
|
||||
if updatedTakerLendingItem.Type == lendingstate.Market {
|
||||
if updatedTakerLendingItem.FilledAmount.Sign() > 0 {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusFilled
|
||||
} else {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusReject
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug("PutObject processed takerLendingItem",
|
||||
"term", updatedTakerLendingItem.Term, "userAddr", updatedTakerLendingItem.UserAddress.Hex(), "side", updatedTakerLendingItem.Side,
|
||||
"Interest", updatedTakerLendingItem.Interest, "quantity", updatedTakerLendingItem.Quantity, "filledAmount", updatedTakerLendingItem.FilledAmount, "status", updatedTakerLendingItem.Status,
|
||||
"hash", updatedTakerLendingItem.Hash.Hex(), "txHash", updatedTakerLendingItem.TxHash.Hex())
|
||||
|
||||
if !(updatedTakerLendingItem.Type == lendingstate.Repay || updatedTakerLendingItem.Type == lendingstate.TopUp || updatedTakerLendingItem.Type == lendingstate.Recall) || updatedTakerLendingItem.Status != lendingstate.LendingStatusOpen {
|
||||
if err := db.PutObject(updatedTakerLendingItem.Hash, updatedTakerLendingItem); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to put processed takerOrder. Hash: %s Error: %s", updatedTakerLendingItem.Hash.Hex(), err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
items := db.GetListItemByHashes(makerDirtyHashes, &lendingstate.LendingItem{})
|
||||
if items != nil {
|
||||
makerItems := items.([]*lendingstate.LendingItem)
|
||||
log.Debug("Maker dirty lendingItem", "len", len(makerItems), "txhash", txHash.Hex())
|
||||
for _, m := range makerItems {
|
||||
if txMatchTime.Before(m.UpdatedAt) {
|
||||
log.Debug("Ignore old lendingItem/lendingTrades maker", "txHash", txHash.Hex(), "txTime", txMatchTime.UnixNano(), "updatedAt", m.UpdatedAt.UnixNano())
|
||||
continue
|
||||
}
|
||||
lastState = lendingstate.LendingItemHistoryItem{
|
||||
TxHash: m.TxHash,
|
||||
FilledAmount: lendingstate.CloneBigInt(m.FilledAmount),
|
||||
Status: m.Status,
|
||||
UpdatedAt: m.UpdatedAt,
|
||||
}
|
||||
l.UpdateLendingItemCache(m.LendingToken, m.CollateralToken, m.Hash, txHash, lastState)
|
||||
m.TxHash = txHash
|
||||
m.UpdatedAt = txMatchTime
|
||||
m.FilledAmount = new(big.Int).Add(m.FilledAmount, makerDirtyFilledAmount[m.Hash.Hex()])
|
||||
if m.FilledAmount.Cmp(m.Quantity) < 0 {
|
||||
m.Status = lendingstate.LendingStatusPartialFilled
|
||||
} else {
|
||||
m.Status = lendingstate.LendingStatusFilled
|
||||
}
|
||||
log.Debug("PutObject processed makerLendingItem",
|
||||
"term", m.Term, "userAddr", m.UserAddress.Hex(), "side", m.Side,
|
||||
"Interest", m.Interest, "quantity", m.Quantity, "filledAmount", m.FilledAmount, "status", m.Status,
|
||||
"hash", m.Hash.Hex(), "txHash", m.TxHash.Hex())
|
||||
if err := db.PutObject(m.Hash, m); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to put processed makerOrder. Hash: %s Error: %s", m.Hash.Hex(), err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. put rejected orders to leveldb and update status REJECTED
|
||||
log.Debug("Got rejected lendingItems", "number", len(rejectedItems), "rejectedLendingItems", rejectedItems)
|
||||
|
||||
if len(rejectedItems) > 0 {
|
||||
var rejectedHashes []string
|
||||
// updateRejectedOrders
|
||||
for _, r := range rejectedItems {
|
||||
rejectedHashes = append(rejectedHashes, r.Hash.Hex())
|
||||
if updatedTakerLendingItem.Hash == r.Hash && !txMatchTime.Before(r.UpdatedAt) {
|
||||
// cache r history for handling reorg
|
||||
historyRecord := lendingstate.LendingItemHistoryItem{
|
||||
TxHash: updatedTakerLendingItem.TxHash,
|
||||
FilledAmount: lendingstate.CloneBigInt(updatedTakerLendingItem.FilledAmount),
|
||||
Status: updatedTakerLendingItem.Status,
|
||||
UpdatedAt: updatedTakerLendingItem.UpdatedAt,
|
||||
}
|
||||
l.UpdateLendingItemCache(updatedTakerLendingItem.LendingToken, updatedTakerLendingItem.CollateralToken, updatedTakerLendingItem.Hash, txHash, historyRecord)
|
||||
// if whole order is rejected, status = REJECTED
|
||||
// otherwise, status = FILLED
|
||||
if updatedTakerLendingItem.FilledAmount.Sign() > 0 {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusFilled
|
||||
} else {
|
||||
updatedTakerLendingItem.Status = lendingstate.LendingStatusReject
|
||||
}
|
||||
updatedTakerLendingItem.TxHash = txHash
|
||||
updatedTakerLendingItem.UpdatedAt = txMatchTime
|
||||
if err := db.PutObject(updatedTakerLendingItem.Hash, updatedTakerLendingItem); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to reject takerOrder. Hash: %s Error: %s", updatedTakerLendingItem.Hash.Hex(), err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
items := db.GetListItemByHashes(rejectedHashes, &lendingstate.LendingItem{})
|
||||
if items != nil {
|
||||
dirtyRejectedItems := items.([]*lendingstate.LendingItem)
|
||||
for _, r := range dirtyRejectedItems {
|
||||
if txMatchTime.Before(r.UpdatedAt) {
|
||||
log.Debug("Ignore old orders/trades reject", "txHash", txHash.Hex(), "txTime", txMatchTime.UnixNano(), "updatedAt", updatedTakerLendingItem.UpdatedAt.UnixNano())
|
||||
continue
|
||||
}
|
||||
// cache lendingItem for handling reorg
|
||||
historyRecord := lendingstate.LendingItemHistoryItem{
|
||||
TxHash: r.TxHash,
|
||||
FilledAmount: lendingstate.CloneBigInt(r.FilledAmount),
|
||||
Status: r.Status,
|
||||
UpdatedAt: r.UpdatedAt,
|
||||
}
|
||||
l.UpdateLendingItemCache(r.LendingToken, r.CollateralToken, r.Hash, txHash, historyRecord)
|
||||
dirtyFilledAmount, ok := makerDirtyFilledAmount[r.Hash.Hex()]
|
||||
if ok && dirtyFilledAmount != nil {
|
||||
r.FilledAmount = new(big.Int).Add(r.FilledAmount, dirtyFilledAmount)
|
||||
}
|
||||
// if whole order is rejected, status = REJECTED
|
||||
// otherwise, status = FILLED
|
||||
if r.FilledAmount.Sign() > 0 {
|
||||
r.Status = lendingstate.LendingStatusFilled
|
||||
} else {
|
||||
r.Status = lendingstate.LendingStatusReject
|
||||
}
|
||||
r.TxHash = txHash
|
||||
r.UpdatedAt = txMatchTime
|
||||
if err = db.PutObject(r.Hash, r); err != nil {
|
||||
return fmt.Errorf("SDKNode: failed to update rejectedOder to sdkNode %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.CommitLendingBulk(); err != nil {
|
||||
return fmt.Errorf("SDKNode fail to commit bulk update lendingItem/lendingTrades at txhash %s . Error: %s", txHash.Hex(), err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Lending) UpdateLiquidatedTrade(blockTime uint64, result lendingstate.FinalizedResult, trades map[common.Hash]*lendingstate.LendingTrade) error {
|
||||
db := l.GetMongoDB()
|
||||
db.InitLendingBulk()
|
||||
|
||||
txhash := result.TxHash
|
||||
txTime := time.Unix(int64(blockTime), 0).UTC()
|
||||
if err := l.UpdateLendingTrade(trades, txhash, txTime); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// adding auto repay transaction
|
||||
if len(result.AutoRepay) > 0 {
|
||||
for _, hash := range result.AutoRepay {
|
||||
trade := trades[hash]
|
||||
if trade == nil {
|
||||
continue
|
||||
}
|
||||
paymentBalance := lendingstate.CalculateTotalRepayValue(blockTime, trade.LiquidationTime, trade.Term, trade.Interest, trade.Amount)
|
||||
repayItem := &lendingstate.LendingItem{
|
||||
Quantity: paymentBalance,
|
||||
Interest: big.NewInt(int64(trade.Interest)),
|
||||
Side: "",
|
||||
Type: lendingstate.Repay,
|
||||
LendingToken: trade.LendingToken,
|
||||
CollateralToken: trade.CollateralToken,
|
||||
FilledAmount: paymentBalance,
|
||||
Status: lendingstate.Repay,
|
||||
Relayer: trade.BorrowingRelayer,
|
||||
Term: trade.Term,
|
||||
UserAddress: trade.Borrower,
|
||||
Signature: nil,
|
||||
Hash: trade.Hash,
|
||||
TxHash: txhash,
|
||||
Nonce: nil,
|
||||
CreatedAt: txTime,
|
||||
UpdatedAt: txTime,
|
||||
LendingId: 0,
|
||||
LendingTradeId: trade.TradeId,
|
||||
AutoTopUp: true, // auto repay
|
||||
ExtraData: "",
|
||||
}
|
||||
if err := db.PutObject(repayItem.Hash, repayItem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adding auto topup transaction
|
||||
if len(result.AutoTopUp) > 0 {
|
||||
oldTradeHashes := []string{}
|
||||
for _, hash := range result.AutoTopUp {
|
||||
oldTradeHashes = append(oldTradeHashes, hash.Hex())
|
||||
}
|
||||
items := db.GetListItemByHashes(oldTradeHashes, &lendingstate.LendingTrade{})
|
||||
if items != nil && len(items.([]*lendingstate.LendingTrade)) > 0 {
|
||||
for _, oldTrade := range items.([]*lendingstate.LendingTrade) {
|
||||
newTrade := trades[oldTrade.Hash]
|
||||
topUpAmount := new(big.Int).Sub(newTrade.CollateralLockedAmount, oldTrade.CollateralLockedAmount)
|
||||
extraData, _ := json.Marshal(struct {
|
||||
Price *big.Int
|
||||
}{
|
||||
Price: new(big.Int).Div(new(big.Int).Mul(newTrade.LiquidationPrice, common.BaseTopUp), common.RateTopUp),
|
||||
})
|
||||
topUpItem := &lendingstate.LendingItem{
|
||||
Quantity: topUpAmount,
|
||||
Interest: big.NewInt(int64(oldTrade.Interest)),
|
||||
Side: "",
|
||||
Type: lendingstate.TopUp,
|
||||
LendingToken: oldTrade.LendingToken,
|
||||
CollateralToken: oldTrade.CollateralToken,
|
||||
FilledAmount: topUpAmount,
|
||||
Status: lendingstate.TopUp,
|
||||
AutoTopUp: true, // auto topup
|
||||
Relayer: oldTrade.BorrowingRelayer,
|
||||
Term: oldTrade.Term,
|
||||
UserAddress: oldTrade.Borrower,
|
||||
Signature: nil,
|
||||
Hash: oldTrade.Hash,
|
||||
TxHash: txhash,
|
||||
Nonce: nil,
|
||||
CreatedAt: txTime,
|
||||
UpdatedAt: txTime,
|
||||
LendingId: 0,
|
||||
LendingTradeId: oldTrade.TradeId,
|
||||
ExtraData: string(extraData),
|
||||
}
|
||||
if err := db.PutObject(topUpItem.Hash, topUpItem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adding auto recall transaction
|
||||
if len(result.AutoRecall) > 0 {
|
||||
oldTradeHashes := []string{}
|
||||
for _, hash := range result.AutoRecall {
|
||||
oldTradeHashes = append(oldTradeHashes, hash.Hex())
|
||||
}
|
||||
items := db.GetListItemByHashes(oldTradeHashes, &lendingstate.LendingTrade{})
|
||||
if items != nil && len(items.([]*lendingstate.LendingTrade)) > 0 {
|
||||
for _, oldTrade := range items.([]*lendingstate.LendingTrade) {
|
||||
newTrade := trades[oldTrade.Hash]
|
||||
recallAmount := new(big.Int).Sub(oldTrade.CollateralLockedAmount, newTrade.CollateralLockedAmount)
|
||||
extraData, _ := json.Marshal(struct {
|
||||
Price *big.Int
|
||||
}{
|
||||
Price: new(big.Int).Div(new(big.Int).Mul(newTrade.LiquidationPrice, oldTrade.DepositRate), oldTrade.LiquidationRate),
|
||||
})
|
||||
topUpItem := &lendingstate.LendingItem{
|
||||
Quantity: recallAmount,
|
||||
Interest: big.NewInt(int64(oldTrade.Interest)),
|
||||
Side: "",
|
||||
Type: lendingstate.Recall,
|
||||
LendingToken: oldTrade.LendingToken,
|
||||
CollateralToken: oldTrade.CollateralToken,
|
||||
FilledAmount: recallAmount,
|
||||
Status: lendingstate.Recall,
|
||||
AutoTopUp: true, // auto recall
|
||||
Relayer: oldTrade.BorrowingRelayer,
|
||||
Term: oldTrade.Term,
|
||||
UserAddress: oldTrade.Borrower,
|
||||
Signature: nil,
|
||||
Hash: oldTrade.Hash,
|
||||
TxHash: txhash,
|
||||
Nonce: nil,
|
||||
CreatedAt: txTime,
|
||||
UpdatedAt: txTime,
|
||||
LendingId: 0,
|
||||
LendingTradeId: oldTrade.TradeId,
|
||||
ExtraData: string(extraData),
|
||||
}
|
||||
if err := db.PutObject(topUpItem.Hash, topUpItem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.CommitLendingBulk(); err != nil {
|
||||
return fmt.Errorf("failed to updateLendingTrade . Err: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Lending) UpdateLendingTrade(trades map[common.Hash]*lendingstate.LendingTrade, txhash common.Hash, txTime time.Time) error {
|
||||
db := l.GetMongoDB()
|
||||
hashQuery := []string{}
|
||||
if len(trades) == 0 {
|
||||
return nil
|
||||
}
|
||||
for _, trade := range trades {
|
||||
hashQuery = append(hashQuery, trade.Hash.Hex())
|
||||
}
|
||||
items := db.GetListItemByHashes(hashQuery, &lendingstate.LendingTrade{})
|
||||
if items != nil && len(items.([]*lendingstate.LendingTrade)) > 0 {
|
||||
for _, trade := range items.([]*lendingstate.LendingTrade) {
|
||||
history := lendingstate.LendingTradeHistoryItem{
|
||||
TxHash: trade.TxHash,
|
||||
CollateralLockedAmount: trade.CollateralLockedAmount,
|
||||
LiquidationPrice: trade.LiquidationPrice,
|
||||
Status: trade.Status,
|
||||
UpdatedAt: trade.UpdatedAt,
|
||||
}
|
||||
l.UpdateLendingTradeCache(trade.Hash, txhash, history)
|
||||
trade.TxHash = txhash
|
||||
trade.UpdatedAt = txTime
|
||||
|
||||
newTrade := trades[trade.Hash]
|
||||
trade.CollateralLockedAmount = newTrade.CollateralLockedAmount
|
||||
trade.Status = newTrade.Status
|
||||
trade.LiquidationPrice = newTrade.LiquidationPrice
|
||||
trade.ExtraData = newTrade.ExtraData
|
||||
|
||||
if err := db.PutObject(trade.Hash, trade); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Debug("UpdateLendingTrade successfully", "txhash", txhash, "hash", hashQuery)
|
||||
} else {
|
||||
// not update, just upsert
|
||||
for _, trade := range trades {
|
||||
if err := db.PutObject(trade.Hash, trade); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Lending) GetLendingState(block *types.Block, author common.Address) (*lendingstate.LendingStateDB, error) {
|
||||
root, err := l.GetLendingStateRoot(block, author)
|
||||
if err != nil {
|
||||
|
|
@ -690,86 +216,6 @@ func (l *Lending) UpdateLendingTradeCache(hash common.Hash, txhash common.Hash,
|
|||
l.lendingTradeHistory.Add(txhash, lendingCacheAtTxHash)
|
||||
}
|
||||
|
||||
func (l *Lending) RollbackLendingData(txhash common.Hash) error {
|
||||
db := l.GetMongoDB()
|
||||
db.InitLendingBulk()
|
||||
|
||||
// rollback lendingItem
|
||||
items := db.GetListItemByTxHash(txhash, &lendingstate.LendingItem{})
|
||||
if items != nil {
|
||||
for _, item := range items.([]*lendingstate.LendingItem) {
|
||||
cacheAtTxHash, ok := l.lendingItemHistory.Get(txhash)
|
||||
log.Debug("XDCxlending reorg: rollback lendingItem", "txhash", txhash.Hex(), "item", lendingstate.ToJSON(item), "lendingItemHistory", cacheAtTxHash)
|
||||
if !ok || cacheAtTxHash == nil {
|
||||
log.Debug("XDCxlending reorg: remove item due to no lendingItemHistory", "item", lendingstate.ToJSON(item))
|
||||
if err := db.DeleteObject(item.Hash, &lendingstate.LendingItem{}); err != nil {
|
||||
return fmt.Errorf("failed to remove reorg LendingItem. Err: %v . Item: %s", err.Error(), lendingstate.ToJSON(item))
|
||||
}
|
||||
continue
|
||||
}
|
||||
lendingItemHistory := cacheAtTxHash[lendingstate.GetLendingItemHistoryKey(item.LendingToken, item.CollateralToken, item.Hash)]
|
||||
if (lendingItemHistory == lendingstate.LendingItemHistoryItem{}) {
|
||||
log.Debug("XDCxlending reorg: remove item due to empty lendingItemHistory", "item", lendingstate.ToJSON(item))
|
||||
if err := db.DeleteObject(item.Hash, &lendingstate.LendingItem{}); err != nil {
|
||||
return fmt.Errorf("failed to remove reorg LendingItem. Err: %v . Item: %s", err.Error(), lendingstate.ToJSON(item))
|
||||
}
|
||||
continue
|
||||
}
|
||||
item.TxHash = lendingItemHistory.TxHash
|
||||
item.Status = lendingItemHistory.Status
|
||||
item.FilledAmount = lendingstate.CloneBigInt(lendingItemHistory.FilledAmount)
|
||||
item.UpdatedAt = lendingItemHistory.UpdatedAt
|
||||
log.Debug("XDCxlending reorg: update item to the last lendingItemHistory", "item", lendingstate.ToJSON(item), "lendingItemHistory", lendingItemHistory)
|
||||
if err := db.PutObject(item.Hash, item); err != nil {
|
||||
return fmt.Errorf("failed to update reorg LendingItem. Err: %v . Item: %s", err.Error(), lendingstate.ToJSON(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rollback lendingTrade
|
||||
items = db.GetListItemByTxHash(txhash, &lendingstate.LendingTrade{})
|
||||
if items != nil {
|
||||
for _, trade := range items.([]*lendingstate.LendingTrade) {
|
||||
cacheAtTxHash, ok := l.lendingTradeHistory.Get(txhash)
|
||||
log.Debug("XDCxlending reorg: rollback LendingTrade", "txhash", txhash.Hex(), "trade", lendingstate.ToJSON(trade), "LendingTradeHistory", cacheAtTxHash)
|
||||
if !ok || cacheAtTxHash == nil {
|
||||
log.Debug("XDCxlending reorg: remove trade due to no LendingTradeHistory", "trade", lendingstate.ToJSON(trade))
|
||||
if err := db.DeleteObject(trade.Hash, &lendingstate.LendingTrade{}); err != nil {
|
||||
return fmt.Errorf("failed to remove reorg LendingTrade. Err: %v . Trade: %s", err.Error(), lendingstate.ToJSON(trade))
|
||||
}
|
||||
continue
|
||||
}
|
||||
lendingTradeHistoryItem := cacheAtTxHash[trade.Hash]
|
||||
if (lendingTradeHistoryItem == lendingstate.LendingTradeHistoryItem{}) {
|
||||
log.Debug("XDCxlending reorg: remove trade due to empty LendingTradeHistory", "trade", lendingstate.ToJSON(trade))
|
||||
if err := db.DeleteObject(trade.Hash, &lendingstate.LendingTrade{}); err != nil {
|
||||
return fmt.Errorf("failed to remove reorg LendingTrade. Err: %v . Trade: %s", err.Error(), lendingstate.ToJSON(trade))
|
||||
}
|
||||
continue
|
||||
}
|
||||
trade.TxHash = lendingTradeHistoryItem.TxHash
|
||||
trade.Status = lendingTradeHistoryItem.Status
|
||||
trade.CollateralLockedAmount = lendingstate.CloneBigInt(lendingTradeHistoryItem.CollateralLockedAmount)
|
||||
trade.LiquidationPrice = lendingstate.CloneBigInt(lendingTradeHistoryItem.LiquidationPrice)
|
||||
trade.UpdatedAt = lendingTradeHistoryItem.UpdatedAt
|
||||
log.Debug("XDCxlending reorg: update trade to the last lendingTradeHistoryItem", "trade", lendingstate.ToJSON(trade), "lendingTradeHistoryItem", lendingTradeHistoryItem)
|
||||
if err := db.PutObject(trade.Hash, trade); err != nil {
|
||||
return fmt.Errorf("failed to update reorg LendingTrade. Err: %v . Trade: %s", err.Error(), lendingstate.ToJSON(trade))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove repay/topup/recall history
|
||||
db.DeleteItemByTxHash(txhash, &lendingstate.LendingItem{Type: lendingstate.Repay})
|
||||
db.DeleteItemByTxHash(txhash, &lendingstate.LendingItem{Type: lendingstate.TopUp})
|
||||
db.DeleteItemByTxHash(txhash, &lendingstate.LendingItem{Type: lendingstate.Recall})
|
||||
|
||||
if err := db.CommitLendingBulk(); err != nil {
|
||||
return fmt.Errorf("failed to RollbackLendingData. %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Lending) ProcessLiquidationData(header *types.Header, chain consensus.ChainContext, statedb *state.StateDB, tradingState *tradingstate.TradingStateDB, lendingState *lendingstate.LendingStateDB) (updatedTrades map[common.Hash]*lendingstate.LendingTrade, liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades []*lendingstate.LendingTrade, err error) {
|
||||
time := new(big.Int).SetUint64(header.Time)
|
||||
updatedTrades = map[common.Hash]*lendingstate.LendingTrade{} // sum of liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades
|
||||
|
|
|
|||
|
|
@ -71,10 +71,6 @@ var (
|
|||
utils.USBFlag,
|
||||
utils.SmartCardDaemonPathFlag,
|
||||
utils.EnablePersonal,
|
||||
utils.XDCXEnabledFlag,
|
||||
utils.XDCXDBEngineFlag,
|
||||
utils.XDCXDBConnectionUrlFlag,
|
||||
utils.XDCXDBReplicaSetNameFlag,
|
||||
utils.XDCXDBNameFlag,
|
||||
utils.TxPoolNoLocalsFlag,
|
||||
utils.TxPoolJournalFlag,
|
||||
|
|
|
|||
|
|
@ -845,18 +845,6 @@ var (
|
|||
}
|
||||
|
||||
// XDCX settings
|
||||
XDCXEnabledFlag = &cli.BoolFlag{
|
||||
Name: "XDCx",
|
||||
Usage: "Enable the XDCX protocol",
|
||||
Category: flags.XdcxCategory,
|
||||
}
|
||||
XDCXDBEngineFlag = &cli.StringFlag{
|
||||
Name: "XDCx-dbengine",
|
||||
Aliases: []string{"XDCx.dbengine"},
|
||||
Usage: "Database engine for XDCX (leveldb, mongodb)",
|
||||
Value: "leveldb",
|
||||
Category: flags.XdcxCategory,
|
||||
}
|
||||
XDCXDBNameFlag = &cli.StringFlag{
|
||||
Name: "XDCx-dbName",
|
||||
Aliases: []string{"XDCx.dbName"},
|
||||
|
|
@ -864,19 +852,6 @@ var (
|
|||
Value: "XDCdex",
|
||||
Category: flags.XdcxCategory,
|
||||
}
|
||||
XDCXDBConnectionUrlFlag = &cli.StringFlag{
|
||||
Name: "XDCx-dbConnectionUrl",
|
||||
Aliases: []string{"XDCx.dbConnectionUrl"},
|
||||
Usage: "ConnectionUrl to database if dbEngine is mongodb. Host:port. If there are multiple instances, separated by comma. Eg: localhost:27017,localhost:27018",
|
||||
Value: "localhost:27017",
|
||||
Category: flags.XdcxCategory,
|
||||
}
|
||||
XDCXDBReplicaSetNameFlag = &cli.StringFlag{
|
||||
Name: "XDCx-dbReplicaSetName",
|
||||
Aliases: []string{"XDCx.dbReplicaSetName"},
|
||||
Usage: "ReplicaSetName if Master-Slave is setup",
|
||||
Category: flags.XdcxCategory,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -1475,24 +1450,11 @@ func SetXDCXConfig(ctx *cli.Context, cfg *XDCx.Config, XDCDataDir string) {
|
|||
// XDCx datadir: XDCDataDir/XDCx
|
||||
cfg.DataDir = filepath.Join(XDCDataDir, "XDCx")
|
||||
log.Info("XDCX datadir", "path", cfg.DataDir)
|
||||
if ctx.IsSet(XDCXDBEngineFlag.Name) {
|
||||
cfg.DBEngine = ctx.String(XDCXDBEngineFlag.Name)
|
||||
} else {
|
||||
cfg.DBEngine = XDCXDBEngineFlag.Value
|
||||
}
|
||||
if ctx.IsSet(XDCXDBNameFlag.Name) {
|
||||
cfg.DBName = ctx.String(XDCXDBNameFlag.Name)
|
||||
} else {
|
||||
cfg.DBName = XDCXDBNameFlag.Value
|
||||
}
|
||||
if ctx.IsSet(XDCXDBConnectionUrlFlag.Name) {
|
||||
cfg.ConnectionUrl = ctx.String(XDCXDBConnectionUrlFlag.Name)
|
||||
} else {
|
||||
cfg.ConnectionUrl = XDCXDBConnectionUrlFlag.Value
|
||||
}
|
||||
if ctx.IsSet(XDCXDBReplicaSetNameFlag.Name) {
|
||||
cfg.ReplicaSetName = ctx.String(XDCXDBReplicaSetNameFlag.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// SetEthConfig applies eth-related command line flags to the config.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package utils
|
|||
|
||||
import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
|
||||
|
|
@ -29,9 +28,6 @@ type TradingService interface {
|
|||
GetTriegc() *prque.Prque[int64, common.Hash]
|
||||
ApplyOrder(header *types.Header, coinbase common.Address, chain consensus.ChainContext, statedb *state.StateDB, XDCXstatedb *tradingstate.TradingStateDB, orderBook common.Hash, order *tradingstate.OrderItem) ([]map[string]string, []*tradingstate.OrderItem, error)
|
||||
UpdateMediumPriceBeforeEpoch(epochNumber uint64, tradingStateDB *tradingstate.TradingStateDB, statedb *state.StateDB) error
|
||||
IsSDKNode() bool
|
||||
SyncDataToSDKNode(takerOrder *tradingstate.OrderItem, txHash common.Hash, txMatchTime time.Time, statedb *state.StateDB, trades []map[string]string, rejectedOrders []*tradingstate.OrderItem, dirtyOrderCount *uint64) error
|
||||
RollbackReorgTxMatch(txhash common.Hash) error
|
||||
GetTokenDecimal(chain consensus.ChainContext, statedb *state.StateDB, tokenAddr common.Address) (*big.Int, error)
|
||||
}
|
||||
|
||||
|
|
@ -45,9 +41,6 @@ type LendingService interface {
|
|||
GetCollateralPrices(header *types.Header, chain consensus.ChainContext, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, collateralToken common.Address, lendingToken common.Address) (*big.Int, *big.Int, error)
|
||||
GetMediumTradePriceBeforeEpoch(chain consensus.ChainContext, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, baseToken common.Address, quoteToken common.Address) (*big.Int, error)
|
||||
ProcessLiquidationData(header *types.Header, chain consensus.ChainContext, statedb *state.StateDB, tradingState *tradingstate.TradingStateDB, lendingState *lendingstate.LendingStateDB) (updatedTrades map[common.Hash]*lendingstate.LendingTrade, liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades []*lendingstate.LendingTrade, err error)
|
||||
SyncDataToSDKNode(chain consensus.ChainContext, state *state.StateDB, block *types.Block, takerOrderInTx *lendingstate.LendingItem, txHash common.Hash, txMatchTime time.Time, trades []*lendingstate.LendingTrade, rejectedOrders []*lendingstate.LendingItem, dirtyOrderCount *uint64) error
|
||||
UpdateLiquidatedTrade(blockTime uint64, result lendingstate.FinalizedResult, trades map[common.Hash]*lendingstate.LendingTrade) error
|
||||
RollbackLendingData(txhash common.Hash) error
|
||||
}
|
||||
|
||||
type PublicApiSnapshot struct {
|
||||
|
|
|
|||
|
|
@ -138,9 +138,6 @@ func (v *BlockValidator) ValidateTradingOrder(statedb *state.StateDB, XDCxStated
|
|||
Rejects: newRejectedOrders,
|
||||
}
|
||||
}
|
||||
if XDCXService.IsSDKNode() {
|
||||
v.bc.AddMatchingResult(txMatchBatch.TxHash, tradingResult)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -173,9 +170,6 @@ func (v *BlockValidator) ValidateLendingOrder(statedb *state.StateDB, lendingSta
|
|||
Rejects: newRejectedOrders,
|
||||
}
|
||||
}
|
||||
if XDCXService.IsSDKNode() {
|
||||
v.bc.AddLendingResult(batch.TxHash, lendingResult)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1824,10 +1824,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
|
|||
// Only count canonical blocks for GC processing time
|
||||
bc.gcproc += res.procTime
|
||||
bc.UpdateBlocksHashCache(block)
|
||||
if bc.chainConfig.IsTIPXDCX(block.Number()) && bc.chainConfig.XDPoS != nil && block.NumberU64() > bc.chainConfig.XDPoS.Epoch {
|
||||
bc.logExchangeData(block)
|
||||
bc.logLendingData(block)
|
||||
}
|
||||
case SideStatTy:
|
||||
log.Debug("Inserted forked block from downloader", "number", block.Number(), "hash", block.Hash(), "diff", block.Difficulty(), "elapsed",
|
||||
common.PrettyDuration(time.Since(start)), "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()))
|
||||
|
|
@ -2282,10 +2278,6 @@ func (bc *BlockChain) insertBlock(block *types.Block) ([]interface{}, []*types.L
|
|||
// Only count canonical blocks for GC processing time
|
||||
bc.gcproc += result.proctime
|
||||
bc.UpdateBlocksHashCache(block)
|
||||
if bc.chainConfig.IsTIPXDCXReceiver(block.Number()) && bc.chainConfig.XDPoS != nil && block.NumberU64() > bc.chainConfig.XDPoS.Epoch {
|
||||
bc.logExchangeData(block)
|
||||
bc.logLendingData(block)
|
||||
}
|
||||
case SideStatTy:
|
||||
log.Debug("Inserted forked block from fetcher", "number", block.Number(), "hash", block.Hash(), "diff", block.Difficulty(), "elapsed",
|
||||
common.PrettyDuration(time.Since(block.ReceivedAt)), "txs", len(block.Transactions()), "gas", block.GasUsed(), "uncles", len(block.Uncles()))
|
||||
|
|
@ -2830,146 +2822,6 @@ func (bc *BlockChain) UpdateM1() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (bc *BlockChain) logExchangeData(block *types.Block) {
|
||||
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
||||
if !ok || engine == nil {
|
||||
return
|
||||
}
|
||||
XDCXService := engine.GetXDCXService()
|
||||
if XDCXService == nil || !XDCXService.IsSDKNode() {
|
||||
return
|
||||
}
|
||||
txMatchBatchData, err := ExtractTradingTransactions(block.Transactions())
|
||||
if err != nil {
|
||||
log.Error("failed to extract matching transaction", "err", err)
|
||||
return
|
||||
}
|
||||
if len(txMatchBatchData) == 0 {
|
||||
return
|
||||
}
|
||||
currentState, err := bc.State()
|
||||
if err != nil {
|
||||
log.Crit("logExchangeData: failed to get current state", "err", err)
|
||||
return
|
||||
}
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
//The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns
|
||||
// That's why we should put this log statement in an anonymous function
|
||||
log.Debug("logExchangeData takes", "time", common.PrettyDuration(time.Since(start)), "blockNumber", block.NumberU64())
|
||||
}()
|
||||
|
||||
for _, txMatchBatch := range txMatchBatchData {
|
||||
dirtyOrderCount := uint64(0)
|
||||
for _, txMatch := range txMatchBatch.Data {
|
||||
var (
|
||||
takerOrderInTx *tradingstate.OrderItem
|
||||
trades []map[string]string
|
||||
rejectedOrders []*tradingstate.OrderItem
|
||||
)
|
||||
|
||||
if takerOrderInTx, err = txMatch.DecodeOrder(); err != nil {
|
||||
log.Error("SDK node decode takerOrderInTx failed", "txDataMatch", txMatch)
|
||||
return
|
||||
}
|
||||
cacheKey := crypto.Keccak256Hash(txMatchBatch.TxHash.Bytes(), tradingstate.GetMatchingResultCacheKey(takerOrderInTx).Bytes())
|
||||
// getTrades from cache
|
||||
resultTrades, ok := bc.resultTrade.Get(cacheKey)
|
||||
if ok && resultTrades != nil {
|
||||
trades = resultTrades.([]map[string]string)
|
||||
}
|
||||
|
||||
// getRejectedOrder from cache
|
||||
rejected, ok := bc.rejectedOrders.Get(cacheKey)
|
||||
if ok && rejected != nil {
|
||||
rejectedOrders = rejected.([]*tradingstate.OrderItem)
|
||||
}
|
||||
|
||||
txMatchTime := time.Unix(int64(block.Header().Time), 0).UTC()
|
||||
if err := XDCXService.SyncDataToSDKNode(takerOrderInTx, txMatchBatch.TxHash, txMatchTime, currentState, trades, rejectedOrders, &dirtyOrderCount); err != nil {
|
||||
log.Error("failed to SyncDataToSDKNode ", "blockNumber", block.Number(), "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *BlockChain) logLendingData(block *types.Block) {
|
||||
engine, ok := bc.Engine().(*XDPoS.XDPoS)
|
||||
if !ok || engine == nil {
|
||||
return
|
||||
}
|
||||
XDCXService := engine.GetXDCXService()
|
||||
if XDCXService == nil || !XDCXService.IsSDKNode() {
|
||||
return
|
||||
}
|
||||
lendingService := engine.GetLendingService()
|
||||
if lendingService == nil {
|
||||
return
|
||||
}
|
||||
batches, err := ExtractLendingTransactions(block.Transactions())
|
||||
if err != nil {
|
||||
log.Error("failed to extract lending transaction", "err", err)
|
||||
return
|
||||
}
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
//The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns
|
||||
// That's why we should put this log statement in an anonymous function
|
||||
log.Debug("logLendingData takes", "time", common.PrettyDuration(time.Since(start)), "blockNumber", block.NumberU64())
|
||||
}()
|
||||
|
||||
for _, batch := range batches {
|
||||
dirtyOrderCount := uint64(0)
|
||||
for _, item := range batch.Data {
|
||||
var (
|
||||
trades []*lendingstate.LendingTrade
|
||||
rejectedOrders []*lendingstate.LendingItem
|
||||
)
|
||||
// getTrades from cache
|
||||
resultLendingTrades, ok := bc.resultLendingTrade.Get(crypto.Keccak256Hash(batch.TxHash.Bytes(), lendingstate.GetLendingCacheKey(item).Bytes()))
|
||||
|
||||
if ok && resultLendingTrades != nil {
|
||||
trades = resultLendingTrades.([]*lendingstate.LendingTrade)
|
||||
}
|
||||
|
||||
// getRejectedOrder from cache
|
||||
rejected, ok := bc.rejectedLendingItem.Get(crypto.Keccak256Hash(batch.TxHash.Bytes(), lendingstate.GetLendingCacheKey(item).Bytes()))
|
||||
if ok && rejected != nil {
|
||||
rejectedOrders = rejected.([]*lendingstate.LendingItem)
|
||||
}
|
||||
|
||||
txMatchTime := time.Unix(int64(block.Header().Time), 0).UTC()
|
||||
statedb, _ := bc.State()
|
||||
|
||||
if err := lendingService.SyncDataToSDKNode(bc, statedb.Copy(), block, item, batch.TxHash, txMatchTime, trades, rejectedOrders, &dirtyOrderCount); err != nil {
|
||||
log.Error("lending: failed to SyncDataToSDKNode ", "blockNumber", block.Number(), "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update finalizedTrades
|
||||
if block.Number().Uint64()%bc.chainConfig.XDPoS.Epoch == common.LiquidateLendingTradeBlock {
|
||||
finalizedTx, err := ExtractLendingFinalizedTradeTransactions(block.Transactions())
|
||||
if err != nil {
|
||||
log.Error("failed to extract finalizedTrades transaction", "err", err)
|
||||
return
|
||||
}
|
||||
finalizedTrades := map[common.Hash]*lendingstate.LendingTrade{}
|
||||
finalizedData, ok := bc.finalizedTrade.Get(finalizedTx.TxHash)
|
||||
if ok && finalizedData != nil {
|
||||
finalizedTrades = finalizedData.(map[common.Hash]*lendingstate.LendingTrade)
|
||||
}
|
||||
if len(finalizedTrades) > 0 {
|
||||
if err := lendingService.UpdateLiquidatedTrade(block.Time(), finalizedTx, finalizedTrades); err != nil {
|
||||
log.Error("lending: failed to UpdateLiquidatedTrade ", "blockNumber", block.Number(), "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *BlockChain) AddMatchingResult(txHash common.Hash, matchingResults map[common.Hash]tradingstate.MatchingResult) {
|
||||
for hash, result := range matchingResults {
|
||||
cacheKey := crypto.Keccak256Hash(txHash.Bytes(), hash.Bytes())
|
||||
|
|
@ -3078,17 +2930,10 @@ func (bc *BlockChain) processTradingAndLendingStates(isValidBlockNumber bool, bl
|
|||
}
|
||||
// liquidate / finalize open lendingTrades
|
||||
if block.Number().Uint64()%bc.chainConfig.XDPoS.Epoch == common.LiquidateLendingTradeBlock {
|
||||
finalizedTrades, _, _, _, _, err := lendingService.ProcessLiquidationData(block.Header(), bc, statedb, tradingState, lendingState)
|
||||
_, _, _, _, _, err := lendingService.ProcessLiquidationData(block.Header(), bc, statedb, tradingState, lendingState)
|
||||
if err != nil {
|
||||
return tradingState, lendingState, fmt.Errorf("failed to ProcessLiquidationData. Err: %v", err)
|
||||
}
|
||||
if tradingService.IsSDKNode() {
|
||||
finalizedTx, err := ExtractLendingFinalizedTradeTransactions(block.Transactions())
|
||||
if err != nil {
|
||||
return tradingState, lendingState, err
|
||||
}
|
||||
bc.AddFinalizedTrades(finalizedTx.TxHash, finalizedTrades)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -752,15 +752,11 @@ func (w *worker) commitNewWork() {
|
|||
var (
|
||||
txs *types.TransactionsByPriceAndNonce
|
||||
specialTxs types.Transactions
|
||||
tradingTransaction *types.Transaction
|
||||
lendingTransaction *types.Transaction
|
||||
tradingTxMatches []tradingstate.TxDataMatch
|
||||
tradingMatchingResults map[common.Hash]tradingstate.MatchingResult
|
||||
lendingMatchingResults map[common.Hash]lendingstate.MatchingResult
|
||||
lendingInput []*lendingstate.LendingItem
|
||||
updatedTrades map[common.Hash]*lendingstate.LendingTrade
|
||||
liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades []*lendingstate.LendingTrade
|
||||
lendingFinalizedTradeTransaction *types.Transaction
|
||||
)
|
||||
feeCapacity := state.GetTRC21FeeCapacityFromStateWithCache(parent.Root(), work.state)
|
||||
if w.config.XDPoS != nil {
|
||||
|
|
@ -800,7 +796,7 @@ func (w *worker) commitNewWork() {
|
|||
log.Debug("Start processing order pending")
|
||||
tradingOrderPending, _ := w.eth.OrderPool().Pending()
|
||||
log.Debug("Start processing order pending", "len", len(tradingOrderPending))
|
||||
tradingTxMatches, tradingMatchingResults = XDCX.ProcessOrderPending(header, w.coinbase, w.chain, tradingOrderPending, work.state, work.tradingState)
|
||||
tradingTxMatches, _ = XDCX.ProcessOrderPending(header, w.coinbase, w.chain, tradingOrderPending, work.state, work.tradingState)
|
||||
log.Debug("trading transaction matches found", "tradingTxMatches", len(tradingTxMatches))
|
||||
|
||||
lendingOrderPending, _ := w.eth.LendingPool().Pending()
|
||||
|
|
@ -832,15 +828,10 @@ func (w *worker) commitNewWork() {
|
|||
if err != nil {
|
||||
log.Error("Fail to create tx matches", "error", err)
|
||||
return
|
||||
} else {
|
||||
tradingTransaction = txM
|
||||
if XDCX.IsSDKNode() {
|
||||
w.chain.AddMatchingResult(tradingTransaction.Hash(), tradingMatchingResults)
|
||||
}
|
||||
// force adding trading, lending transaction to this block
|
||||
if tradingTransaction != nil {
|
||||
specialTxs = append(specialTxs, tradingTransaction)
|
||||
}
|
||||
}
|
||||
// force adding trading, lending transaction to this block
|
||||
if txM != nil {
|
||||
specialTxs = append(specialTxs, txM)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -862,14 +853,9 @@ func (w *worker) commitNewWork() {
|
|||
if err != nil {
|
||||
log.Error("Fail to create lending tx", "error", err)
|
||||
return
|
||||
} else {
|
||||
lendingTransaction = signedLendingTx
|
||||
if XDCX.IsSDKNode() {
|
||||
w.chain.AddLendingResult(lendingTransaction.Hash(), lendingMatchingResults)
|
||||
}
|
||||
if lendingTransaction != nil {
|
||||
specialTxs = append(specialTxs, lendingTransaction)
|
||||
}
|
||||
}
|
||||
if signedLendingTx != nil {
|
||||
specialTxs = append(specialTxs, signedLendingTx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -886,14 +872,9 @@ func (w *worker) commitNewWork() {
|
|||
if err != nil {
|
||||
log.Error("Fail to create lending tx", "error", err)
|
||||
return
|
||||
} else {
|
||||
lendingFinalizedTradeTransaction = signedFinalizedTx
|
||||
if XDCX.IsSDKNode() {
|
||||
w.chain.AddFinalizedTrades(lendingFinalizedTradeTransaction.Hash(), updatedTrades)
|
||||
}
|
||||
if lendingFinalizedTradeTransaction != nil {
|
||||
specialTxs = append(specialTxs, lendingFinalizedTradeTransaction)
|
||||
}
|
||||
}
|
||||
if signedFinalizedTx != nil {
|
||||
specialTxs = append(specialTxs, signedFinalizedTx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue