Merge pull request #8953 from ProofOfKeags/refactor/lnwallet-channel-channel-constraints-partition

[MICRO]: multi: break ChannelConstraints into two sub-structures
This commit is contained in:
Oliver Gugger
2024-08-05 02:08:52 -06:00
committed by GitHub
15 changed files with 338 additions and 242 deletions

View File

@@ -501,29 +501,34 @@ func (r *ChannelReservation) IsTaproot() bool {
// of satoshis that can be transferred in a single commitment. This function
// will also attempt to verify the constraints for sanity, returning an error
// if the parameters are seemed unsound.
func (r *ChannelReservation) CommitConstraints(c *channeldb.ChannelConstraints,
maxLocalCSVDelay uint16, responder bool) error {
func (r *ChannelReservation) CommitConstraints(
bounds *channeldb.ChannelStateBounds,
commitParams *channeldb.CommitmentParams,
maxLocalCSVDelay uint16,
responder bool) error {
r.Lock()
defer r.Unlock()
// First, verify the sanity of the channel constraints.
err := VerifyConstraints(c, maxLocalCSVDelay, r.partialState.Capacity)
err := VerifyConstraints(
bounds, commitParams, maxLocalCSVDelay, r.partialState.Capacity,
)
if err != nil {
return err
}
// Our dust limit should always be less than or equal to our proposed
// channel reserve.
if responder && r.ourContribution.DustLimit > c.ChanReserve {
r.ourContribution.DustLimit = c.ChanReserve
if responder && r.ourContribution.DustLimit > bounds.ChanReserve {
r.ourContribution.DustLimit = bounds.ChanReserve
}
r.ourContribution.ChanReserve = c.ChanReserve
r.ourContribution.MaxPendingAmount = c.MaxPendingAmount
r.ourContribution.MinHTLC = c.MinHTLC
r.ourContribution.MaxAcceptedHtlcs = c.MaxAcceptedHtlcs
r.ourContribution.CsvDelay = c.CsvDelay
r.ourContribution.ChanReserve = bounds.ChanReserve
r.ourContribution.MaxPendingAmount = bounds.MaxPendingAmount
r.ourContribution.MinHTLC = bounds.MinHTLC
r.ourContribution.MaxAcceptedHtlcs = bounds.MaxAcceptedHtlcs
r.ourContribution.CsvDelay = commitParams.CsvDelay
return nil
}
@@ -805,62 +810,75 @@ func (r *ChannelReservation) Cancel() error {
// VerifyConstraints is a helper function that can be used to check the sanity
// of various channel constraints.
func VerifyConstraints(c *channeldb.ChannelConstraints,
maxLocalCSVDelay uint16, channelCapacity btcutil.Amount) error {
func VerifyConstraints(bounds *channeldb.ChannelStateBounds,
commitParams *channeldb.CommitmentParams, maxLocalCSVDelay uint16,
channelCapacity btcutil.Amount) error {
// Fail if the csv delay for our funds exceeds our maximum.
if c.CsvDelay > maxLocalCSVDelay {
return ErrCsvDelayTooLarge(c.CsvDelay, maxLocalCSVDelay)
if commitParams.CsvDelay > maxLocalCSVDelay {
return ErrCsvDelayTooLarge(
commitParams.CsvDelay, maxLocalCSVDelay,
)
}
// The channel reserve should always be greater or equal to the dust
// limit. The reservation request should be denied if otherwise.
if c.DustLimit > c.ChanReserve {
return ErrChanReserveTooSmall(c.ChanReserve, c.DustLimit)
if commitParams.DustLimit > bounds.ChanReserve {
return ErrChanReserveTooSmall(
bounds.ChanReserve, commitParams.DustLimit,
)
}
// Validate against the maximum-sized witness script dust limit, and
// also ensure that the DustLimit is not too large.
maxWitnessLimit := DustLimitForSize(input.UnknownWitnessSize)
if c.DustLimit < maxWitnessLimit || c.DustLimit > 3*maxWitnessLimit {
return ErrInvalidDustLimit(c.DustLimit)
if commitParams.DustLimit < maxWitnessLimit ||
commitParams.DustLimit > 3*maxWitnessLimit {
return ErrInvalidDustLimit(commitParams.DustLimit)
}
// Fail if we consider the channel reserve to be too large. We
// currently fail if it is greater than 20% of the channel capacity.
maxChanReserve := channelCapacity / 5
if c.ChanReserve > maxChanReserve {
return ErrChanReserveTooLarge(c.ChanReserve, maxChanReserve)
if bounds.ChanReserve > maxChanReserve {
return ErrChanReserveTooLarge(
bounds.ChanReserve, maxChanReserve,
)
}
// Fail if the minimum HTLC value is too large. If this is too large,
// the channel won't be useful for sending small payments. This limit
// is currently set to maxValueInFlight, effectively letting the remote
// setting this as large as it wants.
if c.MinHTLC > c.MaxPendingAmount {
return ErrMinHtlcTooLarge(c.MinHTLC, c.MaxPendingAmount)
if bounds.MinHTLC > bounds.MaxPendingAmount {
return ErrMinHtlcTooLarge(
bounds.MinHTLC, bounds.MaxPendingAmount,
)
}
// Fail if maxHtlcs is above the maximum allowed number of 483. This
// number is specified in BOLT-02.
if c.MaxAcceptedHtlcs > uint16(input.MaxHTLCNumber/2) {
if bounds.MaxAcceptedHtlcs > uint16(input.MaxHTLCNumber/2) {
return ErrMaxHtlcNumTooLarge(
c.MaxAcceptedHtlcs, uint16(input.MaxHTLCNumber/2),
bounds.MaxAcceptedHtlcs, uint16(input.MaxHTLCNumber/2),
)
}
// Fail if we consider maxHtlcs too small. If this is too small we
// cannot offer many HTLCs to the remote.
const minNumHtlc = 5
if c.MaxAcceptedHtlcs < minNumHtlc {
return ErrMaxHtlcNumTooSmall(c.MaxAcceptedHtlcs, minNumHtlc)
if bounds.MaxAcceptedHtlcs < minNumHtlc {
return ErrMaxHtlcNumTooSmall(
bounds.MaxAcceptedHtlcs, minNumHtlc,
)
}
// Fail if we consider maxValueInFlight too small. We currently require
// the remote to at least allow minNumHtlc * minHtlc in flight.
if c.MaxPendingAmount < minNumHtlc*c.MinHTLC {
if bounds.MaxPendingAmount < minNumHtlc*bounds.MinHTLC {
return ErrMaxValueInFlightTooSmall(
c.MaxPendingAmount, minNumHtlc*c.MinHTLC,
bounds.MaxPendingAmount, minNumHtlc*bounds.MinHTLC,
)
}

View File

@@ -422,16 +422,18 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
aliceChanReservation, err := alice.InitChannelReservation(aliceReq)
require.NoError(t, err, "unable to initialize funding reservation")
aliceChanReservation.SetNumConfsRequired(numReqConfs)
channelConstraints := &channeldb.ChannelConstraints{
DustLimit: lnwallet.DustLimitUnknownWitness(),
bounds := &channeldb.ChannelStateBounds{
ChanReserve: fundingAmount / 100,
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmount),
MinHTLC: 1,
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
CsvDelay: csvDelay,
}
commitParams := &channeldb.CommitmentParams{
DustLimit: lnwallet.DustLimitUnknownWitness(),
CsvDelay: csvDelay,
}
err = aliceChanReservation.CommitConstraints(
channelConstraints, defaultMaxLocalCsvDelay, false,
bounds, commitParams, defaultMaxLocalCsvDelay, false,
)
require.NoError(t, err, "unable to verify constraints")
@@ -463,7 +465,7 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
bobChanReservation, err := bob.InitChannelReservation(bobReq)
require.NoError(t, err, "bob unable to init channel reservation")
err = bobChanReservation.CommitConstraints(
channelConstraints, defaultMaxLocalCsvDelay, true,
bounds, commitParams, defaultMaxLocalCsvDelay, true,
)
require.NoError(t, err, "unable to verify constraints")
bobChanReservation.SetNumConfsRequired(numReqConfs)
@@ -827,16 +829,18 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
aliceChanReservation, err := alice.InitChannelReservation(aliceReq)
require.NoError(t, err, "unable to init channel reservation")
aliceChanReservation.SetNumConfsRequired(numReqConfs)
channelConstraints := &channeldb.ChannelConstraints{
DustLimit: lnwallet.DustLimitUnknownWitness(),
bounds := &channeldb.ChannelStateBounds{
ChanReserve: fundingAmt / 100,
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmt),
MinHTLC: 1,
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
CsvDelay: csvDelay,
}
commitParams := &channeldb.CommitmentParams{
DustLimit: lnwallet.DustLimitUnknownWitness(),
CsvDelay: csvDelay,
}
err = aliceChanReservation.CommitConstraints(
channelConstraints, defaultMaxLocalCsvDelay, false,
bounds, commitParams, defaultMaxLocalCsvDelay, false,
)
require.NoError(t, err, "unable to verify constraints")
@@ -875,7 +879,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
bobChanReservation, err := bob.InitChannelReservation(bobReq)
require.NoError(t, err, "unable to create bob reservation")
err = bobChanReservation.CommitConstraints(
channelConstraints, defaultMaxLocalCsvDelay, true,
bounds, commitParams, defaultMaxLocalCsvDelay, true,
)
require.NoError(t, err, "unable to verify constraints")
bobChanReservation.SetNumConfsRequired(numReqConfs)

View File

@@ -150,13 +150,15 @@ func CreateTestChannels(t *testing.T, chanType channeldb.ChannelType,
}
aliceCfg := channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
DustLimit: aliceDustLimit,
ChannelStateBounds: channeldb.ChannelStateBounds{
MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
ChanReserve: channelCapacity / 100,
MinHTLC: 0,
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
CsvDelay: uint16(csvTimeoutAlice),
},
CommitmentParams: channeldb.CommitmentParams{
DustLimit: aliceDustLimit,
CsvDelay: uint16(csvTimeoutAlice),
},
MultiSigKey: keychain.KeyDescriptor{
PubKey: aliceKeys[0].PubKey(),
@@ -175,13 +177,15 @@ func CreateTestChannels(t *testing.T, chanType channeldb.ChannelType,
},
}
bobCfg := channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
DustLimit: bobDustLimit,
ChannelStateBounds: channeldb.ChannelStateBounds{
MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
ChanReserve: channelCapacity / 100,
MinHTLC: 0,
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
CsvDelay: uint16(csvTimeoutBob),
},
CommitmentParams: channeldb.CommitmentParams{
DustLimit: bobDustLimit,
CsvDelay: uint16(csvTimeoutBob),
},
MultiSigKey: keychain.KeyDescriptor{
PubKey: bobKeys[0].PubKey(),

View File

@@ -603,14 +603,14 @@ func testSpendValidation(t *testing.T, tweakless bool) {
dustLimit := DustLimitForSize(input.UnknownWitnessSize)
aliceChanCfg := &channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
CommitmentParams: channeldb.CommitmentParams{
DustLimit: dustLimit,
CsvDelay: csvTimeout,
},
}
bobChanCfg := &channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
CommitmentParams: channeldb.CommitmentParams{
DustLimit: dustLimit,
CsvDelay: csvTimeout,
},
@@ -834,15 +834,17 @@ func createTestChannelsForVectors(tc *testContext, chanType channeldb.ChannelTyp
// Define channel configurations.
remoteCfg := channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
DustLimit: tc.dustLimit,
ChannelStateBounds: channeldb.ChannelStateBounds{
MaxPendingAmount: lnwire.NewMSatFromSatoshis(
tc.fundingAmount,
),
ChanReserve: 0,
MinHTLC: 0,
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
CsvDelay: tc.localCsvDelay,
},
CommitmentParams: channeldb.CommitmentParams{
DustLimit: tc.dustLimit,
CsvDelay: tc.localCsvDelay,
},
MultiSigKey: keychain.KeyDescriptor{
PubKey: tc.remoteFundingPrivkey.PubKey(),
@@ -861,15 +863,17 @@ func createTestChannelsForVectors(tc *testContext, chanType channeldb.ChannelTyp
},
}
localCfg := channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
DustLimit: tc.dustLimit,
ChannelStateBounds: channeldb.ChannelStateBounds{
MaxPendingAmount: lnwire.NewMSatFromSatoshis(
tc.fundingAmount,
),
ChanReserve: 0,
MinHTLC: 0,
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
CsvDelay: tc.localCsvDelay,
},
CommitmentParams: channeldb.CommitmentParams{
DustLimit: tc.dustLimit,
CsvDelay: tc.localCsvDelay,
},
MultiSigKey: keychain.KeyDescriptor{
PubKey: tc.localFundingPrivkey.PubKey(),

View File

@@ -1379,7 +1379,7 @@ func (l *LightningWallet) initOurContribution(reservation *ChannelReservation,
)
reservation.partialState.RevocationProducer = producer
reservation.ourContribution.ChannelConstraints.DustLimit =
reservation.ourContribution.CommitmentParams.DustLimit =
DustLimitUnknownWitness()
// If taproot channels are active, then we'll generate our verification