@@ -14,8 +14,7 @@ import (
1414)
1515
1616type redemptionEntry struct {
17- walletPublicKeyHash [20 ]byte
18-
17+ walletPublicKeyHash [20 ]byte
1918 redemptionKey string
2019 redeemerOutputScript bitcoin.Script
2120 requestedAt time.Time
@@ -143,6 +142,7 @@ func FindPendingRedemptions(
143142// ProposeRedemption handles redemption proposal submission.
144143func ProposeRedemption (
145144 chain Chain ,
145+ btcChain bitcoin.Chain ,
146146 walletPublicKeyHash [20 ]byte ,
147147 fee int64 ,
148148 redeemersOutputScripts []bitcoin.Script ,
@@ -152,9 +152,25 @@ func ProposeRedemption(
152152 return fmt .Errorf ("redemptions list is empty" )
153153 }
154154
155- // Estimate fee if it's missing.
155+ // Estimate fee if it's missing. Do not check the estimated fee against
156+ // the maximum total and per-request fees allowed by the Bridge. This
157+ // is done during the on-chain validation of the proposal so there is no
158+ // need to do it here.
156159 if fee <= 0 {
157- panic ("fee estimation not implemented yet" )
160+ logger .Infof ("estimating redemption transaction fee..." )
161+
162+ estimatedFee , err := EstimateRedemptionFee (
163+ btcChain ,
164+ redeemersOutputScripts ,
165+ )
166+ if err != nil {
167+ return fmt .Errorf (
168+ "cannot estimate redemption transaction fee: [%w]" ,
169+ err ,
170+ )
171+ }
172+
173+ fee = estimatedFee
158174 }
159175
160176 logger .Infof ("redemption transaction fee: [%d]" , fee )
@@ -319,3 +335,43 @@ redemptionRequestedLoop:
319335
320336 return result , nil
321337}
338+
339+ func EstimateRedemptionFee (
340+ btcChain bitcoin.Chain ,
341+ redeemersOutputScripts []bitcoin.Script ,
342+ ) (int64 , error ) {
343+ sizeEstimator := bitcoin .NewTransactionSizeEstimator ().
344+ // 1 P2WPKH main UTXO input.
345+ AddPublicKeyHashInputs (1 , true ).
346+ // 1 P2WPKH change output.
347+ AddPublicKeyHashOutputs (1 , true )
348+
349+ for _ , script := range redeemersOutputScripts {
350+ switch bitcoin .GetScriptType (script ) {
351+ case bitcoin .P2PKHScript :
352+ sizeEstimator .AddPublicKeyHashOutputs (1 , false )
353+ case bitcoin .P2WPKHScript :
354+ sizeEstimator .AddPublicKeyHashOutputs (1 , true )
355+ case bitcoin .P2SHScript :
356+ sizeEstimator .AddScriptHashOutputs (1 , false )
357+ case bitcoin .P2WSHScript :
358+ sizeEstimator .AddScriptHashOutputs (1 , true )
359+ default :
360+ return 0 , fmt .Errorf ("non-standard redeemer output script type" )
361+ }
362+ }
363+
364+ transactionSize , err := sizeEstimator .VirtualSize ()
365+ if err != nil {
366+ return 0 , fmt .Errorf ("cannot estimate transaction virtual size: [%v]" , err )
367+ }
368+
369+ feeEstimator := bitcoin .NewTransactionFeeEstimator (btcChain )
370+
371+ totalFee , err := feeEstimator .EstimateFee (transactionSize )
372+ if err != nil {
373+ return 0 , fmt .Errorf ("cannot estimate transaction fee: [%v]" , err )
374+ }
375+
376+ return totalFee , nil
377+ }
0 commit comments