OSDN Git Service

fix match engine (#522)
authorPoseidon <shenao.78@163.com>
Wed, 25 Mar 2020 10:01:11 +0000 (18:01 +0800)
committerGitHub <noreply@github.com>
Wed, 25 Mar 2020 10:01:11 +0000 (18:01 +0800)
* fix match engine

* opt code

* opt code for add refund

application/mov/match/engine.go
application/mov/match/fee_strategy.go
application/mov/mov_core.go

index 77de111..4e5a029 100644 (file)
@@ -62,7 +62,7 @@ func (e *Engine) NextMatchedTx(tradePairs ...*common.TradePair) (*types.Tx, erro
        return tx, nil
 }
 
        return tx, nil
 }
 
-func (e *Engine) addMatchTxFeeOutput(txData *types.TxData, refunds []RefundAssets, fees []*bc.AssetAmount) error {
+func (e *Engine) addMatchTxFeeOutput(txData *types.TxData, refunds RefundAssets, fees []*bc.AssetAmount) error {
        for _, feeAmount := range fees {
                txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*feeAmount.AssetId, feeAmount.Amount, e.rewardProgram))
        }
        for _, feeAmount := range fees {
                txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*feeAmount.AssetId, feeAmount.Amount, e.rewardProgram))
        }
@@ -106,7 +106,7 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) {
 
        receivedAmounts, priceDiffs := CalcReceivedAmount(orders)
        allocatedAssets := e.feeStrategy.Allocate(receivedAmounts, priceDiffs)
 
        receivedAmounts, priceDiffs := CalcReceivedAmount(orders)
        allocatedAssets := e.feeStrategy.Allocate(receivedAmounts, priceDiffs)
-       if err := addMatchTxOutput(txData, orders, receivedAmounts, allocatedAssets.Receives); err != nil {
+       if err := addMatchTxOutput(txData, orders, receivedAmounts, allocatedAssets); err != nil {
                return nil, err
        }
 
                return nil, err
        }
 
@@ -123,22 +123,25 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) {
        return types.NewTx(*txData), nil
 }
 
        return types.NewTx(*txData), nil
 }
 
-func addMatchTxOutput(txData *types.TxData, orders []*common.Order, receivedAmounts, deductFeeReceives []*bc.AssetAmount) error {
+func addMatchTxOutput(txData *types.TxData, orders []*common.Order, receivedAmounts []*bc.AssetAmount, allocatedAssets *AllocatedAssets) error {
        for i, order := range orders {
                contractArgs, err := segwit.DecodeP2WMCProgram(order.Utxo.ControlProgram)
                if err != nil {
                        return err
                }
 
        for i, order := range orders {
                contractArgs, err := segwit.DecodeP2WMCProgram(order.Utxo.ControlProgram)
                if err != nil {
                        return err
                }
 
-               requestAmount := CalcRequestAmount(order.Utxo.Amount, contractArgs.RatioNumerator, contractArgs.RatioDenominator)
                receivedAmount := receivedAmounts[i].Amount
                shouldPayAmount := calcShouldPayAmount(receivedAmount, contractArgs.RatioNumerator, contractArgs.RatioDenominator)
                receivedAmount := receivedAmounts[i].Amount
                shouldPayAmount := calcShouldPayAmount(receivedAmount, contractArgs.RatioNumerator, contractArgs.RatioDenominator)
-               isPartialTrade := requestAmount > receivedAmount
 
 
-               setMatchTxArguments(txData.Inputs[i], isPartialTrade, len(txData.Outputs), receivedAmounts[i].Amount)
-               txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.ToAssetID, deductFeeReceives[i].Amount, contractArgs.SellerProgram))
+               exchangeAmount := order.Utxo.Amount - shouldPayAmount
+               isPartialTrade := CalcRequestAmount(exchangeAmount, contractArgs.RatioNumerator, contractArgs.RatioDenominator) >= 1
+
+               setMatchTxArguments(txData.Inputs[i], isPartialTrade, len(txData.Outputs), receivedAmount)
+               txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.ToAssetID, allocatedAssets.Receives[i].Amount, contractArgs.SellerProgram))
                if isPartialTrade {
                if isPartialTrade {
-                       txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.FromAssetID, order.Utxo.Amount-shouldPayAmount, order.Utxo.ControlProgram))
+                       txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.FromAssetID, exchangeAmount, order.Utxo.ControlProgram))
+               } else if exchangeAmount > 0 {
+                       allocatedAssets.Refunds.Add(i, *order.FromAssetID, exchangeAmount)
                }
        }
        return nil
                }
        }
        return nil
index f3d1dfc..70a58a6 100644 (file)
@@ -15,12 +15,27 @@ var (
 // AllocatedAssets represent reallocated assets after calculating fees
 type AllocatedAssets struct {
        Receives []*bc.AssetAmount
 // AllocatedAssets represent reallocated assets after calculating fees
 type AllocatedAssets struct {
        Receives []*bc.AssetAmount
-       Refunds  []RefundAssets
+       Refunds  RefundAssets
        Fees     []*bc.AssetAmount
 }
 
 // RefundAssets represent alias for assetAmount array, because each transaction participant can be refunded multiple assets
        Fees     []*bc.AssetAmount
 }
 
 // RefundAssets represent alias for assetAmount array, because each transaction participant can be refunded multiple assets
-type RefundAssets []*bc.AssetAmount
+type RefundAssets [][]*bc.AssetAmount
+
+// Add used to add a refund to specify order
+func (r RefundAssets) Add(index int, asset bc.AssetID, amount uint64) {
+       if index >= len(r) {
+               index = 0
+       }
+
+       for _, assetAmount := range r[index] {
+               if *assetAmount.AssetId == asset {
+                       assetAmount.Amount += amount
+                       return
+               }
+       }
+       r[index] = append(r[index], &bc.AssetAmount{AssetId: &asset, Amount: amount})
+}
 
 // FeeStrategy used to indicate how to charge a matching fee
 type FeeStrategy interface {
 
 // FeeStrategy used to indicate how to charge a matching fee
 type FeeStrategy interface {
@@ -50,7 +65,7 @@ func (d *DefaultFeeStrategy) Allocate(receiveAmounts, priceDiffs []*bc.AssetAmou
        }
 
        var fees []*bc.AssetAmount
        }
 
        var fees []*bc.AssetAmount
-       refunds := make([]RefundAssets, len(receiveAmounts))
+       refunds := make([][]*bc.AssetAmount, len(receiveAmounts))
        receives := make([]*bc.AssetAmount, len(receiveAmounts))
 
        for i, receiveAmount := range receiveAmounts {
        receives := make([]*bc.AssetAmount, len(receiveAmounts))
 
        for i, receiveAmount := range receiveAmounts {
index a6357bc..c4f7760 100644 (file)
@@ -162,11 +162,11 @@ func (m *Core) ValidateTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHe
        }
 
        if common.IsMatchedTx(tx) {
        }
 
        if common.IsMatchedTx(tx) {
-               if err := validateMatchedTx(tx, verifyResult, blockHeight); err != nil {
+               if err := validateMatchedTx(tx, blockHeight); err != nil {
                        return err
                }
        } else if common.IsCancelOrderTx(tx) {
                        return err
                }
        } else if common.IsCancelOrderTx(tx) {
-               if err := validateCancelOrderTx(tx, verifyResult); err != nil {
+               if err := validateCancelOrderTx(tx); err != nil {
                        return err
                }
        }
                        return err
                }
        }
@@ -220,7 +220,7 @@ func calcFeeAmount(matchedTx *types.Tx) (map[bc.AssetID]*matchedTxFee, error) {
        return assetFeeMap, nil
 }
 
        return assetFeeMap, nil
 }
 
-func validateCancelOrderTx(tx *types.Tx, verifyResult *bc.TxVerifyResult) error {
+func validateCancelOrderTx(tx *types.Tx) error {
        for _, input := range tx.Inputs {
                if !segwit.IsP2WMCScript(input.ControlProgram()) {
                        return errInputProgramMustP2WMCScript
        for _, input := range tx.Inputs {
                if !segwit.IsP2WMCScript(input.ControlProgram()) {
                        return errInputProgramMustP2WMCScript
@@ -253,7 +253,7 @@ func validateMagneticContractArgs(fromAssetAmount bc.AssetAmount, program []byte
        return nil
 }
 
        return nil
 }
 
-func validateMatchedTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHeight uint64) error {
+func validateMatchedTx(tx *types.Tx, blockHeight uint64) error {
        fromAssetIDMap := make(map[string]bool)
        toAssetIDMap := make(map[string]bool)
        for i, input := range tx.Inputs {
        fromAssetIDMap := make(map[string]bool)
        toAssetIDMap := make(map[string]bool)
        for i, input := range tx.Inputs {