weight_estimator_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package sweep
  2. import (
  3. "testing"
  4. "github.com/btcsuite/btcd/btcutil"
  5. "github.com/btcsuite/btcd/chaincfg"
  6. "github.com/btcsuite/btcd/txscript"
  7. "github.com/btcsuite/btcd/wire"
  8. "github.com/lightningnetwork/lnd/input"
  9. "github.com/lightningnetwork/lnd/lnwallet/chainfee"
  10. "github.com/stretchr/testify/require"
  11. )
  12. // TestWeightEstimator tests weight estimation for inputs with and without
  13. // unconfirmed parents.
  14. func TestWeightEstimator(t *testing.T) {
  15. testFeeRate := chainfee.SatPerKWeight(20000)
  16. w := newWeightEstimator(testFeeRate, 0)
  17. // Add an input without unconfirmed parent tx.
  18. input1 := input.MakeBaseInput(
  19. &wire.OutPoint{}, input.CommitmentAnchor,
  20. &input.SignDescriptor{}, 0, nil,
  21. )
  22. require.NoError(t, w.add(&input1))
  23. // The expectations is that this input is added.
  24. const expectedWeight1 = 322
  25. require.Equal(t, expectedWeight1, w.weight())
  26. require.Equal(t, testFeeRate.FeeForWeight(expectedWeight1),
  27. w.feeWithParent())
  28. // Define a parent transaction that pays a fee of 30000 sat/kw.
  29. parentTxHighFee := &input.TxInfo{
  30. Weight: 100,
  31. Fee: 3000,
  32. }
  33. // Add an output of the parent tx above.
  34. input2 := input.MakeBaseInput(
  35. &wire.OutPoint{}, input.CommitmentAnchor,
  36. &input.SignDescriptor{}, 0,
  37. parentTxHighFee,
  38. )
  39. require.NoError(t, w.add(&input2))
  40. // Pay for parent isn't possible because the parent pays a higher fee
  41. // rate than the child. We expect no additional fee on the child.
  42. const expectedWeight2 = expectedWeight1 + 280
  43. require.Equal(t, expectedWeight2, w.weight())
  44. require.Equal(t, testFeeRate.FeeForWeight(expectedWeight2),
  45. w.feeWithParent())
  46. // Define a parent transaction that pays a fee of 10000 sat/kw.
  47. parentTxLowFee := &input.TxInfo{
  48. Weight: 100,
  49. Fee: 1000,
  50. }
  51. // Add an output of the low-fee parent tx above.
  52. input3 := input.MakeBaseInput(
  53. &wire.OutPoint{}, input.CommitmentAnchor,
  54. &input.SignDescriptor{}, 0,
  55. parentTxLowFee,
  56. )
  57. require.NoError(t, w.add(&input3))
  58. // Expect the weight to increase because of the third input.
  59. const expectedWeight3 = expectedWeight2 + 280
  60. require.Equal(t, expectedWeight3, w.weight())
  61. // Expect the fee to cover the child and the parent transaction at 20
  62. // sat/kw after subtraction of the fee that was already paid by the
  63. // parent.
  64. expectedFee := testFeeRate.FeeForWeight(
  65. expectedWeight3+parentTxLowFee.Weight,
  66. ) - parentTxLowFee.Fee
  67. require.Equal(t, expectedFee, w.feeWithParent())
  68. }
  69. // TestWeightEstimatorMaxFee tests that the weight estimator correctly caps the
  70. // fee at the maximum allowed fee.
  71. func TestWeightEstimatorMaxFee(t *testing.T) {
  72. t.Parallel()
  73. testFeeRate := chainfee.SatPerKWeight(9_000)
  74. maxFeeRate := chainfee.SatPerKWeight(10_000)
  75. w := newWeightEstimator(testFeeRate, maxFeeRate)
  76. // Define a parent transaction that pays a fee of 1000 sat/kw.
  77. parentTxLowFee := &input.TxInfo{
  78. Weight: 100,
  79. Fee: 100,
  80. }
  81. // Add an output of the low-fee parent tx above.
  82. childInput := input.MakeBaseInput(
  83. &wire.OutPoint{}, input.CommitmentAnchor,
  84. &input.SignDescriptor{}, 0, parentTxLowFee,
  85. )
  86. require.NoError(t, w.add(&childInput))
  87. // The child weight should be 322 weight uints.
  88. const childWeight = 322
  89. require.Equal(t, childWeight, w.weight())
  90. // Check the fee is capped at the maximum allowed fee. The
  91. // calculations,
  92. //
  93. // totalWeight = childWeight + parentWeight = 422
  94. // fee = totalWeight * testFeeRate - parentsFee =
  95. // 422 * 9_000 / 1000 - 100 = 3598
  96. // maxFee = childWeight * maxFeeRate = 422 * 10_000 / 1000 = 3220
  97. //
  98. // Thus we cap at the maxFee.
  99. expectedFee := maxFeeRate.FeeForWeight(childWeight)
  100. require.Equal(t, expectedFee, w.feeWithParent())
  101. }
  102. // TestWeightEstimatorAddOutput tests that adding the raw P2WKH output to the
  103. // estimator yield the same result as an estimated add.
  104. func TestWeightEstimatorAddOutput(t *testing.T) {
  105. testFeeRate := chainfee.SatPerKWeight(20000)
  106. p2wkhAddr, err := btcutil.NewAddressWitnessPubKeyHash(
  107. make([]byte, 20), &chaincfg.MainNetParams,
  108. )
  109. require.NoError(t, err)
  110. p2wkhScript, err := txscript.PayToAddrScript(p2wkhAddr)
  111. require.NoError(t, err)
  112. // Create two estimators, add the raw P2WKH out to one.
  113. txOut := &wire.TxOut{
  114. PkScript: p2wkhScript,
  115. Value: 10000,
  116. }
  117. w1 := newWeightEstimator(testFeeRate, 0)
  118. w1.addOutput(txOut)
  119. w2 := newWeightEstimator(testFeeRate, 0)
  120. w2.addP2WKHOutput()
  121. // Estimate hhould be the same.
  122. require.Equal(t, w1.weight(), w2.weight())
  123. }