From ea2a58e80f61ccfd28f2b834e022a7a410c1b247 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 6 Mar 2020 16:11:49 +0100 Subject: [PATCH] fundingmanager+lnwallet: enable anchor commitments If both nodes are signalling the feature, make all opened channels using this type. --- fundingmanager.go | 14 ++++++++++++++ lnwallet/reservation.go | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index bf4ed31b0..3e28f2a87 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -1111,6 +1111,20 @@ func (f *fundingManager) processFundingOpen(msg *lnwire.OpenChannel, func commitmentType(localFeatures, remoteFeatures *lnwire.FeatureVector) lnwallet.CommitmentType { + // If both peers are signalling support for anchor commitments, this + // implicitly mean we'll create the channel of this type. Note that + // this also enables tweakless commitments, as anchor commitments are + // always tweakless. + localAnchors := localFeatures.HasFeature( + lnwire.AnchorsOptional, + ) + remoteAnchors := remoteFeatures.HasFeature( + lnwire.AnchorsOptional, + ) + if localAnchors && remoteAnchors { + return lnwallet.CommitmentTypeAnchors + } + localTweakless := localFeatures.HasFeature( lnwire.StaticRemoteKeyOptional, ) diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index ba4c631ef..823aec4ae 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -27,6 +27,11 @@ const ( // CommitmentTypeTweakless is a newer commitment format where the // to_remote key is static. CommitmentTypeTweakless + + // CommitmentTypeAnchors is a commitment type that is tweakless, and + // has extra anchor ouputs in order to bump the fee of the commitment + // transaction. + CommitmentTypeAnchors ) // String returns the name of the CommitmentType. @@ -36,6 +41,8 @@ func (c CommitmentType) String() string { return "legacy" case CommitmentTypeTweakless: return "tweakless" + case CommitmentTypeAnchors: + return "anchors" default: return "invalid" } @@ -172,12 +179,25 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, initiator bool ) - commitFee := commitFeePerKw.FeeForWeight(input.CommitWeight) + // Based on the channel type, we determine the initial commit weight + // and fee. + commitWeight := int64(input.CommitWeight) + if commitType == CommitmentTypeAnchors { + commitWeight = input.AnchorCommitWeight + } + commitFee := commitFeePerKw.FeeForWeight(commitWeight) + localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt) // TODO(halseth): make method take remote funding amount directly // instead of inferring it from capacity and local amt. capacityMSat := lnwire.NewMSatFromSatoshis(capacity) + + // 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 == CommitmentTypeAnchors { + feeMSat += 2 * lnwire.NewMSatFromSatoshis(anchorSize) + } // If we're the responder to a single-funder reservation, then we have // no initial balance in the channel unless the remote party is pushing @@ -257,7 +277,11 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // 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 commitType == CommitmentTypeTweakless { + // Both the tweakless type and the anchor type is tweakless, + // hence set the bit. + if commitType == CommitmentTypeTweakless || + commitType == CommitmentTypeAnchors { + chanType |= channeldb.SingleFunderTweaklessBit } else { chanType |= channeldb.SingleFunderBit @@ -277,6 +301,11 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, chanType |= channeldb.DualFunderBit } + // We are adding anchor outputs to our commitment. + if commitType == CommitmentTypeAnchors { + chanType |= channeldb.AnchorOutputsBit + } + return &ChannelReservation{ ourContribution: &ChannelContribution{ FundingAmount: ourBalance.ToSatoshis(),