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:
eugene
2022-04-04 16:15:02 -04:00
parent c9f5912601
commit 21c83b0744
3 changed files with 74 additions and 32 deletions

View File

@@ -12,7 +12,6 @@ import (
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwallet/chanfunding"
"github.com/lightningnetwork/lnd/lnwire"
)
@@ -208,11 +207,9 @@ type ChannelReservation struct {
// creation of all channel reservations should be carried out via the
// lnwallet.InitChannelReservation interface.
func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
commitFeePerKw chainfee.SatPerKWeight, wallet *LightningWallet,
id uint64, pushMSat lnwire.MilliSatoshi, chainHash *chainhash.Hash,
flags lnwire.FundingFlag, commitType CommitmentType,
fundingAssembler chanfunding.Assembler,
pendingChanID [32]byte, thawHeight uint32) (*ChannelReservation, error) {
wallet *LightningWallet, id uint64, chainHash *chainhash.Hash,
thawHeight uint32, req *InitFundingReserveMsg) (*ChannelReservation,
error) {
var (
ourBalance lnwire.MilliSatoshi
@@ -223,10 +220,10 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
// Based on the channel type, we determine the initial commit weight
// and fee.
commitWeight := int64(input.CommitWeight)
if commitType.HasAnchors() {
if req.CommitType.HasAnchors() {
commitWeight = int64(input.AnchorCommitWeight)
}
commitFee := commitFeePerKw.FeeForWeight(commitWeight)
commitFee := req.CommitFeePerKw.FeeForWeight(commitWeight)
localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt)
// 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
// addition to the two anchor outputs.
feeMSat := lnwire.NewMSatFromSatoshis(commitFee)
if commitType.HasAnchors() {
if req.CommitType.HasAnchors() {
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
// some funds to us within the first commitment state.
if localFundingAmt == 0 {
ourBalance = pushMSat
theirBalance = capacityMSat - feeMSat - pushMSat
ourBalance = req.PushMSat
theirBalance = capacityMSat - feeMSat - req.PushMSat
initiator = false
// 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
// transaction. We also deduct our balance by the
// amount pushed as part of the initial state.
ourBalance = capacityMSat - feeMSat - pushMSat
theirBalance = pushMSat
ourBalance = capacityMSat - feeMSat - req.PushMSat
theirBalance = req.PushMSat
} else {
// Otherwise, this is a dual funder workflow where both
// slides split the amount funded and the commitment
// fee.
ourBalance = localFundingMSat - (feeMSat / 2)
theirBalance = capacityMSat - localFundingMSat - (feeMSat / 2) + pushMSat
theirBalance = capacityMSat - localFundingMSat - (feeMSat / 2) + req.PushMSat
}
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
// non-zero push amt (there's no pushing for dual funder), then this is
// 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,
// hence set the bit.
if commitType.HasStaticRemoteKey() {
if req.CommitType.HasStaticRemoteKey() {
chanType |= channeldb.SingleFunderTweaklessBit
} else {
chanType |= channeldb.SingleFunderBit
}
switch a := fundingAssembler.(type) {
switch a := req.ChanFunder.(type) {
// The first channels of a batch shouldn't publish the batch TX
// to avoid problems if some of the funding flows can't be
// 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
// in combination with zero-fee second-levels HTLCs.
if commitType.HasAnchors() {
if req.CommitType.HasAnchors() {
chanType |= channeldb.AnchorOutputsBit
chanType |= channeldb.ZeroHtlcTxFeeBit
}
// Set the appropriate LeaseExpiration/Frozen bit based on the
// reservation parameters.
if commitType == CommitmentTypeScriptEnforcedLease {
if req.CommitType == CommitmentTypeScriptEnforcedLease {
if thawHeight == 0 {
return nil, errors.New("missing absolute expiration " +
"for script enforced lease commitment type")
@@ -375,6 +372,18 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
chanType |= channeldb.FrozenBit
}
if req.ZeroConf {
chanType |= channeldb.ZeroConfBit
}
if req.OptionScidAlias {
chanType |= channeldb.ScidAliasChanBit
}
if req.ScidAliasFeature {
chanType |= channeldb.ScidAliasFeatureBit
}
return &ChannelReservation{
ourContribution: &ChannelContribution{
FundingAmount: ourBalance.ToSatoshis(),
@@ -389,18 +398,18 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
ChainHash: *chainHash,
IsPending: true,
IsInitiator: initiator,
ChannelFlags: flags,
ChannelFlags: req.Flags,
Capacity: capacity,
LocalCommitment: channeldb.ChannelCommitment{
LocalBalance: ourBalance,
RemoteBalance: theirBalance,
FeePerKw: btcutil.Amount(commitFeePerKw),
FeePerKw: btcutil.Amount(req.CommitFeePerKw),
CommitFee: commitFee,
},
RemoteCommitment: channeldb.ChannelCommitment{
LocalBalance: ourBalance,
RemoteBalance: theirBalance,
FeePerKw: btcutil.Amount(commitFeePerKw),
FeePerKw: btcutil.Amount(req.CommitFeePerKw),
CommitFee: commitFee,
},
ThawHeight: thawHeight,
@@ -408,14 +417,22 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
InitialLocalBalance: ourBalance,
InitialRemoteBalance: theirBalance,
},
pushMSat: pushMSat,
pendingChanID: pendingChanID,
pushMSat: req.PushMSat,
pendingChanID: req.PendingChanID,
reservationID: id,
wallet: wallet,
chanFunder: fundingAssembler,
chanFunder: req.ChanFunder,
}, 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
// the ultimate funding transaction before the channel can be considered open.
// 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
}
// 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
// the type of commitments that we can generate for them. These constraints
// include several parameters that serve as flow control restricting the amount

View File

@@ -728,11 +728,17 @@ func testCancelNonExistentReservation(miner *rpctest.Harness,
feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1)
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.
res, err := lnwallet.NewChannelReservation(
10000, 10000, feePerKw, alice, 22, 10, &testHdSeed,
lnwire.FFAnnounceChannel, lnwallet.CommitmentTypeTweakless,
nil, [32]byte{}, 0,
10000, 10000, alice, 22, &testHdSeed, 0, req,
)
require.NoError(t, err, "unable to create res")

View File

@@ -153,6 +153,18 @@ type InitFundingReserveMsg struct {
// used.
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
// nil if this initial set is successful.
//
@@ -845,10 +857,8 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg
id := atomic.AddUint64(&l.nextFundingID, 1)
reservation, err := NewChannelReservation(
capacity, localFundingAmt, req.CommitFeePerKw, l, id,
req.PushMSat, l.Cfg.NetParams.GenesisHash, req.Flags,
req.CommitType, req.ChanFunder, req.PendingChanID,
thawHeight,
capacity, localFundingAmt, l, id, l.Cfg.NetParams.GenesisHash,
thawHeight, req,
)
if err != nil {
fundingIntent.Cancel()