lnwallet: Use TxWeightEstimator for funding transaction.
This commit is contained in:
parent
fb32c3f73d
commit
ced530f98e
@ -504,13 +504,13 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
|
|||||||
// don't need to perform any coin selection. Otherwise, attempt to
|
// don't need to perform any coin selection. Otherwise, attempt to
|
||||||
// obtain enough coins to meet the required funding amount.
|
// obtain enough coins to meet the required funding amount.
|
||||||
if req.fundingAmount != 0 {
|
if req.fundingAmount != 0 {
|
||||||
// Coin selection is done on the basis of sat-per-byte, so
|
// Coin selection is done on the basis of sat-per-weight, so
|
||||||
// we'll query the fee estimator for a fee to use to ensure the
|
// we'll query the fee estimator for a fee to use to ensure the
|
||||||
// funding transaction gets into the _next_ block.
|
// funding transaction gets into the _next_ block.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): shouldn't be targeting next block
|
// TODO(roasbeef): shouldn't be targeting next block
|
||||||
satPerByte := l.Cfg.FeeEstimator.EstimateFeePerByte(1)
|
satPerWeight := l.Cfg.FeeEstimator.EstimateFeePerWeight(1)
|
||||||
err := l.selectCoinsAndChange(satPerByte, req.fundingAmount,
|
err := l.selectCoinsAndChange(satPerWeight, req.fundingAmount,
|
||||||
reservation.ourContribution)
|
reservation.ourContribution)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.err <- err
|
req.err <- err
|
||||||
@ -1039,20 +1039,19 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
|
|||||||
|
|
||||||
// Next, create the spending scriptSig, and then verify that the script
|
// Next, create the spending scriptSig, and then verify that the script
|
||||||
// is complete, allowing us to spend from the funding transaction.
|
// is complete, allowing us to spend from the funding transaction.
|
||||||
theirCommitSig := msg.theirCommitmentSig
|
|
||||||
channelValue := int64(res.partialState.Capacity)
|
channelValue := int64(res.partialState.Capacity)
|
||||||
hashCache := txscript.NewTxSigHashes(&commitTx)
|
hashCache := txscript.NewTxSigHashes(&commitTx)
|
||||||
sigHash, err := txscript.CalcWitnessSigHash(witnessScript, hashCache,
|
sigHash, err := txscript.CalcWitnessSigHash(witnessScript, hashCache,
|
||||||
txscript.SigHashAll, &commitTx, 0, channelValue)
|
txscript.SigHashAll, &commitTx, 0, channelValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg.err <- fmt.Errorf("counterparty's commitment signature is "+
|
msg.err <- err
|
||||||
"invalid: %v", err)
|
|
||||||
msg.completeChan <- nil
|
msg.completeChan <- nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that we've received a valid signature from the remote party
|
// Verify that we've received a valid signature from the remote party
|
||||||
// for our version of the commitment transaction.
|
// for our version of the commitment transaction.
|
||||||
|
theirCommitSig := msg.theirCommitmentSig
|
||||||
sig, err := btcec.ParseSignature(theirCommitSig, btcec.S256())
|
sig, err := btcec.ParseSignature(theirCommitSig, btcec.S256())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg.err <- err
|
msg.err <- err
|
||||||
@ -1268,8 +1267,8 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
|
|||||||
// within the passed contribution's inputs. If necessary, a change address will
|
// within the passed contribution's inputs. If necessary, a change address will
|
||||||
// also be generated.
|
// also be generated.
|
||||||
// TODO(roasbeef): remove hardcoded fees and req'd confs for outputs.
|
// TODO(roasbeef): remove hardcoded fees and req'd confs for outputs.
|
||||||
func (l *LightningWallet) selectCoinsAndChange(feeRate uint64, amt btcutil.Amount,
|
func (l *LightningWallet) selectCoinsAndChange(feeRatePerWeight uint64,
|
||||||
contribution *ChannelContribution) error {
|
amt btcutil.Amount, contribution *ChannelContribution) error {
|
||||||
|
|
||||||
// We hold the coin select mutex while querying for outputs, and
|
// We hold the coin select mutex while querying for outputs, and
|
||||||
// performing coin selection in order to avoid inadvertent double
|
// performing coin selection in order to avoid inadvertent double
|
||||||
@ -1277,8 +1276,8 @@ func (l *LightningWallet) selectCoinsAndChange(feeRate uint64, amt btcutil.Amoun
|
|||||||
l.coinSelectMtx.Lock()
|
l.coinSelectMtx.Lock()
|
||||||
defer l.coinSelectMtx.Unlock()
|
defer l.coinSelectMtx.Unlock()
|
||||||
|
|
||||||
walletLog.Infof("Performing coin selection using %v sat/byte as fee "+
|
walletLog.Infof("Performing coin selection using %v sat/weight as fee "+
|
||||||
"rate", feeRate)
|
"rate", feeRatePerWeight)
|
||||||
|
|
||||||
// Find all unlocked unspent witness outputs with greater than 1
|
// Find all unlocked unspent witness outputs with greater than 1
|
||||||
// confirmation.
|
// confirmation.
|
||||||
@ -1291,7 +1290,7 @@ func (l *LightningWallet) selectCoinsAndChange(feeRate uint64, amt btcutil.Amoun
|
|||||||
// Perform coin selection over our available, unlocked unspent outputs
|
// Perform coin selection over our available, unlocked unspent outputs
|
||||||
// in order to find enough coins to meet the funding amount
|
// in order to find enough coins to meet the funding amount
|
||||||
// requirements.
|
// requirements.
|
||||||
selectedCoins, changeAmt, err := coinSelect(feeRate, amt, coins)
|
selectedCoins, changeAmt, err := coinSelect(feeRatePerWeight, amt, coins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1419,33 +1418,9 @@ func selectInputs(amt btcutil.Amount, coins []*Utxo) (btcutil.Amount, []*wire.Ou
|
|||||||
// change output to fund amt satoshis, adhering to the specified fee rate. The
|
// change output to fund amt satoshis, adhering to the specified fee rate. The
|
||||||
// specified fee rate should be expressed in sat/byte for coin selection to
|
// specified fee rate should be expressed in sat/byte for coin selection to
|
||||||
// function properly.
|
// function properly.
|
||||||
func coinSelect(feeRate uint64, amt btcutil.Amount,
|
func coinSelect(feeRatePerWeight uint64, amt btcutil.Amount,
|
||||||
coins []*Utxo) ([]*wire.OutPoint, btcutil.Amount, error) {
|
coins []*Utxo) ([]*wire.OutPoint, btcutil.Amount, error) {
|
||||||
|
|
||||||
const (
|
|
||||||
// txOverhead is the overhead of a transaction residing within
|
|
||||||
// the version number and lock time.
|
|
||||||
txOverhead = 8
|
|
||||||
|
|
||||||
// p2wkhSpendSize an estimate of the number of bytes it takes
|
|
||||||
// to spend a p2wkh output.
|
|
||||||
//
|
|
||||||
// (p2wkh witness) + txid + index + varint script size + sequence
|
|
||||||
// TODO(roasbeef): div by 3 due to witness size?
|
|
||||||
p2wkhSpendSize = (1 + 73 + 1 + 33) + 32 + 4 + 1 + 4
|
|
||||||
|
|
||||||
// p2wkhOutputSize is an estimate of the size of a regualr
|
|
||||||
// p2wkh output.
|
|
||||||
//
|
|
||||||
// 8 (output) + 1 (var int script) + 22 (p2wkh output)
|
|
||||||
p2wkhOutputSize = 8 + 1 + 22
|
|
||||||
|
|
||||||
// p2wkhOutputSize is an estimate of the p2wsh funding uotput.
|
|
||||||
p2wshOutputSize = 8 + 1 + 34
|
|
||||||
)
|
|
||||||
|
|
||||||
var estimatedSize int
|
|
||||||
|
|
||||||
amtNeeded := amt
|
amtNeeded := amt
|
||||||
for {
|
for {
|
||||||
// First perform an initial round of coin selection to estimate
|
// First perform an initial round of coin selection to estimate
|
||||||
@ -1455,10 +1430,20 @@ func coinSelect(feeRate uint64, amt btcutil.Amount,
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on the selected coins, estimate the size of the final
|
var weightEstimate TxWeightEstimator
|
||||||
// fully signed transaction.
|
|
||||||
estimatedSize = ((len(selectedUtxos) * p2wkhSpendSize) +
|
for range selectedUtxos {
|
||||||
p2wshOutputSize + txOverhead)
|
// Assume all selected inputs are P2WKH inputs.
|
||||||
|
// TODO: Handle wallets that have non-witness UTXOs.
|
||||||
|
weightEstimate.AddP2WKHInput()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channel funding multisig output is P2WSH.
|
||||||
|
weightEstimate.AddP2WSHOutput()
|
||||||
|
|
||||||
|
// Assume that change output is a P2WKH output.
|
||||||
|
// TODO: Handle wallets that generate non-witness change addresses.
|
||||||
|
weightEstimate.AddP2WKHOutput()
|
||||||
|
|
||||||
// The difference between the selected amount and the amount
|
// The difference between the selected amount and the amount
|
||||||
// requested will be used to pay fees, and generate a change
|
// requested will be used to pay fees, and generate a change
|
||||||
@ -1469,9 +1454,10 @@ func coinSelect(feeRate uint64, amt btcutil.Amount,
|
|||||||
// amount isn't enough to pay fees, then increase the requested
|
// amount isn't enough to pay fees, then increase the requested
|
||||||
// coin amount by the estimate required fee, performing another
|
// coin amount by the estimate required fee, performing another
|
||||||
// round of coin selection.
|
// round of coin selection.
|
||||||
requiredFee := btcutil.Amount(uint64(estimatedSize) * feeRate)
|
requiredFee := btcutil.Amount(
|
||||||
|
uint64(weightEstimate.Weight()) * feeRatePerWeight)
|
||||||
if overShootAmt < requiredFee {
|
if overShootAmt < requiredFee {
|
||||||
amtNeeded += requiredFee
|
amtNeeded = amt + requiredFee
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user