Merge pull request #4905 from LN-Zap/feat/spend-unconfirmed-estimate
Support spend_unconfirmed in EstimateFee and FundPsbt
This commit is contained in:
16 files changed
+1068
-906
No files matched your search
@@ -484,7 +484,7 @@ func (b *BtcWallet) ImportPublicKey(pubKey *btcec.PublicKey,
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
|
||||
feeRate chainfee.SatPerKWeight, minconf int32, label string) (*wire.MsgTx, error) {
|
||||
feeRate chainfee.SatPerKWeight, minConfs int32, label string) (*wire.MsgTx, error) {
|
||||
|
||||
// Convert our fee rate from sat/kw to sat/kb since it's required by
|
||||
// SendOutputs.
|
||||
@@ -495,13 +495,13 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
|
||||
return nil, lnwallet.ErrNoOutputs
|
||||
}
|
||||
|
||||
// Sanity check minconf.
|
||||
if minconf < 0 {
|
||||
// Sanity check minConfs.
|
||||
if minConfs < 0 {
|
||||
return nil, lnwallet.ErrInvalidMinconf
|
||||
}
|
||||
|
||||
return b.wallet.SendOutputs(
|
||||
outputs, nil, defaultAccount, minconf, feeSatPerKB, label,
|
||||
outputs, nil, defaultAccount, minConfs, feeSatPerKB, label,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -519,7 +519,8 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (b *BtcWallet) CreateSimpleTx(outputs []*wire.TxOut,
|
||||
feeRate chainfee.SatPerKWeight, dryRun bool) (*txauthor.AuthoredTx, error) {
|
||||
feeRate chainfee.SatPerKWeight, minConfs int32,
|
||||
dryRun bool) (*txauthor.AuthoredTx, error) {
|
||||
|
||||
// The fee rate is passed in using units of sat/kw, so we'll convert
|
||||
// this to sat/KB as the CreateSimpleTx method requires this unit.
|
||||
@@ -529,6 +530,12 @@ func (b *BtcWallet) CreateSimpleTx(outputs []*wire.TxOut,
|
||||
if len(outputs) < 1 {
|
||||
return nil, lnwallet.ErrNoOutputs
|
||||
}
|
||||
|
||||
// Sanity check minConfs.
|
||||
if minConfs < 0 {
|
||||
return nil, lnwallet.ErrInvalidMinconf
|
||||
}
|
||||
|
||||
for _, output := range outputs {
|
||||
// When checking an output for things like dusty-ness, we'll
|
||||
// use the default mempool relay fee rather than the target
|
||||
@@ -544,7 +551,7 @@ func (b *BtcWallet) CreateSimpleTx(outputs []*wire.TxOut,
|
||||
}
|
||||
|
||||
return b.wallet.CreateSimpleTx(
|
||||
nil, defaultAccount, outputs, 1, feeSatPerKB, dryRun,
|
||||
nil, defaultAccount, outputs, minConfs, feeSatPerKB, dryRun,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -608,11 +615,11 @@ func (b *BtcWallet) ReleaseOutput(id wtxmgr.LockID, op wire.OutPoint) error {
|
||||
}
|
||||
|
||||
// ListUnspentWitness returns all unspent outputs which are version 0 witness
|
||||
// programs. The 'minconfirms' and 'maxconfirms' parameters indicate the minimum
|
||||
// programs. The 'minConfs' and 'maxConfs' parameters indicate the minimum
|
||||
// and maximum number of confirmations an output needs in order to be returned
|
||||
// by this method. Passing -1 as 'minconfirms' indicates that even unconfirmed
|
||||
// outputs should be returned. Using MaxInt32 as 'maxconfirms' implies returning
|
||||
// all outputs with at least 'minconfirms'. The account parameter serves as a
|
||||
// by this method. Passing -1 as 'minConfs' indicates that even unconfirmed
|
||||
// outputs should be returned. Using MaxInt32 as 'maxConfs' implies returning
|
||||
// all outputs with at least 'minConfs'. The account parameter serves as a
|
||||
// filter to retrieve the unspent outputs for a specific account. When empty,
|
||||
// the unspent outputs of all wallet accounts are returned.
|
||||
//
|
||||
|
||||
@@ -66,7 +66,7 @@ var (
|
||||
var ErrNoOutputs = errors.New("no outputs")
|
||||
|
||||
// ErrInvalidMinconf is returned if we try to create a transaction with
|
||||
// invalid minconf value.
|
||||
// invalid minConfs value.
|
||||
var ErrInvalidMinconf = errors.New("minimum number of confirmations must " +
|
||||
"be a non-negative number")
|
||||
|
||||
@@ -236,7 +236,7 @@ type WalletController interface {
|
||||
//
|
||||
// NOTE: This method requires the global coin selection lock to be held.
|
||||
SendOutputs(outputs []*wire.TxOut,
|
||||
feeRate chainfee.SatPerKWeight, minconf int32, label string) (*wire.MsgTx, error)
|
||||
feeRate chainfee.SatPerKWeight, minConfs int32, label string) (*wire.MsgTx, error)
|
||||
|
||||
// CreateSimpleTx creates a Bitcoin transaction paying to the specified
|
||||
// outputs. The transaction is not broadcasted to the network. In the
|
||||
@@ -251,20 +251,20 @@ type WalletController interface {
|
||||
//
|
||||
// NOTE: This method requires the global coin selection lock to be held.
|
||||
CreateSimpleTx(outputs []*wire.TxOut, feeRate chainfee.SatPerKWeight,
|
||||
dryRun bool) (*txauthor.AuthoredTx, error)
|
||||
minConfs int32, dryRun bool) (*txauthor.AuthoredTx, error)
|
||||
|
||||
// ListUnspentWitness returns all unspent outputs which are version 0
|
||||
// witness programs. The 'minconfirms' and 'maxconfirms' parameters
|
||||
// witness programs. The 'minConfs' and 'maxConfs' parameters
|
||||
// indicate the minimum and maximum number of confirmations an output
|
||||
// needs in order to be returned by this method. Passing -1 as
|
||||
// 'minconfirms' indicates that even unconfirmed outputs should be
|
||||
// returned. Using MaxInt32 as 'maxconfirms' implies returning all
|
||||
// outputs with at least 'minconfirms'. The account parameter serves as
|
||||
// 'minConfs' indicates that even unconfirmed outputs should be
|
||||
// returned. Using MaxInt32 as 'maxConfs' implies returning all
|
||||
// outputs with at least 'minConfs'. The account parameter serves as
|
||||
// a filter to retrieve the unspent outputs for a specific account.
|
||||
// When empty, the unspent outputs of all wallet accounts are returned.
|
||||
//
|
||||
// NOTE: This method requires the global coin selection lock to be held.
|
||||
ListUnspentWitness(minconfirms, maxconfirms int32,
|
||||
ListUnspentWitness(minConfs, maxConfs int32,
|
||||
accountFilter string) ([]*Utxo, error)
|
||||
|
||||
// ListTransactionDetails returns a list of all transactions which are
|
||||
|
||||
@@ -2547,6 +2547,8 @@ func testLastUnusedAddr(miner *rpctest.Harness,
|
||||
// testCreateSimpleTx checks that a call to CreateSimpleTx will return a
|
||||
// transaction that is equal to the one that is being created by SendOutputs in
|
||||
// a subsequent call.
|
||||
// All test cases are doubled-up: one for testing unconfirmed inputs,
|
||||
// one for testing only confirmed inputs.
|
||||
func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
|
||||
_ *lnwallet.LightningWallet, t *testing.T) {
|
||||
|
||||
@@ -2558,51 +2560,108 @@ func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
|
||||
|
||||
// The test cases we will run through for all backends.
|
||||
testCases := []struct {
|
||||
outVals []int64
|
||||
feeRate chainfee.SatPerKWeight
|
||||
valid bool
|
||||
outVals []int64
|
||||
feeRate chainfee.SatPerKWeight
|
||||
valid bool
|
||||
unconfirmed bool
|
||||
}{
|
||||
{
|
||||
outVals: []int64{},
|
||||
feeRate: 2500,
|
||||
valid: false, // No outputs.
|
||||
outVals: []int64{},
|
||||
feeRate: 2500,
|
||||
valid: false, // No outputs.
|
||||
unconfirmed: false,
|
||||
},
|
||||
{
|
||||
outVals: []int64{},
|
||||
feeRate: 2500,
|
||||
valid: false, // No outputs.
|
||||
unconfirmed: true,
|
||||
},
|
||||
|
||||
{
|
||||
outVals: []int64{200},
|
||||
feeRate: 2500,
|
||||
valid: false, // Dust output.
|
||||
outVals: []int64{200},
|
||||
feeRate: 2500,
|
||||
valid: false, // Dust output.
|
||||
unconfirmed: false,
|
||||
},
|
||||
{
|
||||
outVals: []int64{200},
|
||||
feeRate: 2500,
|
||||
valid: false, // Dust output.
|
||||
unconfirmed: true,
|
||||
},
|
||||
|
||||
{
|
||||
outVals: []int64{1e8},
|
||||
feeRate: 2500,
|
||||
valid: true,
|
||||
outVals: []int64{1e8},
|
||||
feeRate: 2500,
|
||||
valid: true,
|
||||
unconfirmed: false,
|
||||
},
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 2500,
|
||||
valid: true,
|
||||
outVals: []int64{1e8},
|
||||
feeRate: 2500,
|
||||
valid: true,
|
||||
unconfirmed: true,
|
||||
},
|
||||
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 2500,
|
||||
valid: true,
|
||||
unconfirmed: false,
|
||||
},
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 12500,
|
||||
valid: true,
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 2500,
|
||||
valid: true,
|
||||
unconfirmed: true,
|
||||
},
|
||||
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 12500,
|
||||
valid: true,
|
||||
unconfirmed: false,
|
||||
},
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 50000,
|
||||
valid: true,
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 12500,
|
||||
valid: true,
|
||||
unconfirmed: true,
|
||||
},
|
||||
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 50000,
|
||||
valid: true,
|
||||
unconfirmed: false,
|
||||
},
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5},
|
||||
feeRate: 50000,
|
||||
valid: true,
|
||||
unconfirmed: true,
|
||||
},
|
||||
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5, 1e8, 2e8,
|
||||
1e8, 2e7, 3e5},
|
||||
feeRate: 44250,
|
||||
valid: true,
|
||||
unconfirmed: false,
|
||||
},
|
||||
{
|
||||
outVals: []int64{1e8, 2e8, 1e8, 2e7, 3e5, 1e8, 2e8,
|
||||
1e8, 2e7, 3e5},
|
||||
feeRate: 44250,
|
||||
valid: true,
|
||||
feeRate: 44250,
|
||||
valid: true,
|
||||
unconfirmed: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
var minConfs int32 = 1
|
||||
|
||||
feeRate := test.feeRate
|
||||
|
||||
// Grab some fresh addresses from the miner that we will send
|
||||
@@ -2629,7 +2688,7 @@ func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
|
||||
|
||||
// Now try creating a tx spending to these outputs.
|
||||
createTx, createErr := w.CreateSimpleTx(
|
||||
outputs, feeRate, true,
|
||||
outputs, feeRate, minConfs, true,
|
||||
)
|
||||
switch {
|
||||
case test.valid && createErr != nil:
|
||||
@@ -2646,7 +2705,7 @@ func testCreateSimpleTx(r *rpctest.Harness, w *lnwallet.LightningWallet,
|
||||
// _very_ similar to the one we just created being sent. The
|
||||
// only difference is that the dry run tx is not signed, and
|
||||
// that the change output position might be different.
|
||||
tx, sendErr := w.SendOutputs(outputs, feeRate, 1, labels.External)
|
||||
tx, sendErr := w.SendOutputs(outputs, feeRate, minConfs, labels.External)
|
||||
switch {
|
||||
case test.valid && sendErr != nil:
|
||||
t.Fatalf("got unexpected error when sending tx: %v",
|
||||
|
||||
Reference in new issue
Block a user