Golang implemented sidechain for Bytom
Révision | 38de5720d9b9302a7bbafe9015f45517cdf02b27 (tree) |
---|---|
l'heure | 2020-03-25 22:28:22 |
Auteur | paladz <453256728@qq.c...> |
Commiter | paladz |
fix fee
@@ -62,20 +62,42 @@ 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, orders []*common.Order, 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 | } |
69 | 69 | |
70 | - for i, refund := range refunds { | |
71 | - // each trading participant may be refunded multiple assets | |
72 | - for _, assetAmount := range refund { | |
73 | - contractArgs, err := segwit.DecodeP2WMCProgram(txData.Inputs[i].ControlProgram()) | |
74 | - if err != nil { | |
75 | - return err | |
76 | - } | |
70 | + refoundAmount := map[bc.AssetID]uint64{} | |
71 | + refoundAddress := [][]byte{} | |
72 | + for _, input := range txData.Inputs { | |
73 | + refoundAmount[input.AssetID()] += input.Amount() | |
74 | + contractArgs, err := segwit.DecodeP2WMCProgram(input.ControlProgram()) | |
75 | + if err != nil { | |
76 | + return err | |
77 | + } | |
78 | + | |
79 | + refoundAddress = append(refoundAddress, contractArgs.SellerProgram) | |
80 | + } | |
81 | + | |
82 | + for _, output := range txData.Outputs { | |
83 | + assetAmount := output.AssetAmount() | |
84 | + refoundAmount[*assetAmount.AssetId] -= assetAmount.Amount | |
85 | + if refoundAmount[*assetAmount.AssetId] == 0 { | |
86 | + delete(refoundAmount, *assetAmount.AssetId) | |
87 | + } | |
88 | + } | |
89 | + | |
90 | + refoundCount := len(refoundAddress) | |
91 | + for asset, amount := range refoundAmount { | |
92 | + averageAmount := amount / uint64(refoundCount) | |
93 | + if averageAmount == 0 { | |
94 | + averageAmount = 1 | |
95 | + } | |
77 | 96 | |
78 | - txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*assetAmount.AssetId, assetAmount.Amount, contractArgs.SellerProgram)) | |
97 | + for i := 0; i < refoundCount && amount > 0; i++ { | |
98 | + txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(asset, | |
99 | + averageAmount, refoundAddress[i])) | |
100 | + amount -= averageAmount | |
79 | 101 | } |
80 | 102 | } |
81 | 103 | return nil |
@@ -104,13 +126,13 @@ func (e *Engine) buildMatchTx(orders []*common.Order) (*types.Tx, error) { | ||
104 | 126 | txData.Inputs = append(txData.Inputs, input) |
105 | 127 | } |
106 | 128 | |
107 | - receivedAmounts, priceDiffs := CalcReceivedAmount(orders) | |
108 | - allocatedAssets := e.feeStrategy.Allocate(receivedAmounts, priceDiffs) | |
129 | + receivedAmounts := CalcReceivedAmount(orders) | |
130 | + allocatedAssets := e.feeStrategy.Allocate(receivedAmounts) | |
109 | 131 | if err := addMatchTxOutput(txData, orders, receivedAmounts, allocatedAssets); err != nil { |
110 | 132 | return nil, err |
111 | 133 | } |
112 | 134 | |
113 | - if err := e.addMatchTxFeeOutput(txData, allocatedAssets.Refunds, allocatedAssets.Fees); err != nil { | |
135 | + if err := e.addMatchTxFeeOutput(txData, orders, allocatedAssets.Fees); err != nil { | |
114 | 136 | return nil, err |
115 | 137 | } |
116 | 138 |
@@ -140,8 +162,6 @@ func addMatchTxOutput(txData *types.TxData, orders []*common.Order, receivedAmou | ||
140 | 162 | txData.Outputs = append(txData.Outputs, types.NewIntraChainOutput(*order.ToAssetID, allocatedAssets.Receives[i].Amount, contractArgs.SellerProgram)) |
141 | 163 | if isPartialTrade { |
142 | 164 | 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) | |
145 | 165 | } |
146 | 166 | } |
147 | 167 | return nil |
@@ -171,26 +191,16 @@ func calcShouldPayAmount(receiveAmount uint64, ratioNumerator, ratioDenominator | ||
171 | 191 | } |
172 | 192 | |
173 | 193 | // CalcReceivedAmount return amount of assets received by each participant in the matching transaction and the price difference |
174 | -func CalcReceivedAmount(orders []*common.Order) ([]*bc.AssetAmount, []*bc.AssetAmount) { | |
175 | - var receivedAmounts, priceDiffs, shouldPayAmounts []*bc.AssetAmount | |
194 | +func CalcReceivedAmount(orders []*common.Order) []*bc.AssetAmount { | |
195 | + var receivedAmounts []*bc.AssetAmount | |
176 | 196 | for i, order := range orders { |
177 | 197 | requestAmount := CalcRequestAmount(order.Utxo.Amount, order.RatioNumerator, order.RatioDenominator) |
178 | 198 | oppositeOrder := orders[calcOppositeIndex(len(orders), i)] |
179 | 199 | receiveAmount := vprMath.MinUint64(oppositeOrder.Utxo.Amount, requestAmount) |
180 | - shouldPayAmount := calcShouldPayAmount(receiveAmount, order.RatioNumerator, order.RatioDenominator) | |
181 | 200 | receivedAmounts = append(receivedAmounts, &bc.AssetAmount{AssetId: order.ToAssetID, Amount: receiveAmount}) |
182 | - shouldPayAmounts = append(shouldPayAmounts, &bc.AssetAmount{AssetId: order.FromAssetID, Amount: shouldPayAmount}) | |
183 | 201 | } |
184 | 202 | |
185 | - for i, receivedAmount := range receivedAmounts { | |
186 | - oppositeShouldPayAmount := shouldPayAmounts[calcOppositeIndex(len(orders), i)] | |
187 | - if oppositeShouldPayAmount.Amount > receivedAmount.Amount { | |
188 | - assetID := oppositeShouldPayAmount.AssetId | |
189 | - amount := oppositeShouldPayAmount.Amount - receivedAmount.Amount | |
190 | - priceDiffs = append(priceDiffs, &bc.AssetAmount{AssetId: assetID, Amount: amount}) | |
191 | - } | |
192 | - } | |
193 | - return receivedAmounts, priceDiffs | |
203 | + return receivedAmounts | |
194 | 204 | } |
195 | 205 | |
196 | 206 | // IsMatched check does the orders can be exchange |
@@ -15,7 +15,6 @@ var ( | ||
15 | 15 | // AllocatedAssets represent reallocated assets after calculating fees |
16 | 16 | type AllocatedAssets struct { |
17 | 17 | Receives []*bc.AssetAmount |
18 | - Refunds RefundAssets | |
19 | 18 | Fees []*bc.AssetAmount |
20 | 19 | } |
21 | 20 |
@@ -43,14 +42,14 @@ type FeeStrategy interface { | ||
43 | 42 | // @param receiveAmounts the amount of assets that the participants in the matching transaction can received when no fee is considered |
44 | 43 | // @param priceDiffs price differential of matching transaction |
45 | 44 | // @return reallocated assets after calculating fees |
46 | - Allocate(receiveAmounts, priceDiffs []*bc.AssetAmount) *AllocatedAssets | |
45 | + Allocate(receiveAmounts []*bc.AssetAmount) *AllocatedAssets | |
47 | 46 | |
48 | 47 | // Validate verify that the fee charged for a matching transaction is correct |
49 | 48 | Validate(receiveAmounts []*bc.AssetAmount, feeAmounts map[bc.AssetID]uint64) error |
50 | 49 | } |
51 | 50 | |
52 | 51 | // DefaultFeeStrategy represent the default fee charge strategy |
53 | -type DefaultFeeStrategy struct {} | |
52 | +type DefaultFeeStrategy struct{} | |
54 | 53 | |
55 | 54 | // NewDefaultFeeStrategy return a new instance of DefaultFeeStrategy |
56 | 55 | func NewDefaultFeeStrategy() *DefaultFeeStrategy { |
@@ -58,47 +57,17 @@ func NewDefaultFeeStrategy() *DefaultFeeStrategy { | ||
58 | 57 | } |
59 | 58 | |
60 | 59 | // Allocate will allocate the price differential in matching transaction to the participants and the fee |
61 | -func (d *DefaultFeeStrategy) Allocate(receiveAmounts, priceDiffs []*bc.AssetAmount) *AllocatedAssets { | |
62 | - feeMap := make(map[bc.AssetID]uint64) | |
63 | - for _, priceDiff := range priceDiffs { | |
64 | - feeMap[*priceDiff.AssetId] = priceDiff.Amount | |
65 | - } | |
66 | - | |
67 | - var fees []*bc.AssetAmount | |
68 | - refunds := make([][]*bc.AssetAmount, len(receiveAmounts)) | |
60 | +func (d *DefaultFeeStrategy) Allocate(receiveAmounts []*bc.AssetAmount) *AllocatedAssets { | |
69 | 61 | receives := make([]*bc.AssetAmount, len(receiveAmounts)) |
62 | + fees := make([]*bc.AssetAmount, len(receiveAmounts)) | |
70 | 63 | |
71 | 64 | for i, receiveAmount := range receiveAmounts { |
72 | 65 | amount := receiveAmount.Amount |
73 | 66 | minFeeAmount := d.calcMinFeeAmount(amount) |
74 | 67 | receives[i] = &bc.AssetAmount{AssetId: receiveAmount.AssetId, Amount: amount - minFeeAmount} |
75 | - feeMap[*receiveAmount.AssetId] += minFeeAmount | |
76 | - | |
77 | - maxFeeAmount := d.calcMaxFeeAmount(amount) | |
78 | - feeAmount, reminder := feeMap[*receiveAmount.AssetId], uint64(0) | |
79 | - if feeAmount > maxFeeAmount { | |
80 | - reminder = feeAmount - maxFeeAmount | |
81 | - feeAmount = maxFeeAmount | |
82 | - } | |
83 | - | |
84 | - fees = append(fees, &bc.AssetAmount{AssetId: receiveAmount.AssetId, Amount: feeAmount}) | |
85 | - | |
86 | - // There is the remaining amount after paying the handling fee, assign it evenly to participants in the transaction | |
87 | - averageAmount := reminder / uint64(len(receiveAmounts)) | |
88 | - if averageAmount == 0 { | |
89 | - averageAmount = 1 | |
90 | - } | |
91 | - | |
92 | - for j := 0; j < len(receiveAmounts) && reminder > 0; j++ { | |
93 | - refundAmount := averageAmount | |
94 | - if j == len(receiveAmounts)-1 { | |
95 | - refundAmount = reminder | |
96 | - } | |
97 | - refunds[j] = append(refunds[j], &bc.AssetAmount{AssetId: receiveAmount.AssetId, Amount: refundAmount}) | |
98 | - reminder -= averageAmount | |
99 | - } | |
68 | + fees[i] = &bc.AssetAmount{AssetId: receiveAmount.AssetId, Amount: minFeeAmount} | |
100 | 69 | } |
101 | - return &AllocatedAssets{Receives: receives, Refunds: refunds, Fees: fees} | |
70 | + return &AllocatedAssets{Receives: receives, Fees: fees} | |
102 | 71 | } |
103 | 72 | |
104 | 73 | // Validate verify that the fee charged for a matching transaction is correct |
@@ -298,7 +298,7 @@ func validateMatchedTxFee(tx *types.Tx, blockHeight uint64) error { | ||
298 | 298 | return err |
299 | 299 | } |
300 | 300 | |
301 | - receivedAmount, _ := match.CalcReceivedAmount(orders) | |
301 | + receivedAmount := match.CalcReceivedAmount(orders) | |
302 | 302 | feeAmounts := make(map[bc.AssetID]uint64) |
303 | 303 | for assetID, fee := range matchedTxFees { |
304 | 304 | feeAmounts[assetID] = fee.amount |