Golang implemented sidechain for Bytom
Revision | 64b4b3c98067ae87822c00e3a8e1286945eacf79 (tree) |
---|---|
Time | 2020-03-25 18:46:14 |
Author | shenao78 <shenao.78@163....> |
Commiter | shenao78 |
fix match engine
@@ -62,7 +62,7 @@ func (e *Engine) NextMatchedTx(tradePairs ...*common.TradePair) (*types.Tx, erro | ||
62 | 62 | return tx, nil |
63 | 63 | } |
64 | 64 | |
65 | -func (e *Engine) addMatchTxFeeOutput(txData *types.TxData, refunds []RefundAssets, fees []*bc.AssetAmount) error { | |
65 | +func (e *Engine) addMatchTxFeeOutput(txData *types.TxData, refunds RefundAssets, fees []*bc.AssetAmount) error { | |
66 | 66 | for _, feeAmount := range fees { |
67 | 67 | txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*feeAmount.AssetId, feeAmount.Amount, e.rewardProgram)) |
68 | 68 | } |
@@ -106,7 +106,7 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) { | ||
106 | 106 | |
107 | 107 | receivedAmounts, priceDiffs := CalcReceivedAmount(orders) |
108 | 108 | allocatedAssets := e.feeStrategy.Allocate(receivedAmounts, priceDiffs) |
109 | - if err := addMatchTxOutput(txData, orders, receivedAmounts, allocatedAssets.Receives); err != nil { | |
109 | + if err := addMatchTxOutput(txData, orders, receivedAmounts, allocatedAssets); err != nil { | |
110 | 110 | return nil, err |
111 | 111 | } |
112 | 112 |
@@ -123,22 +123,25 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) { | ||
123 | 123 | return types.NewTx(*txData), nil |
124 | 124 | } |
125 | 125 | |
126 | -func addMatchTxOutput(txData *types.TxData, orders []*common.Order, receivedAmounts, deductFeeReceives []*bc.AssetAmount) error { | |
126 | +func addMatchTxOutput(txData *types.TxData, orders []*common.Order, receivedAmounts []*bc.AssetAmount, allocatedAssets *AllocatedAssets) error { | |
127 | 127 | for i, order := range orders { |
128 | 128 | contractArgs, err := segwit.DecodeP2WMCProgram(order.Utxo.ControlProgram) |
129 | 129 | if err != nil { |
130 | 130 | return err |
131 | 131 | } |
132 | 132 | |
133 | - requestAmount := CalcRequestAmount(order.Utxo.Amount, contractArgs.RatioNumerator, contractArgs.RatioDenominator) | |
134 | 133 | receivedAmount := receivedAmounts[i].Amount |
135 | 134 | shouldPayAmount := calcShouldPayAmount(receivedAmount, contractArgs.RatioNumerator, contractArgs.RatioDenominator) |
136 | - isPartialTrade := requestAmount > receivedAmount | |
137 | 135 | |
138 | - setMatchTxArguments(txData.Inputs[i], isPartialTrade, len(txData.Outputs), receivedAmounts[i].Amount) | |
139 | - txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.ToAssetID, deductFeeReceives[i].Amount, contractArgs.SellerProgram)) | |
136 | + exchangeAmount := order.Utxo.Amount - shouldPayAmount | |
137 | + isPartialTrade := CalcRequestAmount(exchangeAmount, contractArgs.RatioNumerator, contractArgs.RatioDenominator) >= 1 | |
138 | + | |
139 | + setMatchTxArguments(txData.Inputs[i], isPartialTrade, len(txData.Outputs), receivedAmount) | |
140 | + txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.ToAssetID, allocatedAssets.Receives[i].Amount, contractArgs.SellerProgram)) | |
140 | 141 | if isPartialTrade { |
141 | - txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.FromAssetID, order.Utxo.Amount-shouldPayAmount, order.Utxo.ControlProgram)) | |
142 | + txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.FromAssetID, exchangeAmount, order.Utxo.ControlProgram)) | |
143 | + } else if exchangeAmount > 0 { | |
144 | + allocatedAssets.Refunds.Add(i, *order.FromAssetID, exchangeAmount) | |
142 | 145 | } |
143 | 146 | } |
144 | 147 | return nil |
@@ -15,12 +15,31 @@ var ( | ||
15 | 15 | // AllocatedAssets represent reallocated assets after calculating fees |
16 | 16 | type AllocatedAssets struct { |
17 | 17 | Receives []*bc.AssetAmount |
18 | - Refunds []RefundAssets | |
18 | + Refunds RefundAssets | |
19 | 19 | Fees []*bc.AssetAmount |
20 | 20 | } |
21 | 21 | |
22 | 22 | // RefundAssets represent alias for assetAmount array, because each transaction participant can be refunded multiple assets |
23 | -type RefundAssets []*bc.AssetAmount | |
23 | +type RefundAssets [][]*bc.AssetAmount | |
24 | + | |
25 | +// Add used to add a refund to specify order | |
26 | +func (r RefundAssets) Add(index int, asset bc.AssetID, amount uint64) { | |
27 | + if index >= len(r) { | |
28 | + return | |
29 | + } | |
30 | + | |
31 | + var found bool | |
32 | + for _, assetAmount := range r[index] { | |
33 | + if *assetAmount.AssetId == asset { | |
34 | + assetAmount.Amount += amount | |
35 | + found = true | |
36 | + break | |
37 | + } | |
38 | + } | |
39 | + if !found { | |
40 | + r[index] = append(r[index], &bc.AssetAmount{AssetId: &asset, Amount: amount}) | |
41 | + } | |
42 | +} | |
24 | 43 | |
25 | 44 | // FeeStrategy used to indicate how to charge a matching fee |
26 | 45 | type FeeStrategy interface { |
@@ -50,7 +69,7 @@ func (d *DefaultFeeStrategy) Allocate(receiveAmounts, priceDiffs []*bc.AssetAmou | ||
50 | 69 | } |
51 | 70 | |
52 | 71 | var fees []*bc.AssetAmount |
53 | - refunds := make([]RefundAssets, len(receiveAmounts)) | |
72 | + refunds := make([][]*bc.AssetAmount, len(receiveAmounts)) | |
54 | 73 | receives := make([]*bc.AssetAmount, len(receiveAmounts)) |
55 | 74 | |
56 | 75 | for i, receiveAmount := range receiveAmounts { |
@@ -162,11 +162,11 @@ func (m *Core) ValidateTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHe | ||
162 | 162 | } |
163 | 163 | |
164 | 164 | if common.IsMatchedTx(tx) { |
165 | - if err := validateMatchedTx(tx, verifyResult, blockHeight); err != nil { | |
165 | + if err := validateMatchedTx(tx, blockHeight); err != nil { | |
166 | 166 | return err |
167 | 167 | } |
168 | 168 | } else if common.IsCancelOrderTx(tx) { |
169 | - if err := validateCancelOrderTx(tx, verifyResult); err != nil { | |
169 | + if err := validateCancelOrderTx(tx); err != nil { | |
170 | 170 | return err |
171 | 171 | } |
172 | 172 | } |
@@ -220,7 +220,7 @@ func calcFeeAmount(matchedTx *types.Tx) (map[bc.AssetID]*matchedTxFee, error) { | ||
220 | 220 | return assetFeeMap, nil |
221 | 221 | } |
222 | 222 | |
223 | -func validateCancelOrderTx(tx *types.Tx, verifyResult *bc.TxVerifyResult) error { | |
223 | +func validateCancelOrderTx(tx *types.Tx) error { | |
224 | 224 | for _, input := range tx.Inputs { |
225 | 225 | if !segwit.IsP2WMCScript(input.ControlProgram()) { |
226 | 226 | return errInputProgramMustP2WMCScript |
@@ -253,7 +253,7 @@ func validateMagneticContractArgs(fromAssetAmount bc.AssetAmount, program []byte | ||
253 | 253 | return nil |
254 | 254 | } |
255 | 255 | |
256 | -func validateMatchedTx(tx *types.Tx, verifyResult *bc.TxVerifyResult, blockHeight uint64) error { | |
256 | +func validateMatchedTx(tx *types.Tx, blockHeight uint64) error { | |
257 | 257 | fromAssetIDMap := make(map[string]bool) |
258 | 258 | toAssetIDMap := make(map[string]bool) |
259 | 259 | for i, input := range tx.Inputs { |