diff --git a/contractcourt/breach_arbitrator.go b/contractcourt/breach_arbitrator.go index 89927b6e1..96fa689c3 100644 --- a/contractcourt/breach_arbitrator.go +++ b/contractcourt/breach_arbitrator.go @@ -19,6 +19,7 @@ import ( "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/labels" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -1497,14 +1498,14 @@ func (b *BreachArbitrator) createSweepTx(inputs ...input.Input) (*wire.MsgTx, spendableOutputs = append(spendableOutputs, inp) } - txWeight := int64(weightEstimate.Weight()) + txWeight := weightEstimate.Weight() return b.sweepSpendableOutputsTxn(txWeight, spendableOutputs...) } // sweepSpendableOutputsTxn creates a signed transaction from a sequence of // spendable outputs by sweeping the funds into a single p2wkh output. -func (b *BreachArbitrator) sweepSpendableOutputsTxn(txWeight int64, +func (b *BreachArbitrator) sweepSpendableOutputsTxn(txWeight lntypes.WeightUnit, inputs ...input.Input) (*wire.MsgTx, error) { // First, we obtain a new public key script from the wallet which we'll diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 6963bf708..93c76bd40 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -2480,7 +2480,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2517,7 +2517,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2578,7 +2578,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2609,7 +2609,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2675,7 +2675,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2721,7 +2721,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2771,7 +2771,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2835,7 +2835,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2880,7 +2880,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2976,7 +2976,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3022,7 +3022,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3113,7 +3113,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // With two HTLCs on the pending commit, and two added to the in-memory // commitment state, the resulting bandwidth should reflect that Alice // is paying the all htlc amounts in addition to all htlc fees. - htlcWeight = int64(1+numHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+numHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3205,7 +3205,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // Since the latter two HTLCs have been completely dropped from memory, // only the first two HTLCs we added should still be reflected in the // channel bandwidth. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3264,7 +3264,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3309,7 +3309,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // We account for the 2 htlcs and the additional one which would be // needed when sending and htlc. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3387,7 +3387,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { } // Alice's bandwidth should have reverted back to her starting value. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3414,7 +3414,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // We account for the 2 htlcs and the additional one which would be // needed when sending and htlc. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3492,7 +3492,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { t.Fatalf("expected %d packet to be failed", halfHtlcs) } - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3540,7 +3540,7 @@ func TestChannelLinkTrimCircuitsRemoteCommit(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3602,7 +3602,7 @@ func TestChannelLinkTrimCircuitsRemoteCommit(t *testing.T) { // The resulting bandwidth should reflect that Alice is paying both // htlc amounts, in addition to both htlc fees. - htlcWeight = int64(1+numHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+numHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3700,7 +3700,7 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer(feePerKw, commitWeight+htlcWeight) // The starting bandwidth of the channel should be exactly the amount @@ -3727,7 +3727,7 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) { _ = harness.aliceLink.handleSwitchPacket(addPkt) time.Sleep(time.Millisecond * 100) - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) diff --git a/input/input.go b/input/input.go index a6d3fa5b4..aef524a4c 100644 --- a/input/input.go +++ b/input/input.go @@ -71,7 +71,7 @@ type TxInfo struct { Fee btcutil.Amount // Weight is the weight of the tx. - Weight int64 + Weight lntypes.WeightUnit } // String returns a human readable version of the tx info. diff --git a/input/mocks.go b/input/mocks.go index 915e4ea69..2f38400d8 100644 --- a/input/mocks.go +++ b/input/mocks.go @@ -9,6 +9,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/stretchr/testify/mock" ) @@ -157,10 +158,10 @@ func (m *MockWitnessType) WitnessGenerator(signer Signer, // if it would be included in a tx. It also returns if the output itself is a // nested p2sh output, if so then we need to take into account the extra // sigScript data size. -func (m *MockWitnessType) SizeUpperBound() (int, bool, error) { +func (m *MockWitnessType) SizeUpperBound() (lntypes.WeightUnit, bool, error) { args := m.Called() - return args.Int(0), args.Bool(1), args.Error(2) + return args.Get(0).(lntypes.WeightUnit), args.Bool(1), args.Error(2) } // AddWeightEstimation adds the estimated size of the witness in bytes to the diff --git a/input/size.go b/input/size.go index e71e4190b..5d4b15ec1 100644 --- a/input/size.go +++ b/input/size.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/waddrmgr" + "github.com/lightningnetwork/lnd/lntypes" ) const ( @@ -862,9 +863,9 @@ type TxWeightEstimator struct { hasWitness bool inputCount uint32 outputCount uint32 - inputSize int - inputWitnessSize int - outputSize int + inputSize lntypes.VByte + inputWitnessSize lntypes.WeightUnit + outputSize lntypes.VByte } // AddP2PKHInput updates the weight estimate to account for an additional input @@ -888,7 +889,9 @@ func (twe *TxWeightEstimator) AddP2WKHInput() *TxWeightEstimator { // AddWitnessInput updates the weight estimate to account for an additional // input spending a native pay-to-witness output. This accepts the total size // of the witness as a parameter. -func (twe *TxWeightEstimator) AddWitnessInput(witnessSize int) *TxWeightEstimator { +func (twe *TxWeightEstimator) AddWitnessInput( + witnessSize lntypes.WeightUnit) *TxWeightEstimator { + twe.inputSize += InputSize twe.inputWitnessSize += witnessSize twe.inputCount++ @@ -905,7 +908,8 @@ func (twe *TxWeightEstimator) AddWitnessInput(witnessSize int) *TxWeightEstimato // NOTE: The leaf witness size must be calculated without the byte that accounts // for the number of witness elements, only the total size of all elements on // the stack that are consumed by the revealed script should be counted. -func (twe *TxWeightEstimator) AddTapscriptInput(leafWitnessSize int, +func (twe *TxWeightEstimator) AddTapscriptInput( + leafWitnessSize lntypes.WeightUnit, tapscript *waddrmgr.Tapscript) *TxWeightEstimator { // We add 1 byte for the total number of witness elements. @@ -915,7 +919,9 @@ func (twe *TxWeightEstimator) AddTapscriptInput(leafWitnessSize int, 1 + len(tapscript.ControlBlock.InclusionProof) twe.inputSize += InputSize - twe.inputWitnessSize += leafWitnessSize + controlBlockWitnessSize + twe.inputWitnessSize += leafWitnessSize + lntypes.WeightUnit( + controlBlockWitnessSize, + ) twe.inputCount++ twe.hasWitness = true @@ -956,7 +962,9 @@ func (twe *TxWeightEstimator) AddNestedP2WKHInput() *TxWeightEstimator { // AddNestedP2WSHInput updates the weight estimate to account for an additional // input spending a P2SH output with a nested P2WSH redeem script. -func (twe *TxWeightEstimator) AddNestedP2WSHInput(witnessSize int) *TxWeightEstimator { +func (twe *TxWeightEstimator) AddNestedP2WSHInput( + witnessSize lntypes.WeightUnit) *TxWeightEstimator { + twe.inputSize += InputSize + NestedP2WSHSize twe.inputWitnessSize += witnessSize twe.inputCount++ @@ -967,7 +975,7 @@ func (twe *TxWeightEstimator) AddNestedP2WSHInput(witnessSize int) *TxWeightEsti // AddTxOutput adds a known TxOut to the weight estimator. func (twe *TxWeightEstimator) AddTxOutput(txOut *wire.TxOut) *TxWeightEstimator { - twe.outputSize += txOut.SerializeSize() + twe.outputSize += lntypes.VByte(txOut.SerializeSize()) twe.outputCount++ return twe @@ -1020,18 +1028,20 @@ func (twe *TxWeightEstimator) AddP2SHOutput() *TxWeightEstimator { // AddOutput estimates the weight of an output based on the pkScript. func (twe *TxWeightEstimator) AddOutput(pkScript []byte) *TxWeightEstimator { - twe.outputSize += BaseOutputSize + len(pkScript) + twe.outputSize += BaseOutputSize + lntypes.VByte(len(pkScript)) twe.outputCount++ return twe } // Weight gets the estimated weight of the transaction. -func (twe *TxWeightEstimator) Weight() int { - txSizeStripped := BaseTxSize + - wire.VarIntSerializeSize(uint64(twe.inputCount)) + twe.inputSize + - wire.VarIntSerializeSize(uint64(twe.outputCount)) + twe.outputSize - weight := txSizeStripped * witnessScaleFactor +func (twe *TxWeightEstimator) Weight() lntypes.WeightUnit { + inputCount := wire.VarIntSerializeSize(uint64(twe.inputCount)) + outputCount := wire.VarIntSerializeSize(uint64(twe.outputCount)) + txSizeStripped := BaseTxSize + lntypes.VByte(inputCount) + + twe.inputSize + lntypes.VByte(outputCount) + twe.outputSize + weight := lntypes.WeightUnit(txSizeStripped * witnessScaleFactor) + if twe.hasWitness { weight += WitnessHeaderSize + twe.inputWitnessSize } @@ -1041,5 +1051,5 @@ func (twe *TxWeightEstimator) Weight() int { // VSize gets the estimated virtual size of the transactions, in vbytes. func (twe *TxWeightEstimator) VSize() int { // A tx's vsize is 1/4 of the weight, rounded up. - return (twe.Weight() + witnessScaleFactor - 1) / witnessScaleFactor + return int(twe.Weight().ToVB()) } diff --git a/input/size_test.go b/input/size_test.go index 1f447cf89..9c3446afb 100644 --- a/input/size_test.go +++ b/input/size_test.go @@ -297,11 +297,12 @@ func TestTxWeightEstimator(t *testing.T) { tx.AddTxOut(&wire.TxOut{PkScript: p2shScript}) } - expectedWeight := blockchain.GetTransactionWeight(btcutil.NewTx(tx)) - if weightEstimate.Weight() != int(expectedWeight) { - t.Errorf("Case %d: Got wrong weight: expected %d, got %d", - i, expectedWeight, weightEstimate.Weight()) - } + expectedWeight := blockchain.GetTransactionWeight( + btcutil.NewTx(tx), + ) + require.EqualValuesf(t, expectedWeight, weightEstimate.Weight(), + "Case %d: Got wrong weight: expected %d, got %d", + i, expectedWeight, weightEstimate.Weight()) } } diff --git a/input/witnessgen.go b/input/witnessgen.go index 66b5ef90e..c49328afc 100644 --- a/input/witnessgen.go +++ b/input/witnessgen.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/lntypes" ) // WitnessGenerator represents a function that is able to generate the final @@ -32,7 +33,7 @@ type WitnessType interface { // WitnessType if it would be included in a tx. It also returns if the // output itself is a nested p2sh output, if so then we need to take // into account the extra sigScript data size. - SizeUpperBound() (int, bool, error) + SizeUpperBound() (lntypes.WeightUnit, bool, error) // AddWeightEstimation adds the estimated size of the witness in bytes // to the given weight estimator. @@ -726,7 +727,9 @@ func (wt StandardWitnessType) WitnessGenerator(signer Signer, // sigScript data size. // // NOTE: This is part of the WitnessType interface. -func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { +func (wt StandardWitnessType) SizeUpperBound() (lntypes.WeightUnit, + bool, error) { + switch wt { // Outputs on a remote commitment transaction that pay directly to us. case CommitSpendNoDelayTweakless: @@ -743,7 +746,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseCommitmentTimeLock: size := ToLocalTimeoutWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // 1 CSV time locked output to us on remote commitment. case CommitmentToRemoteConfirmed: @@ -751,7 +755,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseCommitmentToRemoteConfirmed: size := ToRemoteConfirmedWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // Anchor output on the commitment transaction. case CommitmentAnchor: @@ -765,7 +770,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseHtlcOfferedTimeoutSecondLevel: size := ToLocalTimeoutWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // Input to the outgoing HTLC second layer timeout transaction. case HtlcOfferedTimeoutSecondLevelInputConfirmed: @@ -779,7 +785,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseHtlcAcceptedSuccessSecondLevel: size := ToLocalTimeoutWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // Input to the incoming second-layer HTLC success transaction. case HtlcAcceptedSuccessSecondLevelInputConfirmed: diff --git a/itest/lnd_channel_funding_fund_max_test.go b/itest/lnd_channel_funding_fund_max_test.go index 63d4d471d..fb1987705 100644 --- a/itest/lnd_channel_funding_fund_max_test.go +++ b/itest/lnd_channel_funding_fund_max_test.go @@ -309,7 +309,7 @@ func fundingFee(numInput int, change bool) btcutil.Amount { weightEstimate.AddP2TROutput() } - totalWeight := int64(weightEstimate.Weight()) + totalWeight := weightEstimate.Weight() return feeRate.FeeForWeight(totalWeight) } diff --git a/itest/lnd_recovery_test.go b/itest/lnd_recovery_test.go index c3e6efccd..766d10956 100644 --- a/itest/lnd_recovery_test.go +++ b/itest/lnd_recovery_test.go @@ -379,7 +379,7 @@ func testRescanAddressDetection(ht *lntest.HarnessTest) { estimator := input.TxWeightEstimator{} estimator.AddP2WKHInput() estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) diff --git a/itest/lnd_sweep_test.go b/itest/lnd_sweep_test.go index 4702def38..27ad13266 100644 --- a/itest/lnd_sweep_test.go +++ b/itest/lnd_sweep_test.go @@ -271,7 +271,7 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // We expect the fees to increase by i*delta. expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) expectedFeeRate := chainfee.NewSatPerKWeight( - expectedFee, uint64(txWeight), + expectedFee, txWeight, ) // We should see Bob's anchor sweeping tx being fee bumped @@ -608,7 +608,7 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // We expect the fees to increase by i*delta. expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) expectedFeeRate := chainfee.NewSatPerKWeight( - expectedFee, uint64(txWeight), + expectedFee, txWeight, ) // We should see Bob's anchor sweeping tx being fee bumped @@ -929,7 +929,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { outgoingBudget := 2 * invoiceAmt outgoingTxSize := ht.CalculateTxWeight(outgoingSweep) outgoingEndFeeRate := chainfee.NewSatPerKWeight( - outgoingBudget, uint64(outgoingTxSize), + outgoingBudget, outgoingTxSize, ) // Assert the initial sweeping tx is using the start fee rate. @@ -950,7 +950,8 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // assertSweepFeeRate is a helper closure that asserts the expected fee // rate is used at the given position for a sweeping tx. assertSweepFeeRate := func(sweepTx *wire.MsgTx, - startFeeRate, delta chainfee.SatPerKWeight, txSize int64, + startFeeRate, delta chainfee.SatPerKWeight, + txSize lntypes.WeightUnit, deadline, position int32, desc string) { // Bob's HTLC sweeping tx should be fee bumped. @@ -1068,7 +1069,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { incomingBudget := invoiceAmt.MulF64(contractcourt.DefaultBudgetRatio) incomingTxSize := ht.CalculateTxWeight(incomingSweep) incomingEndFeeRate := chainfee.NewSatPerKWeight( - incomingBudget, uint64(incomingTxSize), + incomingBudget, incomingTxSize, ) // Assert the initial sweeping tx is using the start fee rate. @@ -1415,7 +1416,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // Calculate the ending fee rate and fee rate delta used in his fee // function. - bobTxWeight := uint64(ht.CalculateTxWeight(bobSweepTx)) + bobTxWeight := ht.CalculateTxWeight(bobSweepTx) bobEndingFeeRate := chainfee.NewSatPerKWeight(bobBudget, bobTxWeight) bobFeeRateDelta := (bobEndingFeeRate - bobStartFeeRate) / chainfee.SatPerKWeight(deadlineB-1) diff --git a/itest/lnd_taproot_test.go b/itest/lnd_taproot_test.go index ed37e04e8..3b5cb4799 100644 --- a/itest/lnd_taproot_test.go +++ b/itest/lnd_taproot_test.go @@ -22,6 +22,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/node" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/stretchr/testify/require" ) @@ -187,7 +188,7 @@ func testTaprootComputeInputScriptKeySpendBip86(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -278,7 +279,7 @@ func testTaprootSignOutputRawScriptSpend(ht *lntest.HarnessTest, ) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() sigHash := txscript.SigHashDefault if len(sigHashType) != 0 { sigHash = sigHashType[0] @@ -431,7 +432,7 @@ func testTaprootSignOutputRawKeySpendBip86(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(sigHash) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -525,7 +526,7 @@ func testTaprootSignOutputRawKeySpendRootHash(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -610,7 +611,7 @@ func testTaprootMuSig2KeySpendBip86(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -740,7 +741,7 @@ func testTaprootMuSig2KeySpendRootHash(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -874,10 +875,11 @@ func testTaprootMuSig2ScriptSpend(ht *lntest.HarnessTest, feeRate := chainfee.SatPerKWeight(12500) estimator := input.TxWeightEstimator{} estimator.AddTapscriptInput( - len([]byte("foobar"))+len(leaf1.Script)+1, tapscript, + lntypes.WeightUnit(len([]byte("foobar"))+len(leaf1.Script)+1), + tapscript, ) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -956,7 +958,7 @@ func testTaprootMuSig2CombinedLeafKeySpend(ht *lntest.HarnessTest, input.TaprootSignatureWitnessSize, tapscript, ) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -1525,7 +1527,7 @@ func sendToTaprootOutput(ht *lntest.HarnessTest, hn *node.HarnessNode, // spend request, the given sweep address' balance is verified to be seen as // funds belonging to the wallet. func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode, - tx *wire.MsgTx, estimatedWeight int64, + tx *wire.MsgTx, estimatedWeight lntypes.WeightUnit, spendRequest *chainrpc.SpendRequest, sweepAddr string) { ht.Helper() @@ -1564,7 +1566,7 @@ func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode, // Since Schnorr signatures are fixed size, we must be able to estimate // the size of this transaction exactly. txWeight := blockchain.GetTransactionWeight(btcutil.NewTx(tx)) - require.Equal(ht, estimatedWeight, txWeight) + require.EqualValues(ht, estimatedWeight, txWeight) txReq := &walletrpc.Transaction{ TxHex: buf.Bytes(), diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index a00c38207..4c3996515 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1660,8 +1660,6 @@ func (w *WalletKit) fundPsbtInternalWallet(account string, // fundPsbtCoinSelect uses the "new" PSBT funding method using the channel // funding coin selection algorithm that allows specifying custom inputs while // selecting coins. -// -//nolint:funlen func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32, packet *psbt.Packet, minConfs int32, changeType chanfunding.ChangeAddressType, @@ -1737,7 +1735,7 @@ func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32, // Do we already have enough inputs specified to pay for the TX as it // is? In that case we only need to allocate any change, if there is // any. - packetFeeNoChange := feeRate.FeeForWeight(int64(estimator.Weight())) + packetFeeNoChange := feeRate.FeeForWeight(estimator.Weight()) if inputSum >= outputSum+packetFeeNoChange { // Calculate the packet's fee with a change output so, so we can // let the coin selection algorithm decide whether to use a @@ -1749,9 +1747,7 @@ func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32, case chanfunding.P2WKHChangeAddress: estimator.AddP2WKHOutput() } - packetFeeWithChange := feeRate.FeeForWeight( - int64(estimator.Weight()), - ) + packetFeeWithChange := feeRate.FeeForWeight(estimator.Weight()) changeAmt, needMore, err := chanfunding.CalculateChangeAmount( inputSum, outputSum, packetFeeNoChange, diff --git a/lnrpc/walletrpc/walletkit_server_test.go b/lnrpc/walletrpc/walletkit_server_test.go index d47a55981..115ccf96e 100644 --- a/lnrpc/walletrpc/walletkit_server_test.go +++ b/lnrpc/walletrpc/walletkit_server_test.go @@ -132,7 +132,7 @@ func TestFundPsbtCoinSelect(t *testing.T) { } weight := estimator.Weight() - fee := chainfee.FeePerKwFloor.FeeForWeight(int64(weight)) + fee := chainfee.FeePerKwFloor.FeeForWeight(weight) return fee + dust } diff --git a/lntest/harness.go b/lntest/harness.go index 889bb156e..ba61b0ac3 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/lntest/node" "github.com/lightningnetwork/lnd/lntest/rpc" "github.com/lightningnetwork/lnd/lntest/wait" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/stretchr/testify/require" @@ -2041,9 +2042,9 @@ func (h *HarnessTest) CalculateTxFee(tx *wire.MsgTx) btcutil.Amount { // CalculateTxWeight calculates the weight for a given tx. // // TODO(yy): use weight estimator to get more accurate result. -func (h *HarnessTest) CalculateTxWeight(tx *wire.MsgTx) int64 { +func (h *HarnessTest) CalculateTxWeight(tx *wire.MsgTx) lntypes.WeightUnit { utx := btcutil.NewTx(tx) - return blockchain.GetTransactionWeight(utx) + return lntypes.WeightUnit(blockchain.GetTransactionWeight(utx)) } // CalculateTxFeeRate calculates the fee rate for a given tx. @@ -2053,7 +2054,7 @@ func (h *HarnessTest) CalculateTxFeeRate( w := h.CalculateTxWeight(tx) fee := h.CalculateTxFee(tx) - return chainfee.NewSatPerKWeight(fee, uint64(w)) + return chainfee.NewSatPerKWeight(fee, w) } // CalculateTxesFeeRate takes a list of transactions and estimates the fee rate diff --git a/lntest/utils.go b/lntest/utils.go index 660c42ef9..d230b6b61 100644 --- a/lntest/utils.go +++ b/lntest/utils.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntest/wait" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" @@ -212,8 +213,9 @@ func CalcStaticFee(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount { anchors = anchorSize } - return feePerKw.FeeForWeight(int64(commitWeight+htlcWeight*numHTLCs)) + - anchors + totalWeight := commitWeight + htlcWeight*numHTLCs + + return feePerKw.FeeForWeight(lntypes.WeightUnit(totalWeight)) + anchors } // CalculateMaxHtlc re-implements the RequiredRemoteChannelReserve of the @@ -266,8 +268,10 @@ func CalcStaticFeeBuffer(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount { // Account for the HTLC which will be required when sending an htlc. numHTLCs++ + + totalWeight := commitWeight + numHTLCs*htlcWeight feeBuffer := lnwallet.CalcFeeBuffer( - feePerKw, int64(commitWeight+numHTLCs*htlcWeight), + feePerKw, lntypes.WeightUnit(totalWeight), ) return feeBuffer.ToSatoshis() diff --git a/lntypes/txsize.go b/lntypes/txsize.go new file mode 100644 index 000000000..0618bfc51 --- /dev/null +++ b/lntypes/txsize.go @@ -0,0 +1,42 @@ +package lntypes + +import ( + "fmt" + "math" +) + +// WeightUnit defines a unit to express the transaction size. One weight unit +// is 1/4_000_000 of the max block size. The tx weight is calculated using +// `Base tx size * 3 + Total tx size`. +// - Base tx size is size of the transaction serialized without the witness +// data. +// - Total tx size is the transaction size in bytes serialized according +// #BIP144. +type WeightUnit uint64 + +// ToVB converts a value expressed in weight units to virtual bytes. +func (wu WeightUnit) ToVB() VByte { + // According to BIP141: Virtual transaction size is defined as + // Transaction weight / 4 (rounded up to the next integer). + return VByte(math.Ceil(float64(wu) / 4)) +} + +// String returns the string representation of the weight unit. +func (wu WeightUnit) String() string { + return fmt.Sprintf("%d wu", wu) +} + +// VByte defines a unit to express the transaction size. One virtual byte is +// 1/4th of a weight unit. The tx virtual bytes is calculated using `TxWeight / +// 4`. +type VByte uint64 + +// ToWU converts a value expressed in virtual bytes to weight units. +func (vb VByte) ToWU() WeightUnit { + return WeightUnit(vb * 4) +} + +// String returns the string representation of the virtual byte. +func (vb VByte) String() string { + return fmt.Sprintf("%d vb", vb) +} diff --git a/lntypes/txsize_test.go b/lntypes/txsize_test.go new file mode 100644 index 000000000..a68a45b23 --- /dev/null +++ b/lntypes/txsize_test.go @@ -0,0 +1,28 @@ +package lntypes + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// TestTxSizeUnit tests the conversion of tx size to different units. +func TestTxSizeUnit(t *testing.T) { + t.Parallel() + + // Test normal conversion from 100wu to 25vb. + wu := WeightUnit(100) + vb := VByte(25) + require.Equal(t, vb, wu.ToVB(), "wu -> vb conversion "+ + "failed: want %v, got %v", vb, wu.ToVB()) + require.Equal(t, wu, vb.ToWU(), "vb -> wu conversion "+ + "failed: want %v, got %v", wu, vb.ToWU()) + + // Test rounding up conversion from 99wu to 25vb. + wu = WeightUnit(99) + vb = VByte(25) + require.Equal(t, vb, wu.ToVB(), "wu -> vb conversion "+ + "failed: want %v, got %v", vb, wu.ToVB()) + require.Equal(t, WeightUnit(100), vb.ToWU(), "vb -> wu conversion "+ + "failed: want %v, got %v", 100, vb.ToWU()) +} diff --git a/lnwallet/chainfee/rates.go b/lnwallet/chainfee/rates.go index 98cefc13b..f5294e4d1 100644 --- a/lnwallet/chainfee/rates.go +++ b/lnwallet/chainfee/rates.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcutil" + "github.com/lightningnetwork/lnd/lntypes" ) const ( @@ -41,7 +42,7 @@ type SatPerKVByte btcutil.Amount // FeeForVSize calculates the fee resulting from this fee rate and the given // vsize in vbytes. -func (s SatPerKVByte) FeeForVSize(vbytes int64) btcutil.Amount { +func (s SatPerKVByte) FeeForVSize(vbytes lntypes.VByte) btcutil.Amount { return btcutil.Amount(s) * btcutil.Amount(vbytes) / 1000 } @@ -59,17 +60,23 @@ func (s SatPerKVByte) String() string { type SatPerKWeight btcutil.Amount // NewSatPerKWeight creates a new fee rate in sat/kw. -func NewSatPerKWeight(fee btcutil.Amount, weight uint64) SatPerKWeight { - return SatPerKWeight(fee.MulF64(1000 / float64(weight))) +func NewSatPerKWeight(fee btcutil.Amount, wu lntypes.WeightUnit) SatPerKWeight { + return SatPerKWeight(fee.MulF64(1000 / float64(wu))) } // FeeForWeight calculates the fee resulting from this fee rate and the given // weight in weight units (wu). -func (s SatPerKWeight) FeeForWeight(wu int64) btcutil.Amount { +func (s SatPerKWeight) FeeForWeight(wu lntypes.WeightUnit) btcutil.Amount { // The resulting fee is rounded down, as specified in BOLT#03. return btcutil.Amount(s) * btcutil.Amount(wu) / 1000 } +// FeeForVByte calculates the fee resulting from this fee rate and the given +// size in vbytes (vb). +func (s SatPerKWeight) FeeForVByte(vb lntypes.VByte) btcutil.Amount { + return s.FeePerKVByte().FeeForVSize(vb) +} + // FeePerKVByte converts the current fee rate from sat/kw to sat/kb. func (s SatPerKWeight) FeePerKVByte() SatPerKVByte { return SatPerKVByte(s * blockchain.WitnessScaleFactor) diff --git a/lnwallet/chancloser/chancloser.go b/lnwallet/chancloser/chancloser.go index bc9a1c903..47635c3af 100644 --- a/lnwallet/chancloser/chancloser.go +++ b/lnwallet/chancloser/chancloser.go @@ -240,7 +240,7 @@ func calcCoopCloseFee(chanType channeldb.ChannelType, weightEstimator.AddTxOutput(remoteOutput) } - totalWeight := int64(weightEstimator.Weight()) + totalWeight := weightEstimator.Weight() return idealFeeRate.FeeForWeight(totalWeight) } diff --git a/lnwallet/chanfunding/coin_select.go b/lnwallet/chanfunding/coin_select.go index 4cf50c574..9bf7f2dc0 100644 --- a/lnwallet/chanfunding/coin_select.go +++ b/lnwallet/chanfunding/coin_select.go @@ -116,7 +116,7 @@ func calculateFees(utxos []wallet.Coin, feeRate chainfee.SatPerKWeight, // Estimate the fee required for a transaction without a change // output. - totalWeight := int64(weightEstimate.Weight()) + totalWeight := weightEstimate.Weight() requiredFeeNoChange := feeRate.FeeForWeight(totalWeight) // Estimate the fee required for a transaction with a change output. @@ -137,7 +137,7 @@ func calculateFees(utxos []wallet.Coin, feeRate chainfee.SatPerKWeight, // Now that we have added the change output, redo the fee // estimate. - totalWeight = int64(weightEstimate.Weight()) + totalWeight = weightEstimate.Weight() requiredFeeWithChange := feeRate.FeeForWeight(totalWeight) return requiredFeeNoChange, requiredFeeWithChange, nil diff --git a/lnwallet/chanfunding/coin_select_test.go b/lnwallet/chanfunding/coin_select_test.go index 43027f32f..a6ff18bae 100644 --- a/lnwallet/chanfunding/coin_select_test.go +++ b/lnwallet/chanfunding/coin_select_test.go @@ -50,7 +50,7 @@ func fundingFee(feeRate chainfee.SatPerKWeight, numInput int, // nolint:unparam weightEstimate.AddP2TROutput() } - totalWeight := int64(weightEstimate.Weight()) + totalWeight := weightEstimate.Weight() return feeRate.FeeForWeight(totalWeight) } diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 1af0e4b5f..0e0d762c1 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -28,6 +28,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" @@ -3800,7 +3801,7 @@ func (lc *LightningChannel) getUnsignedAckedUpdates() []channeldb.LogUpdate { // an htlc even if our channel is drained locally. // See: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md func CalcFeeBuffer(feePerKw chainfee.SatPerKWeight, - commitWeight int64) lnwire.MilliSatoshi { + commitWeight lntypes.WeightUnit) lnwire.MilliSatoshi { // Account for a 100% in fee rate increase. bufferFeePerKw := 2 * feePerKw @@ -3873,7 +3874,7 @@ func (b BufferType) String() string { // and verifies that it does not become negative. This function returns the new // balance and the exact buffer amount (excluding the commitment fee). func (lc *LightningChannel) applyCommitFee( - balance lnwire.MilliSatoshi, commitWeight int64, + balance lnwire.MilliSatoshi, commitWeight lntypes.WeightUnit, feePerKw chainfee.SatPerKWeight, buffer BufferType) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, error) { @@ -4730,8 +4731,8 @@ func (lc *LightningChannel) ProcessChanSyncMsg( // If the updateState boolean is set true, the add and remove heights of the // HTLCs will be set to the next commitment height. func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, - updateState bool) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, int64, - *htlcView, error) { + updateState bool) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, + lntypes.WeightUnit, *htlcView, error) { commitChain := lc.localCommitChain dustLimit := lc.channelState.LocalChanCfg.DustLimit @@ -4792,7 +4793,7 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, // Now go through all HTLCs at this stage, to calculate the total // weight, needed to calculate the transaction fee. - var totalHtlcWeight int64 + var totalHtlcWeight lntypes.WeightUnit for _, htlc := range filteredHTLCView.ourUpdates { if HtlcIsDust( lc.channelState.ChanType, false, !remoteChain, @@ -7522,7 +7523,7 @@ type AnchorResolution struct { CommitFee btcutil.Amount // CommitWeight is the weight of the commit tx. - CommitWeight int64 + CommitWeight lntypes.WeightUnit } // LocalForceCloseSummary describes the final commitment state before the @@ -8200,7 +8201,7 @@ func NewAnchorResolution(chanState *channeldb.OpenChannel, return &AnchorResolution{ CommitAnchor: *outPoint, AnchorSignDescriptor: *signDesc, - CommitWeight: weight, + CommitWeight: lntypes.WeightUnit(weight), CommitFee: fee, }, nil } @@ -8226,7 +8227,7 @@ func (lc *LightningChannel) AvailableBalance() lnwire.MilliSatoshi { // this method. Additionally, the total weight of the next to be created // commitment is returned for accounting purposes. func (lc *LightningChannel) availableBalance( - buffer BufferType) (lnwire.MilliSatoshi, int64) { + buffer BufferType) (lnwire.MilliSatoshi, lntypes.WeightUnit) { // We'll grab the current set of log updates that the remote has // ACKed. @@ -8265,8 +8266,9 @@ func (lc *LightningChannel) availableBalance( // commitment, increasing the commitment fee we must pay as an initiator, // eating into our balance. It will make sure we won't violate the channel // reserve constraints for this amount. -func (lc *LightningChannel) availableCommitmentBalance(view *htlcView, - remoteChain bool, buffer BufferType) (lnwire.MilliSatoshi, int64) { +func (lc *LightningChannel) availableCommitmentBalance( + view *htlcView, remoteChain bool, + buffer BufferType) (lnwire.MilliSatoshi, lntypes.WeightUnit) { // Compute the current balances for this commitment. This will take // into account HTLCs to determine the commit weight, which the diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 7ef5c118a..4accf1262 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -832,7 +832,7 @@ func TestForceClose(t *testing.T) { type forceCloseTestCase struct { chanType channeldb.ChannelType - expectedCommitWeight int64 + expectedCommitWeight lntypes.WeightUnit anchorAmt btcutil.Amount } @@ -4803,7 +4803,7 @@ func TestChanAvailableBandwidth(t *testing.T) { ) assertBandwidthEstimateCorrect := func(aliceInitiate bool, - numNonDustHtlcsOnCommit int64) { + numNonDustHtlcsOnCommit lntypes.WeightUnit) { // With the HTLC's added, we'll now query the AvailableBalance // method for the current available channel bandwidth from @@ -5189,7 +5189,7 @@ func TestChanCommitWeightDustHtlcs(t *testing.T) { // fromt the given channel's POV. // When sending htlcs we enforce the feebuffer on the commitment // transaction. - remoteCommitWeight := func(lc *LightningChannel) int64 { + remoteCommitWeight := func(lc *LightningChannel) lntypes.WeightUnit { remoteACKedIndex := lc.localCommitChain.tip().theirMessageIndex htlcView := lc.fetchHTLCView(remoteACKedIndex, lc.localUpdateLog.logIndex) @@ -10454,8 +10454,8 @@ func TestApplyCommitmentFee(t *testing.T) { balanceBelowReserve = lnwire.NewMSatFromSatoshis(5_000) // commitment weight with an additional htlc. - commitWeight int64 = input.BaseAnchorCommitmentTxWeight + - input.HTLCWeight + commitWeight lntypes.WeightUnit = input. + BaseAnchorCommitmentTxWeight + input.HTLCWeight // fee rate of 10 sat/vbyte. feePerKw = chainfee.SatPerKWeight(2500) diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 6ecef795b..96af8d7cf 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" ) @@ -471,7 +472,7 @@ func SecondLevelHtlcScript(chanType channeldb.ChannelType, initiator bool, } // CommitWeight returns the base commitment weight before adding HTLCs. -func CommitWeight(chanType channeldb.ChannelType) int64 { +func CommitWeight(chanType channeldb.ChannelType) lntypes.WeightUnit { switch { case chanType.IsTaproot(): return input.TaprootCommitWeight @@ -724,7 +725,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, // by the current fee-per-kw, then divide by 1000 to get the proper // fee. totalCommitWeight := CommitWeight(cb.chanState.ChanType) + - input.HTLCWeight*numHTLCs + lntypes.WeightUnit(input.HTLCWeight*numHTLCs) // With the weight known, we can now calculate the commitment fee, // ensuring that we account for any dust outputs trimmed above. diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index a99448768..1c6dbbabe 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chanfunding" "github.com/lightningnetwork/lnd/lnwire" ) @@ -241,13 +242,15 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // Based on the channel type, we determine the initial commit weight // and fee. - commitWeight := int64(input.CommitWeight) + commitWeight := input.CommitWeight if req.CommitType.IsTaproot() { commitWeight = input.TaprootCommitWeight } else if req.CommitType.HasAnchors() { - commitWeight = int64(input.AnchorCommitWeight) + commitWeight = input.AnchorCommitWeight } - commitFee := req.CommitFeePerKw.FeeForWeight(commitWeight) + commitFee := req.CommitFeePerKw.FeeForWeight( + lntypes.WeightUnit(commitWeight), + ) localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt) // TODO(halseth): make method take remote funding amount directly diff --git a/lnwallet/test_utils.go b/lnwallet/test_utils.go index e33d563c3..29213bb7f 100644 --- a/lnwallet/test_utils.go +++ b/lnwallet/test_utils.go @@ -16,6 +16,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" @@ -506,9 +507,10 @@ func calcStaticFee(chanType channeldb.ChannelType, numHTLCs int) btcutil.Amount htlcWeight = 172 feePerKw = btcutil.Amount(24/4) * 1000 ) - return feePerKw * - (btcutil.Amount(CommitWeight(chanType) + - htlcWeight*int64(numHTLCs))) / 1000 + htlcsWeight := htlcWeight * int64(numHTLCs) + totalWeight := CommitWeight(chanType) + lntypes.WeightUnit(htlcsWeight) + + return feePerKw * (btcutil.Amount(totalWeight)) / 1000 } // ForceStateTransition executes the necessary interaction between the two diff --git a/lnwallet/transactions_test.go b/lnwallet/transactions_test.go index 1f15523c4..d2a2a448b 100644 --- a/lnwallet/transactions_test.go +++ b/lnwallet/transactions_test.go @@ -913,7 +913,7 @@ func createTestChannelsForVectors(tc *testContext, chanType channeldb.ChannelTyp // Create the initial commitment transactions for the channel. feePerKw := chainfee.SatPerKWeight(feeRate) - commitWeight := int64(input.CommitWeight) + commitWeight := lntypes.WeightUnit(input.CommitWeight) if chanType.HasAnchors() { commitWeight = input.AnchorCommitWeight } diff --git a/sweep/aggregator.go b/sweep/aggregator.go index c812cbe2b..6028adca3 100644 --- a/sweep/aggregator.go +++ b/sweep/aggregator.go @@ -5,6 +5,8 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -201,8 +203,8 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { for _, pi := range inputs { op := pi.OutPoint() - // Get the size and skip if there's an error. - size, _, err := pi.WitnessType().SizeUpperBound() + // Get the size of the witness and skip if there's an error. + witnessSize, _, err := pi.WitnessType().SizeUpperBound() if err != nil { log.Warnf("Skipped input=%v: cannot get its size: %v", op, err) @@ -210,12 +212,27 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { continue } + //nolint:lll + // Calculate the size if the input is included in the tx. + // + // NOTE: When including this input, we need to account the + // non-witness data which is expressed in vb. + // + // TODO(yy): This is not accurate for tapscript input. We need + // to unify calculations used in the `TxWeightEstimator` inside + // `input/size.go` and `weightEstimator` in + // `weight_estimator.go`. And calculate the expected weights + // similar to BOLT-3: + // https://github.com/lightning/bolts/blob/master/03-transactions.md#appendix-a-expected-weights + wu := lntypes.VByte(input.InputSize).ToWU() + witnessSize + // Skip inputs that has too little budget. - minFee := minFeeRate.FeeForWeight(int64(size)) + minFee := minFeeRate.FeeForWeight(wu) if pi.params.Budget < minFee { log.Warnf("Skipped input=%v: has budget=%v, but the "+ - "min fee requires %v", op, pi.params.Budget, - minFee) + "min fee requires %v (feerate=%v), size=%v", op, + pi.params.Budget, minFee, + minFeeRate.FeePerVByte(), wu.ToVB()) continue } @@ -224,11 +241,12 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { startingFeeRate := pi.params.StartingFeeRate.UnwrapOr( chainfee.SatPerKWeight(0), ) - startingFee := startingFeeRate.FeeForWeight(int64(size)) + startingFee := startingFeeRate.FeeForWeight(wu) if pi.params.Budget < startingFee { log.Errorf("Skipped input=%v: has budget=%v, but the "+ - "starting fee requires %v", op, - pi.params.Budget, minFee) + "starting fee requires %v (feerate=%v), "+ + "size=%v", op, pi.params.Budget, startingFee, + startingFeeRate.FeePerVByte(), wu.ToVB()) continue } diff --git a/sweep/aggregator_test.go b/sweep/aggregator_test.go index 289f2780e..a32c849a0 100644 --- a/sweep/aggregator_test.go +++ b/sweep/aggregator_test.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/stretchr/testify/require" ) @@ -34,15 +35,19 @@ func TestBudgetAggregatorFilterInputs(t *testing.T) { // Mock the `SizeUpperBound` method to return an error exactly once. dummyErr := errors.New("dummy error") - wtErr.On("SizeUpperBound").Return(0, false, dummyErr).Once() + wtErr.On("SizeUpperBound").Return( + lntypes.WeightUnit(0), false, dummyErr).Once() // Create a mock WitnessType that gives the size. wt := &input.MockWitnessType{} defer wt.AssertExpectations(t) // Mock the `SizeUpperBound` method to return the size four times. - const wtSize = 100 - wt.On("SizeUpperBound").Return(wtSize, true, nil).Times(4) + const wu lntypes.WeightUnit = 100 + wt.On("SizeUpperBound").Return(wu, true, nil).Times(4) + + // Calculate the input size. + inpSize := lntypes.VByte(input.InputSize).ToWU() + wu // Create a mock input that will be filtered out due to error. inpErr := &input.MockInput{} @@ -62,9 +67,9 @@ func TestBudgetAggregatorFilterInputs(t *testing.T) { var ( // Define three budget values, one below the min fee rate, one // above and one equal to it. - budgetLow = minFeeRate.FeeForWeight(wtSize) - 1 - budgetEqual = minFeeRate.FeeForWeight(wtSize) - budgetHigh = minFeeRate.FeeForWeight(wtSize) + 1 + budgetLow = minFeeRate.FeeForWeight(inpSize) - 1 + budgetEqual = minFeeRate.FeeForWeight(inpSize) + budgetHigh = minFeeRate.FeeForWeight(inpSize) + 1 // Define three outpoints with different budget values. opLow = wire.OutPoint{Hash: chainhash.Hash{2}} @@ -396,8 +401,12 @@ func TestBudgetInputSetClusterInputs(t *testing.T) { // Mock the `SizeUpperBound` method to return the size 10 times since // we are using ten inputs. - const wtSize = 100 - wt.On("SizeUpperBound").Return(wtSize, true, nil).Times(10) + const wu lntypes.WeightUnit = 100 + wt.On("SizeUpperBound").Return(wu, true, nil).Times(10) + + // Calculate the input size. + inpSize := lntypes.VByte(input.InputSize).ToWU() + wu + wt.On("String").Return("mock witness type") // Mock the estimator to return a constant fee rate. @@ -407,8 +416,8 @@ func TestBudgetInputSetClusterInputs(t *testing.T) { var ( // Define two budget values, one below the min fee rate and one // above it. - budgetLow = minFeeRate.FeeForWeight(wtSize) - 1 - budgetHigh = minFeeRate.FeeForWeight(wtSize) + 1 + budgetLow = minFeeRate.FeeForWeight(inpSize) - 1 + budgetHigh = minFeeRate.FeeForWeight(inpSize) + 1 // Create three deadline heights, which means there are three // groups of inputs to be expected. diff --git a/sweep/fee_bumper.go b/sweep/fee_bumper.go index dd471efff..b4d429894 100644 --- a/sweep/fee_bumper.go +++ b/sweep/fee_bumper.go @@ -17,6 +17,7 @@ import ( "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -155,7 +156,7 @@ func (r *BumpRequest) MaxFeeRateAllowed() (chainfee.SatPerKWeight, error) { // calcSweepTxWeight calculates the weight of the sweep tx. It assumes a // sweeping tx always has a single output(change). func calcSweepTxWeight(inputs []input.Input, - outputPkScript []byte) (uint64, error) { + outputPkScript []byte) (lntypes.WeightUnit, error) { // Use a const fee rate as we only use the weight estimator to // calculate the size. @@ -175,7 +176,7 @@ func calcSweepTxWeight(inputs []input.Input, return 0, err } - return uint64(estimator.weight()), nil + return estimator.weight(), nil } // BumpResult is used by the Bumper to send updates about the tx being diff --git a/sweep/tx_input_set.go b/sweep/tx_input_set.go index 27cdafada..31f20b7db 100644 --- a/sweep/tx_input_set.go +++ b/sweep/tx_input_set.go @@ -314,7 +314,8 @@ func (b *BudgetInputSet) AddWalletInputs(wallet Wallet) error { } b.addInput(pi) - log.Debugf("Added wallet input %v to input set", pi) + log.Debugf("Added wallet input to input set: op=%v, amt=%v", + pi.OutPoint(), utxo.Value) // Return if we've reached the minimum output amount. if !b.NeedWalletInput() { diff --git a/sweep/weight_estimator.go b/sweep/weight_estimator.go index f705c826e..429b36ee5 100644 --- a/sweep/weight_estimator.go +++ b/sweep/weight_estimator.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -15,7 +16,7 @@ type weightEstimator struct { feeRate chainfee.SatPerKWeight parents map[chainhash.Hash]struct{} parentsFee btcutil.Amount - parentsWeight int64 + parentsWeight lntypes.WeightUnit // maxFeeRate is the max allowed fee rate configured by the user. maxFeeRate chainfee.SatPerKWeight @@ -102,7 +103,7 @@ func (w *weightEstimator) addOutput(txOut *wire.TxOut) { } // weight gets the estimated weight of the transaction. -func (w *weightEstimator) weight() int { +func (w *weightEstimator) weight() lntypes.WeightUnit { return w.estimator.Weight() } @@ -111,7 +112,7 @@ func (w *weightEstimator) weight() int { // parent transactions. func (w *weightEstimator) fee() btcutil.Amount { // Calculate the weight of the transaction. - weight := int64(w.estimator.Weight()) + weight := w.estimator.Weight() // Calculate the fee. fee := w.feeRate.FeeForWeight(weight) @@ -123,7 +124,7 @@ func (w *weightEstimator) fee() btcutil.Amount { // outputs, taking into account unconfirmed parent transactions (cpfp). func (w *weightEstimator) feeWithParent() btcutil.Amount { // Calculate fee and weight for just this tx. - childWeight := int64(w.estimator.Weight()) + childWeight := w.estimator.Weight() // Add combined weight of unconfirmed parent txes. totalWeight := childWeight + w.parentsWeight diff --git a/sweep/weight_estimator_test.go b/sweep/weight_estimator_test.go index d5beb5174..513aa01cc 100644 --- a/sweep/weight_estimator_test.go +++ b/sweep/weight_estimator_test.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/stretchr/testify/require" ) @@ -28,7 +29,7 @@ func TestWeightEstimator(t *testing.T) { require.NoError(t, w.add(&input1)) // The expectations is that this input is added. - const expectedWeight1 = 322 + const expectedWeight1 lntypes.WeightUnit = 322 require.Equal(t, expectedWeight1, w.weight()) require.Equal(t, testFeeRate.FeeForWeight(expectedWeight1), w.feeWithParent()) @@ -50,7 +51,7 @@ func TestWeightEstimator(t *testing.T) { // Pay for parent isn't possible because the parent pays a higher fee // rate than the child. We expect no additional fee on the child. - const expectedWeight2 = expectedWeight1 + 280 + const expectedWeight2 lntypes.WeightUnit = expectedWeight1 + 280 require.Equal(t, expectedWeight2, w.weight()) require.Equal(t, testFeeRate.FeeForWeight(expectedWeight2), w.feeWithParent()) @@ -70,7 +71,7 @@ func TestWeightEstimator(t *testing.T) { require.NoError(t, w.add(&input3)) // Expect the weight to increase because of the third input. - const expectedWeight3 = expectedWeight2 + 280 + const expectedWeight3 lntypes.WeightUnit = expectedWeight2 + 280 require.Equal(t, expectedWeight3, w.weight()) // Expect the fee to cover the child and the parent transaction at 20 @@ -107,7 +108,7 @@ func TestWeightEstimatorMaxFee(t *testing.T) { require.NoError(t, w.add(&childInput)) // The child weight should be 322 weight uints. - const childWeight = 322 + const childWeight lntypes.WeightUnit = 322 require.Equal(t, childWeight, w.weight()) // Check the fee is capped at the maximum allowed fee. The diff --git a/watchtower/blob/commitments.go b/watchtower/blob/commitments.go index f86240447..994c55caf 100644 --- a/watchtower/blob/commitments.go +++ b/watchtower/blob/commitments.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" ) @@ -115,7 +116,7 @@ func (c CommitmentType) ToRemoteWitnessType() (input.WitnessType, error) { // ToRemoteWitnessSize is the size of the witness that will be required to spend // the to_remote output. -func (c CommitmentType) ToRemoteWitnessSize() (int, error) { +func (c CommitmentType) ToRemoteWitnessSize() (lntypes.WeightUnit, error) { switch c { // Legacy channels (both tweaked and non-tweaked) spend from P2WKH // output. @@ -137,7 +138,7 @@ func (c CommitmentType) ToRemoteWitnessSize() (int, error) { // ToLocalWitnessSize is the size of the witness that will be required to spend // the to_local output. -func (c CommitmentType) ToLocalWitnessSize() (int, error) { +func (c CommitmentType) ToLocalWitnessSize() (lntypes.WeightUnit, error) { switch c { // An older ToLocalPenaltyWitnessSize constant used to underestimate the // size by one byte. The difference in weight can cause different output diff --git a/watchtower/lookout/justice_descriptor.go b/watchtower/lookout/justice_descriptor.go index 2c0623e65..96b414470 100644 --- a/watchtower/lookout/justice_descriptor.go +++ b/watchtower/lookout/justice_descriptor.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/wtdb" ) @@ -123,7 +124,7 @@ func (p *JusticeDescriptor) commitToRemoteInput() (*breachedInput, error) { // assembleJusticeTxn accepts the breached inputs recovered from state update // and attempts to construct the justice transaction that sweeps the victims // funds to their wallet and claims the watchtower's reward. -func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64, +func (p *JusticeDescriptor) assembleJusticeTxn(txWeight lntypes.WeightUnit, inputs ...*breachedInput) (*wire.MsgTx, error) { justiceTxn := wire.NewMsgTx(2) @@ -287,7 +288,7 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) { // TODO(conner): sweep htlc outputs - txWeight := int64(weightEstimate.Weight()) + txWeight := weightEstimate.Weight() return p.assembleJusticeTxn(txWeight, sweepInputs...) } diff --git a/watchtower/lookout/justice_descriptor_test.go b/watchtower/lookout/justice_descriptor_test.go index 2ca187fdc..a07b440ad 100644 --- a/watchtower/lookout/justice_descriptor_test.go +++ b/watchtower/lookout/justice_descriptor_test.go @@ -317,7 +317,7 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) { } outputs, err := policy.ComputeJusticeTxOuts( - totalAmount, int64(txWeight), justiceKit.SweepAddress(), + totalAmount, txWeight, justiceKit.SweepAddress(), sessionInfo.RewardAddress, ) require.NoError(t, err) diff --git a/watchtower/wtclient/backup_task.go b/watchtower/wtclient/backup_task.go index 49f917514..1e90d7b37 100644 --- a/watchtower/wtclient/backup_task.go +++ b/watchtower/wtclient/backup_task.go @@ -216,7 +216,7 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody, // Now, compute the output values depending on whether FlagReward is set // in the current session's policy. outputs, err := session.Policy.ComputeJusticeTxOuts( - t.totalAmt, int64(weightEstimate.Weight()), + t.totalAmt, weightEstimate.Weight(), t.sweepPkScript, session.RewardPkScript, ) if err != nil { diff --git a/watchtower/wtpolicy/policy.go b/watchtower/wtpolicy/policy.go index 9d5763fb2..89804685b 100644 --- a/watchtower/wtpolicy/policy.go +++ b/watchtower/wtpolicy/policy.go @@ -6,6 +6,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" @@ -180,8 +181,9 @@ func (p *Policy) Validate() error { // that pays no reward to the tower. The value is computed using the weight of // of the justice transaction and subtracting an amount that satisfies the // policy's fee rate. -func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount, - txWeight int64, sweepScript []byte) (btcutil.Amount, error) { +func (p *Policy) ComputeAltruistOutput( + totalAmt btcutil.Amount, txWeight lntypes.WeightUnit, + sweepScript []byte) (btcutil.Amount, error) { txFee := p.SweepFeeRate.FeeForWeight(txWeight) if txFee > totalAmt { @@ -204,7 +206,7 @@ func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount, // and reward rate. The reward to he tower is subtracted first, before // splitting the remaining balance amongst the victim and fees. func (p *Policy) ComputeRewardOutputs(totalAmt btcutil.Amount, - txWeight int64, + txWeight lntypes.WeightUnit, rewardScript []byte) (btcutil.Amount, btcutil.Amount, error) { txFee := p.SweepFeeRate.FeeForWeight(txWeight) @@ -266,7 +268,8 @@ func ComputeRewardAmount(total btcutil.Amount, base, rate uint32) btcutil.Amount // rewardPkScript is the pkScript of the tower where its reward will be // deposited, and will be // ignored if the blob type does not specify a reward. -func (p *Policy) ComputeJusticeTxOuts(totalAmt btcutil.Amount, txWeight int64, +func (p *Policy) ComputeJusticeTxOuts( + totalAmt btcutil.Amount, txWeight lntypes.WeightUnit, sweepPkScript, rewardPkScript []byte) ([]*wire.TxOut, error) { var outputs []*wire.TxOut