mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-11-15 08:36:38 +01:00
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:
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user