From: Poseidon Date: Wed, 25 Mar 2020 10:01:11 +0000 (+0800) Subject: fix match engine (#522) X-Git-Tag: v1.1.0~2 X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=commitdiff_plain;h=d8b8c7fc9098830338a151592ff1f85f5f45fca5;ds=sidebyside fix match engine (#522) * fix match engine * opt code * opt code for add refund --- diff --git a/application/mov/match/engine.go b/application/mov/match/engine.go index 77de1113..4e5a0296 100644 --- a/application/mov/match/engine.go +++ b/application/mov/match/engine.go @@ -62,7 +62,7 @@ func (e *Engine) NextMatchedTx(tradePairs ...*common.TradePair) (*types.Tx, erro 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)) } @@ -106,7 +106,7 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) { 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 } @@ -123,22 +123,25 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) { 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 } - requestAmount := CalcRequestAmount(order.Utxo.Amount, 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 { - 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 diff --git a/application/mov/match/fee_strategy.go b/application/mov/match/fee_strategy.go index f3d1dfc3..70a58a6b 100644 --- a/application/mov/match/fee_strategy.go +++ b/application/mov/match/fee_strategy.go @@ -15,12 +15,27 @@ var ( // 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 -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 { @@ -50,7 +65,7 @@ func (d *DefaultFeeStrategy) Allocate(receiveAmounts, priceDiffs []*bc.AssetAmou } 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 { diff --git a/application/mov/mov_core.go b/application/mov/mov_core.go index a6357bc8..c4f77603 100644 --- a/application/mov/mov_core.go +++ b/application/mov/mov_core.go @@ -162,11 +162,11 @@ func (m *Core) ValidateTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHe } 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) { - if err := validateCancelOrderTx(tx, verifyResult); err != nil { + if err := validateCancelOrderTx(tx); err != nil { return err } } @@ -220,7 +220,7 @@ func calcFeeAmount(matchedTx *types.Tx) (map[bc.AssetID]*matchedTxFee, error) { 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 @@ -253,7 +253,7 @@ func validateMagneticContractArgs(fromAssetAmount bc.AssetAmount, program []byte 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 {