return nil
}
- func getSortedTradePairsFromMatchedTx(tx *types.Tx) ([]*common.TradePair, error) {
- assetMap := make(map[bc.AssetID]bc.AssetID)
- var firstTradePair *common.TradePair
- for _, tx := range tx.Inputs {
- contractArgs, err := segwit.DecodeP2WMCProgram(tx.ControlProgram())
-
+ func validateSpendOrders(matchedTx *types.Tx, orders []*common.Order) error {
+ spendOutputIDs := make(map[string]bool)
+ for _, input := range matchedTx.Inputs {
+ spendOutputID, err := input.SpentOutputID()
if err != nil {
- return nil, err
+ return err
}
- assetMap[tx.AssetID()] = contractArgs.RequestedAsset
- if firstTradePair == nil {
- firstTradePair = &common.TradePair{FromAssetID: tx.AssetAmount().AssetId, ToAssetID: &contractArgs.RequestedAsset}
- }
+ spendOutputIDs[spendOutputID.String()] = true
}
- tradePairs := []*common.TradePair{firstTradePair}
- for tradePair := firstTradePair; *tradePair.ToAssetID != *firstTradePair.FromAssetID; {
- nextTradePairToAssetID, ok := assetMap[*tradePair.ToAssetID]
- if !ok {
- return nil, errInvalidTradePairs
+ for _, order := range orders {
+ outputID := order.UTXOHash().String()
+ if _, ok := spendOutputIDs[outputID]; !ok {
+ return errSpendOutputIDIsIncorrect
}
-
- tradePair = &common.TradePair{FromAssetID: tradePair.ToAssetID, ToAssetID: &nextTradePairToAssetID}
- tradePairs = append(tradePairs, tradePair)
- }
-
- if len(tradePairs) != len(tx.Inputs) {
- return nil, errInvalidTradePairs
- }
- return tradePairs, nil
- }
-
- // DetachBlock parse pending order and cancel from the the transactions of block
- // and add cancel order to the dex db, remove pending order from dex db.
- func (m *MovCore) DetachBlock(block *types.Block) error {
- if block.Height <= m.startBlockHeight {
- return nil
- }
-
- deleteOrders, addOrders, err := applyTransactions(block.Transactions)
- if err != nil {
- return err
}
-
- return m.movStore.ProcessOrders(addOrders, deleteOrders, &block.BlockHeader)
+ return nil
}
- // BeforeProposalBlock return all transactions than can be matched, and the number of transactions cannot exceed the given capacity.
- func (m *MovCore) BeforeProposalBlock(txs []*types.Tx, nodeProgram []byte, blockHeight uint64, gasLeft int64) ([]*types.Tx, int64, error) {
- if blockHeight <= m.startBlockHeight {
- return nil, 0, nil
- }
-
- orderTable, err := buildOrderTable(m.movStore, txs)
- if err != nil {
- return nil, 0, err
- }
-
- matchEngine := match.NewEngine(orderTable, maxFeeRate, nodeProgram)
- tradePairMap := make(map[string]bool)
- tradePairIterator := database.NewTradePairIterator(m.movStore)
+ func applyTransactions(txs []*types.Tx) ([]*common.Order, []*common.Order, error) {
+ deleteOrderMap := make(map[string]*common.Order)
+ addOrderMap := make(map[string]*common.Order)
+ for _, tx := range txs {
+ addOrders, err := getAddOrdersFromTx(tx)
+ if err != nil {
+ return nil, nil, err
+ }
- var packagedTxs []*types.Tx
- for gasLeft > 0 && tradePairIterator.HasNext() {
- tradePair := tradePairIterator.Next()
- if tradePairMap[tradePair.Key()] {
- continue
+ for _, order := range addOrders {
+ addOrderMap[order.Key()] = order
}
- tradePairMap[tradePair.Key()] = true
- tradePairMap[tradePair.Reverse().Key()] = true
- for gasLeft > 0 && matchEngine.HasMatchedTx(tradePair, tradePair.Reverse()) {
- matchedTx, err := matchEngine.NextMatchedTx(tradePair, tradePair.Reverse())
- if err != nil {
- return nil, 0, err
- }
+ deleteOrders, err := getDeleteOrdersFromTx(tx)
+ if err != nil {
+ return nil, nil, err
+ }
- gasUsed := calcMatchedTxGasUsed(matchedTx)
- if gasLeft-gasUsed >= 0 {
- packagedTxs = append(packagedTxs, matchedTx)
- }
- gasLeft -= gasUsed
+ for _, order := range deleteOrders {
+ deleteOrderMap[order.Key()] = order
}
}
- return packagedTxs, gasLeft, nil
- }
- func calcMatchedTxGasUsed(tx *types.Tx) int64 {
- return int64(len(tx.Inputs))*150 + int64(tx.SerializedSize)
+ addOrders, deleteOrders := mergeOrders(addOrderMap, deleteOrderMap)
+ return addOrders, deleteOrders, nil
}
- func buildOrderTable(store database.MovStore, txs []*types.Tx) (*match.OrderTable, error) {
+ func buildOrderBook(store database.MovStore, txs []*types.Tx) (*match.OrderBook, error) {
var nonMatchedTxs []*types.Tx
for _, tx := range txs {
if !common.IsMatchedTx(tx) {