multi: break ChannelConstraints into two sub-structures

This commit breaks the ChannelConstraints structure into two
sub-structures that reflect the fundamental differences in how
these parameters are used. On its face it may not seem necessary,
however the distinction introduced here is relevant for how we
will be implementing the Dynamic Commitments proposal.
This commit is contained in:
Keagan McClelland
2024-05-09 14:32:45 -07:00
parent b21521ff14
commit e3a9d0acbe
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,
)
}