mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-06-06 13:09:52 +02:00
lnd+lnwallet: fundmax flag for openchannel
This commit is contained in:
parent
0e5b3e77cb
commit
5d88693852
@ -4088,23 +4088,26 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req := &lnwallet.InitFundingReserveMsg{
|
req := &lnwallet.InitFundingReserveMsg{
|
||||||
ChainHash: &msg.ChainHash,
|
ChainHash: &msg.ChainHash,
|
||||||
PendingChanID: chanID,
|
PendingChanID: chanID,
|
||||||
NodeID: peerKey,
|
NodeID: peerKey,
|
||||||
NodeAddr: msg.Peer.Address(),
|
NodeAddr: msg.Peer.Address(),
|
||||||
SubtractFees: msg.SubtractFees,
|
SubtractFees: msg.SubtractFees,
|
||||||
LocalFundingAmt: localAmt,
|
LocalFundingAmt: localAmt,
|
||||||
RemoteFundingAmt: 0,
|
RemoteFundingAmt: 0,
|
||||||
CommitFeePerKw: commitFeePerKw,
|
FundUpToMaxAmt: msg.FundUpToMaxAmt,
|
||||||
FundingFeePerKw: msg.FundingFeePerKw,
|
MinFundAmt: msg.MinFundAmt,
|
||||||
PushMSat: msg.PushAmt,
|
RemoteChanReserve: chanReserve,
|
||||||
Flags: channelFlags,
|
CommitFeePerKw: commitFeePerKw,
|
||||||
MinConfs: msg.MinConfs,
|
FundingFeePerKw: msg.FundingFeePerKw,
|
||||||
CommitType: commitType,
|
PushMSat: msg.PushAmt,
|
||||||
ChanFunder: msg.ChanFunder,
|
Flags: channelFlags,
|
||||||
ZeroConf: zeroConf,
|
MinConfs: msg.MinConfs,
|
||||||
OptionScidAlias: scid,
|
CommitType: commitType,
|
||||||
ScidAliasFeature: scidFeatureVal,
|
ChanFunder: msg.ChanFunder,
|
||||||
|
ZeroConf: zeroConf,
|
||||||
|
OptionScidAlias: scid,
|
||||||
|
ScidAliasFeature: scidFeatureVal,
|
||||||
}
|
}
|
||||||
|
|
||||||
reservation, err := f.cfg.Wallet.InitChannelReservation(req)
|
reservation, err := f.cfg.Wallet.InitChannelReservation(req)
|
||||||
|
@ -710,7 +710,7 @@ func openChannel(t *testing.T, alice, bob *testNode, localFundingAmt,
|
|||||||
*wire.OutPoint, *wire.MsgTx) {
|
*wire.OutPoint, *wire.MsgTx) {
|
||||||
|
|
||||||
publ := fundChannel(
|
publ := fundChannel(
|
||||||
t, alice, bob, localFundingAmt, pushAmt, false, numConfs,
|
t, alice, bob, localFundingAmt, pushAmt, false, 0, 0, numConfs,
|
||||||
updateChan, announceChan, nil,
|
updateChan, announceChan, nil,
|
||||||
)
|
)
|
||||||
fundingOutPoint := &wire.OutPoint{
|
fundingOutPoint := &wire.OutPoint{
|
||||||
@ -723,7 +723,8 @@ func openChannel(t *testing.T, alice, bob *testNode, localFundingAmt,
|
|||||||
// fundChannel takes the funding process to the point where the funding
|
// fundChannel takes the funding process to the point where the funding
|
||||||
// transaction is confirmed on-chain. Returns the funding tx.
|
// transaction is confirmed on-chain. Returns the funding tx.
|
||||||
func fundChannel(t *testing.T, alice, bob *testNode, localFundingAmt,
|
func fundChannel(t *testing.T, alice, bob *testNode, localFundingAmt,
|
||||||
pushAmt btcutil.Amount, subtractFees bool, numConfs uint32,
|
pushAmt btcutil.Amount, subtractFees bool, fundUpToMaxAmt,
|
||||||
|
minFundAmt btcutil.Amount, numConfs uint32, //nolint:unparam
|
||||||
updateChan chan *lnrpc.OpenStatusUpdate, announceChan bool,
|
updateChan chan *lnrpc.OpenStatusUpdate, announceChan bool,
|
||||||
chanType *lnwire.ChannelType) *wire.MsgTx {
|
chanType *lnwire.ChannelType) *wire.MsgTx {
|
||||||
|
|
||||||
@ -734,6 +735,8 @@ func fundChannel(t *testing.T, alice, bob *testNode, localFundingAmt,
|
|||||||
TargetPubkey: bob.privKey.PubKey(),
|
TargetPubkey: bob.privKey.PubKey(),
|
||||||
ChainHash: *fundingNetParams.GenesisHash,
|
ChainHash: *fundingNetParams.GenesisHash,
|
||||||
SubtractFees: subtractFees,
|
SubtractFees: subtractFees,
|
||||||
|
FundUpToMaxAmt: fundUpToMaxAmt,
|
||||||
|
MinFundAmt: minFundAmt,
|
||||||
LocalFundingAmt: localFundingAmt,
|
LocalFundingAmt: localFundingAmt,
|
||||||
PushAmt: lnwire.NewMSatFromSatoshis(pushAmt),
|
PushAmt: lnwire.NewMSatFromSatoshis(pushAmt),
|
||||||
FundingFeePerKw: 1000,
|
FundingFeePerKw: 1000,
|
||||||
@ -3730,7 +3733,7 @@ func TestFundingManagerFundAll(t *testing.T) {
|
|||||||
// Initiate a fund channel, and inspect the funding tx.
|
// Initiate a fund channel, and inspect the funding tx.
|
||||||
pushAmt := btcutil.Amount(0)
|
pushAmt := btcutil.Amount(0)
|
||||||
fundingTx := fundChannel(
|
fundingTx := fundChannel(
|
||||||
t, alice, bob, test.spendAmt, pushAmt, true, 1,
|
t, alice, bob, test.spendAmt, pushAmt, true, 0, 0, 1,
|
||||||
updateChan, true, nil,
|
updateChan, true, nil,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -3761,6 +3764,157 @@ func TestFundingManagerFundAll(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFundingManagerFundMax tests that we can initiate a funding request to use
|
||||||
|
// the maximum allowed funds remaining in the wallet.
|
||||||
|
func TestFundingManagerFundMax(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Helper function to create a test utxos
|
||||||
|
constructTestUtxos := func(values ...btcutil.Amount) []*lnwallet.Utxo {
|
||||||
|
var utxos []*lnwallet.Utxo
|
||||||
|
for _, value := range values {
|
||||||
|
utxos = append(utxos, &lnwallet.Utxo{
|
||||||
|
AddressType: lnwallet.WitnessPubKey,
|
||||||
|
Value: value,
|
||||||
|
PkScript: mock.CoinPkScript,
|
||||||
|
OutPoint: wire.OutPoint{
|
||||||
|
Hash: chainhash.Hash{},
|
||||||
|
Index: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return utxos
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
coins []*lnwallet.Utxo
|
||||||
|
fundUpToMaxAmt btcutil.Amount
|
||||||
|
minFundAmt btcutil.Amount
|
||||||
|
pushAmt btcutil.Amount
|
||||||
|
change bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
// We will spend all the funds in the wallet, and expect
|
||||||
|
// no change output due to the dust limit.
|
||||||
|
coins: constructTestUtxos(
|
||||||
|
MaxBtcFundingAmount + 1,
|
||||||
|
),
|
||||||
|
fundUpToMaxAmt: MaxBtcFundingAmount,
|
||||||
|
minFundAmt: MinChanFundingSize,
|
||||||
|
pushAmt: 0,
|
||||||
|
change: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// We spend less than the funds in the wallet, so a
|
||||||
|
// change output should be created.
|
||||||
|
coins: constructTestUtxos(
|
||||||
|
2 * MaxBtcFundingAmount,
|
||||||
|
),
|
||||||
|
fundUpToMaxAmt: MaxBtcFundingAmount,
|
||||||
|
minFundAmt: MinChanFundingSize,
|
||||||
|
pushAmt: 0,
|
||||||
|
change: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// We spend less than the funds in the wallet when
|
||||||
|
// setting a smaller channel size, so a change output
|
||||||
|
// should be created.
|
||||||
|
coins: constructTestUtxos(
|
||||||
|
MaxBtcFundingAmount,
|
||||||
|
),
|
||||||
|
fundUpToMaxAmt: MaxBtcFundingAmount / 2,
|
||||||
|
minFundAmt: MinChanFundingSize,
|
||||||
|
pushAmt: 0,
|
||||||
|
change: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// We are using the entirety of two inputs for the
|
||||||
|
// funding of a channel, hence expect no change output.
|
||||||
|
coins: constructTestUtxos(
|
||||||
|
MaxBtcFundingAmount/2, MaxBtcFundingAmount/2,
|
||||||
|
),
|
||||||
|
fundUpToMaxAmt: MaxBtcFundingAmount,
|
||||||
|
minFundAmt: MinChanFundingSize,
|
||||||
|
pushAmt: 0,
|
||||||
|
change: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// We are using a fraction of two inputs for the funding
|
||||||
|
// of our channel, hence expect a change output.
|
||||||
|
coins: constructTestUtxos(
|
||||||
|
MaxBtcFundingAmount/2, MaxBtcFundingAmount/2,
|
||||||
|
),
|
||||||
|
fundUpToMaxAmt: MaxBtcFundingAmount / 2,
|
||||||
|
minFundAmt: MinChanFundingSize,
|
||||||
|
pushAmt: 0,
|
||||||
|
change: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// We are funding a channel with half of the balance in
|
||||||
|
// our wallet hence expect a change output. Furthermore
|
||||||
|
// we push half of the funding amount to the remote end
|
||||||
|
// which we expect to succeed.
|
||||||
|
coins: constructTestUtxos(MaxBtcFundingAmount),
|
||||||
|
fundUpToMaxAmt: MaxBtcFundingAmount / 2,
|
||||||
|
minFundAmt: MinChanFundingSize / 4,
|
||||||
|
pushAmt: MaxBtcFundingAmount / 4,
|
||||||
|
change: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
test := test
|
||||||
|
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// We set up our mock wallet to control a list of UTXOs
|
||||||
|
// that sum to more than the max channel size.
|
||||||
|
addFunds := func(fundingCfg *Config) {
|
||||||
|
wc := fundingCfg.Wallet.WalletController
|
||||||
|
mockWc, ok := wc.(*mock.WalletController)
|
||||||
|
if ok {
|
||||||
|
mockWc.Utxos = test.coins
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alice, bob := setupFundingManagers(t, addFunds)
|
||||||
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
|
// We will consume the channel updates as we go, so no
|
||||||
|
// buffering is needed.
|
||||||
|
updateChan := make(chan *lnrpc.OpenStatusUpdate)
|
||||||
|
|
||||||
|
// Initiate a fund channel, and inspect the funding tx.
|
||||||
|
pushAmt := test.pushAmt
|
||||||
|
fundingTx := fundChannel(
|
||||||
|
t, alice, bob, 0, pushAmt, false,
|
||||||
|
test.fundUpToMaxAmt, test.minFundAmt, 1,
|
||||||
|
updateChan, true, nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check whether the expected change output is present.
|
||||||
|
if test.change {
|
||||||
|
require.EqualValues(t, 2, len(fundingTx.TxOut))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !test.change {
|
||||||
|
require.EqualValues(t, 1, len(fundingTx.TxOut))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inputs should be all funds in the wallet.
|
||||||
|
require.Equal(t, len(test.coins), len(fundingTx.TxIn))
|
||||||
|
|
||||||
|
for i, txIn := range fundingTx.TxIn {
|
||||||
|
require.Equal(
|
||||||
|
t, test.coins[i].OutPoint,
|
||||||
|
txIn.PreviousOutPoint,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestGetUpfrontShutdown tests different combinations of inputs for getting a
|
// TestGetUpfrontShutdown tests different combinations of inputs for getting a
|
||||||
// shutdown script. It varies whether the peer has the feature set, whether
|
// shutdown script. It varies whether the peer has the feature set, whether
|
||||||
// the user has provided a script and our local configuration to test that
|
// the user has provided a script and our local configuration to test that
|
||||||
@ -4212,8 +4366,8 @@ func TestFundingManagerZeroConf(t *testing.T) {
|
|||||||
|
|
||||||
// Call fundChannel with the zero-conf ChannelType.
|
// Call fundChannel with the zero-conf ChannelType.
|
||||||
fundingTx := fundChannel(
|
fundingTx := fundChannel(
|
||||||
t, alice, bob, fundingAmt, pushAmt, false, 1, updateChan, true,
|
t, alice, bob, fundingAmt, pushAmt, false, 0, 0, 1, updateChan,
|
||||||
&channelType,
|
true, &channelType,
|
||||||
)
|
)
|
||||||
fundingOp := &wire.OutPoint{
|
fundingOp := &wire.OutPoint{
|
||||||
Hash: fundingTx.TxHash(),
|
Hash: fundingTx.TxHash(),
|
||||||
|
@ -121,6 +121,20 @@ type InitFundingReserveMsg struct {
|
|||||||
// to this channel.
|
// to this channel.
|
||||||
RemoteFundingAmt btcutil.Amount
|
RemoteFundingAmt btcutil.Amount
|
||||||
|
|
||||||
|
// FundUpToMaxAmt defines if channel funding should try to add as many
|
||||||
|
// funds to the channel opening as possible up to this amount. If used,
|
||||||
|
// then MinFundAmt is treated as the minimum amount of funds that must
|
||||||
|
// be available to open the channel. If set to zero it is ignored.
|
||||||
|
FundUpToMaxAmt btcutil.Amount
|
||||||
|
|
||||||
|
// MinFundAmt denotes the minimum channel capacity that has to be
|
||||||
|
// allocated iff the FundUpToMaxAmt is set.
|
||||||
|
MinFundAmt btcutil.Amount
|
||||||
|
|
||||||
|
// RemoteChanReserve is the channel reserve we required for the remote
|
||||||
|
// peer.
|
||||||
|
RemoteChanReserve btcutil.Amount
|
||||||
|
|
||||||
// CommitFeePerKw is the starting accepted satoshis/Kw fee for the set
|
// CommitFeePerKw is the starting accepted satoshis/Kw fee for the set
|
||||||
// of initial commitment transactions. In order to ensure timely
|
// of initial commitment transactions. In order to ensure timely
|
||||||
// confirmation, it is recommended that this fee should be generous,
|
// confirmation, it is recommended that this fee should be generous,
|
||||||
@ -772,8 +786,12 @@ func (l *LightningWallet) CancelFundingIntent(pid [32]byte) error {
|
|||||||
// handleFundingReserveRequest processes a message intending to create, and
|
// handleFundingReserveRequest processes a message intending to create, and
|
||||||
// validate a funding reservation request.
|
// validate a funding reservation request.
|
||||||
func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg) {
|
func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg) {
|
||||||
|
|
||||||
|
noFundsCommitted := req.LocalFundingAmt == 0 &&
|
||||||
|
req.RemoteFundingAmt == 0 && req.FundUpToMaxAmt == 0
|
||||||
|
|
||||||
// It isn't possible to create a channel with zero funds committed.
|
// It isn't possible to create a channel with zero funds committed.
|
||||||
if req.LocalFundingAmt+req.RemoteFundingAmt == 0 {
|
if noFundsCommitted {
|
||||||
err := ErrZeroCapacity()
|
err := ErrZeroCapacity()
|
||||||
req.err <- err
|
req.err <- err
|
||||||
req.resp <- nil
|
req.resp <- nil
|
||||||
@ -841,8 +859,14 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg
|
|||||||
// the fee rate passed in to perform coin selection.
|
// the fee rate passed in to perform coin selection.
|
||||||
var err error
|
var err error
|
||||||
fundingReq := &chanfunding.Request{
|
fundingReq := &chanfunding.Request{
|
||||||
RemoteAmt: req.RemoteFundingAmt,
|
RemoteAmt: req.RemoteFundingAmt,
|
||||||
LocalAmt: req.LocalFundingAmt,
|
LocalAmt: req.LocalFundingAmt,
|
||||||
|
FundUpToMaxAmt: req.FundUpToMaxAmt,
|
||||||
|
MinFundAmt: req.MinFundAmt,
|
||||||
|
RemoteChanReserve: req.RemoteChanReserve,
|
||||||
|
PushAmt: lnwire.MilliSatoshi.ToSatoshis(
|
||||||
|
req.PushMSat,
|
||||||
|
),
|
||||||
MinConfs: req.MinConfs,
|
MinConfs: req.MinConfs,
|
||||||
SubtractFees: req.SubtractFees,
|
SubtractFees: req.SubtractFees,
|
||||||
FeeRate: req.FundingFeePerKw,
|
FeeRate: req.FundingFeePerKw,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user