mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-06 17:47:01 +02:00
lnwallet: extend Reservation with alias chan-type, feature-bit flags
This extends the Reservation arguments to include whether a pending channel open has negotiated the zero-conf channel type, the scid-alias channel type, and/or the scid-alias feature bit. The result of those negotiates are stored in the OpenChannel's ChanType. The arguments to NewChannelReservation have also been simplified.
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chanfunding"
|
"github.com/lightningnetwork/lnd/lnwallet/chanfunding"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
@@ -208,11 +207,9 @@ type ChannelReservation struct {
|
|||||||
// creation of all channel reservations should be carried out via the
|
// creation of all channel reservations should be carried out via the
|
||||||
// lnwallet.InitChannelReservation interface.
|
// lnwallet.InitChannelReservation interface.
|
||||||
func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
||||||
commitFeePerKw chainfee.SatPerKWeight, wallet *LightningWallet,
|
wallet *LightningWallet, id uint64, chainHash *chainhash.Hash,
|
||||||
id uint64, pushMSat lnwire.MilliSatoshi, chainHash *chainhash.Hash,
|
thawHeight uint32, req *InitFundingReserveMsg) (*ChannelReservation,
|
||||||
flags lnwire.FundingFlag, commitType CommitmentType,
|
error) {
|
||||||
fundingAssembler chanfunding.Assembler,
|
|
||||||
pendingChanID [32]byte, thawHeight uint32) (*ChannelReservation, error) {
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ourBalance lnwire.MilliSatoshi
|
ourBalance lnwire.MilliSatoshi
|
||||||
@@ -223,10 +220,10 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
// Based on the channel type, we determine the initial commit weight
|
// Based on the channel type, we determine the initial commit weight
|
||||||
// and fee.
|
// and fee.
|
||||||
commitWeight := int64(input.CommitWeight)
|
commitWeight := int64(input.CommitWeight)
|
||||||
if commitType.HasAnchors() {
|
if req.CommitType.HasAnchors() {
|
||||||
commitWeight = int64(input.AnchorCommitWeight)
|
commitWeight = int64(input.AnchorCommitWeight)
|
||||||
}
|
}
|
||||||
commitFee := commitFeePerKw.FeeForWeight(commitWeight)
|
commitFee := req.CommitFeePerKw.FeeForWeight(commitWeight)
|
||||||
|
|
||||||
localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt)
|
localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt)
|
||||||
// TODO(halseth): make method take remote funding amount directly
|
// TODO(halseth): make method take remote funding amount directly
|
||||||
@@ -236,7 +233,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
// The total fee paid by the initiator will be the commitment fee in
|
// The total fee paid by the initiator will be the commitment fee in
|
||||||
// addition to the two anchor outputs.
|
// addition to the two anchor outputs.
|
||||||
feeMSat := lnwire.NewMSatFromSatoshis(commitFee)
|
feeMSat := lnwire.NewMSatFromSatoshis(commitFee)
|
||||||
if commitType.HasAnchors() {
|
if req.CommitType.HasAnchors() {
|
||||||
feeMSat += 2 * lnwire.NewMSatFromSatoshis(anchorSize)
|
feeMSat += 2 * lnwire.NewMSatFromSatoshis(anchorSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,8 +244,8 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
// no initial balance in the channel unless the remote party is pushing
|
// no initial balance in the channel unless the remote party is pushing
|
||||||
// some funds to us within the first commitment state.
|
// some funds to us within the first commitment state.
|
||||||
if localFundingAmt == 0 {
|
if localFundingAmt == 0 {
|
||||||
ourBalance = pushMSat
|
ourBalance = req.PushMSat
|
||||||
theirBalance = capacityMSat - feeMSat - pushMSat
|
theirBalance = capacityMSat - feeMSat - req.PushMSat
|
||||||
initiator = false
|
initiator = false
|
||||||
|
|
||||||
// If the responder doesn't have enough funds to actually pay
|
// If the responder doesn't have enough funds to actually pay
|
||||||
@@ -268,14 +265,14 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
// we pay all the initial fees within the commitment
|
// we pay all the initial fees within the commitment
|
||||||
// transaction. We also deduct our balance by the
|
// transaction. We also deduct our balance by the
|
||||||
// amount pushed as part of the initial state.
|
// amount pushed as part of the initial state.
|
||||||
ourBalance = capacityMSat - feeMSat - pushMSat
|
ourBalance = capacityMSat - feeMSat - req.PushMSat
|
||||||
theirBalance = pushMSat
|
theirBalance = req.PushMSat
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, this is a dual funder workflow where both
|
// Otherwise, this is a dual funder workflow where both
|
||||||
// slides split the amount funded and the commitment
|
// slides split the amount funded and the commitment
|
||||||
// fee.
|
// fee.
|
||||||
ourBalance = localFundingMSat - (feeMSat / 2)
|
ourBalance = localFundingMSat - (feeMSat / 2)
|
||||||
theirBalance = capacityMSat - localFundingMSat - (feeMSat / 2) + pushMSat
|
theirBalance = capacityMSat - localFundingMSat - (feeMSat / 2) + req.PushMSat
|
||||||
}
|
}
|
||||||
|
|
||||||
initiator = true
|
initiator = true
|
||||||
@@ -320,16 +317,16 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
// If either of the balances are zero at this point, or we have a
|
// If either of the balances are zero at this point, or we have a
|
||||||
// non-zero push amt (there's no pushing for dual funder), then this is
|
// non-zero push amt (there's no pushing for dual funder), then this is
|
||||||
// a single-funder channel.
|
// a single-funder channel.
|
||||||
if ourBalance == 0 || theirBalance == 0 || pushMSat != 0 {
|
if ourBalance == 0 || theirBalance == 0 || req.PushMSat != 0 {
|
||||||
// Both the tweakless type and the anchor type is tweakless,
|
// Both the tweakless type and the anchor type is tweakless,
|
||||||
// hence set the bit.
|
// hence set the bit.
|
||||||
if commitType.HasStaticRemoteKey() {
|
if req.CommitType.HasStaticRemoteKey() {
|
||||||
chanType |= channeldb.SingleFunderTweaklessBit
|
chanType |= channeldb.SingleFunderTweaklessBit
|
||||||
} else {
|
} else {
|
||||||
chanType |= channeldb.SingleFunderBit
|
chanType |= channeldb.SingleFunderBit
|
||||||
}
|
}
|
||||||
|
|
||||||
switch a := fundingAssembler.(type) {
|
switch a := req.ChanFunder.(type) {
|
||||||
// The first channels of a batch shouldn't publish the batch TX
|
// The first channels of a batch shouldn't publish the batch TX
|
||||||
// to avoid problems if some of the funding flows can't be
|
// to avoid problems if some of the funding flows can't be
|
||||||
// completed. Only the last channel of a batch should publish.
|
// completed. Only the last channel of a batch should publish.
|
||||||
@@ -358,14 +355,14 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
|
|
||||||
// We are adding anchor outputs to our commitment. We only support this
|
// We are adding anchor outputs to our commitment. We only support this
|
||||||
// in combination with zero-fee second-levels HTLCs.
|
// in combination with zero-fee second-levels HTLCs.
|
||||||
if commitType.HasAnchors() {
|
if req.CommitType.HasAnchors() {
|
||||||
chanType |= channeldb.AnchorOutputsBit
|
chanType |= channeldb.AnchorOutputsBit
|
||||||
chanType |= channeldb.ZeroHtlcTxFeeBit
|
chanType |= channeldb.ZeroHtlcTxFeeBit
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the appropriate LeaseExpiration/Frozen bit based on the
|
// Set the appropriate LeaseExpiration/Frozen bit based on the
|
||||||
// reservation parameters.
|
// reservation parameters.
|
||||||
if commitType == CommitmentTypeScriptEnforcedLease {
|
if req.CommitType == CommitmentTypeScriptEnforcedLease {
|
||||||
if thawHeight == 0 {
|
if thawHeight == 0 {
|
||||||
return nil, errors.New("missing absolute expiration " +
|
return nil, errors.New("missing absolute expiration " +
|
||||||
"for script enforced lease commitment type")
|
"for script enforced lease commitment type")
|
||||||
@@ -375,6 +372,18 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
chanType |= channeldb.FrozenBit
|
chanType |= channeldb.FrozenBit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if req.ZeroConf {
|
||||||
|
chanType |= channeldb.ZeroConfBit
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.OptionScidAlias {
|
||||||
|
chanType |= channeldb.ScidAliasChanBit
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.ScidAliasFeature {
|
||||||
|
chanType |= channeldb.ScidAliasFeatureBit
|
||||||
|
}
|
||||||
|
|
||||||
return &ChannelReservation{
|
return &ChannelReservation{
|
||||||
ourContribution: &ChannelContribution{
|
ourContribution: &ChannelContribution{
|
||||||
FundingAmount: ourBalance.ToSatoshis(),
|
FundingAmount: ourBalance.ToSatoshis(),
|
||||||
@@ -389,18 +398,18 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
ChainHash: *chainHash,
|
ChainHash: *chainHash,
|
||||||
IsPending: true,
|
IsPending: true,
|
||||||
IsInitiator: initiator,
|
IsInitiator: initiator,
|
||||||
ChannelFlags: flags,
|
ChannelFlags: req.Flags,
|
||||||
Capacity: capacity,
|
Capacity: capacity,
|
||||||
LocalCommitment: channeldb.ChannelCommitment{
|
LocalCommitment: channeldb.ChannelCommitment{
|
||||||
LocalBalance: ourBalance,
|
LocalBalance: ourBalance,
|
||||||
RemoteBalance: theirBalance,
|
RemoteBalance: theirBalance,
|
||||||
FeePerKw: btcutil.Amount(commitFeePerKw),
|
FeePerKw: btcutil.Amount(req.CommitFeePerKw),
|
||||||
CommitFee: commitFee,
|
CommitFee: commitFee,
|
||||||
},
|
},
|
||||||
RemoteCommitment: channeldb.ChannelCommitment{
|
RemoteCommitment: channeldb.ChannelCommitment{
|
||||||
LocalBalance: ourBalance,
|
LocalBalance: ourBalance,
|
||||||
RemoteBalance: theirBalance,
|
RemoteBalance: theirBalance,
|
||||||
FeePerKw: btcutil.Amount(commitFeePerKw),
|
FeePerKw: btcutil.Amount(req.CommitFeePerKw),
|
||||||
CommitFee: commitFee,
|
CommitFee: commitFee,
|
||||||
},
|
},
|
||||||
ThawHeight: thawHeight,
|
ThawHeight: thawHeight,
|
||||||
@@ -408,14 +417,22 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
InitialLocalBalance: ourBalance,
|
InitialLocalBalance: ourBalance,
|
||||||
InitialRemoteBalance: theirBalance,
|
InitialRemoteBalance: theirBalance,
|
||||||
},
|
},
|
||||||
pushMSat: pushMSat,
|
pushMSat: req.PushMSat,
|
||||||
pendingChanID: pendingChanID,
|
pendingChanID: req.PendingChanID,
|
||||||
reservationID: id,
|
reservationID: id,
|
||||||
wallet: wallet,
|
wallet: wallet,
|
||||||
chanFunder: fundingAssembler,
|
chanFunder: req.ChanFunder,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddAlias stores the first alias for zero-conf channels.
|
||||||
|
func (r *ChannelReservation) AddAlias(scid lnwire.ShortChannelID) {
|
||||||
|
r.Lock()
|
||||||
|
defer r.Unlock()
|
||||||
|
|
||||||
|
r.partialState.ShortChannelID = scid
|
||||||
|
}
|
||||||
|
|
||||||
// SetNumConfsRequired sets the number of confirmations that are required for
|
// SetNumConfsRequired sets the number of confirmations that are required for
|
||||||
// the ultimate funding transaction before the channel can be considered open.
|
// the ultimate funding transaction before the channel can be considered open.
|
||||||
// This is distinct from the main reservation workflow as it allows
|
// This is distinct from the main reservation workflow as it allows
|
||||||
@@ -428,6 +445,15 @@ func (r *ChannelReservation) SetNumConfsRequired(numConfs uint16) {
|
|||||||
r.partialState.NumConfsRequired = numConfs
|
r.partialState.NumConfsRequired = numConfs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsZeroConf returns if the reservation's underlying partial channel state is
|
||||||
|
// a zero-conf channel.
|
||||||
|
func (r *ChannelReservation) IsZeroConf() bool {
|
||||||
|
r.RLock()
|
||||||
|
defer r.RUnlock()
|
||||||
|
|
||||||
|
return r.partialState.IsZeroConf()
|
||||||
|
}
|
||||||
|
|
||||||
// CommitConstraints takes the constraints that the remote party specifies for
|
// CommitConstraints takes the constraints that the remote party specifies for
|
||||||
// the type of commitments that we can generate for them. These constraints
|
// the type of commitments that we can generate for them. These constraints
|
||||||
// include several parameters that serve as flow control restricting the amount
|
// include several parameters that serve as flow control restricting the amount
|
||||||
|
@@ -728,11 +728,17 @@ func testCancelNonExistentReservation(miner *rpctest.Harness,
|
|||||||
feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1)
|
feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1)
|
||||||
require.NoError(t, err, "unable to query fee estimator")
|
require.NoError(t, err, "unable to query fee estimator")
|
||||||
|
|
||||||
|
req := &lnwallet.InitFundingReserveMsg{
|
||||||
|
CommitFeePerKw: feePerKw,
|
||||||
|
PushMSat: 10,
|
||||||
|
Flags: lnwire.FFAnnounceChannel,
|
||||||
|
CommitType: lnwallet.CommitmentTypeTweakless,
|
||||||
|
PendingChanID: [32]byte{},
|
||||||
|
}
|
||||||
|
|
||||||
// Create our own reservation, give it some ID.
|
// Create our own reservation, give it some ID.
|
||||||
res, err := lnwallet.NewChannelReservation(
|
res, err := lnwallet.NewChannelReservation(
|
||||||
10000, 10000, feePerKw, alice, 22, 10, &testHdSeed,
|
10000, 10000, alice, 22, &testHdSeed, 0, req,
|
||||||
lnwire.FFAnnounceChannel, lnwallet.CommitmentTypeTweakless,
|
|
||||||
nil, [32]byte{}, 0,
|
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to create res")
|
require.NoError(t, err, "unable to create res")
|
||||||
|
|
||||||
|
@@ -153,6 +153,18 @@ type InitFundingReserveMsg struct {
|
|||||||
// used.
|
// used.
|
||||||
ChanFunder chanfunding.Assembler
|
ChanFunder chanfunding.Assembler
|
||||||
|
|
||||||
|
// ZeroConf is a boolean that is true if a zero-conf channel was
|
||||||
|
// negotiated.
|
||||||
|
ZeroConf bool
|
||||||
|
|
||||||
|
// OptionScidAlias is a boolean that is true if an option-scid-alias
|
||||||
|
// channel type was explicitly negotiated.
|
||||||
|
OptionScidAlias bool
|
||||||
|
|
||||||
|
// ScidAliasFeature is true if the option-scid-alias feature bit was
|
||||||
|
// negotiated.
|
||||||
|
ScidAliasFeature bool
|
||||||
|
|
||||||
// err is a channel in which all errors will be sent across. Will be
|
// err is a channel in which all errors will be sent across. Will be
|
||||||
// nil if this initial set is successful.
|
// nil if this initial set is successful.
|
||||||
//
|
//
|
||||||
@@ -845,10 +857,8 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg
|
|||||||
|
|
||||||
id := atomic.AddUint64(&l.nextFundingID, 1)
|
id := atomic.AddUint64(&l.nextFundingID, 1)
|
||||||
reservation, err := NewChannelReservation(
|
reservation, err := NewChannelReservation(
|
||||||
capacity, localFundingAmt, req.CommitFeePerKw, l, id,
|
capacity, localFundingAmt, l, id, l.Cfg.NetParams.GenesisHash,
|
||||||
req.PushMSat, l.Cfg.NetParams.GenesisHash, req.Flags,
|
thawHeight, req,
|
||||||
req.CommitType, req.ChanFunder, req.PendingChanID,
|
|
||||||
thawHeight,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fundingIntent.Cancel()
|
fundingIntent.Cancel()
|
||||||
|
Reference in New Issue
Block a user