You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
3.5 KiB
152 lines
3.5 KiB
package chanacceptor |
|
|
|
import ( |
|
"bytes" |
|
"fmt" |
|
|
|
"github.com/btcsuite/btcutil" |
|
"github.com/lightningnetwork/lnd/lnwire" |
|
) |
|
|
|
const ( |
|
// We use field names in our errors for more readable errors. Create |
|
// consts for them here so that we can exactly match in our unit tests. |
|
fieldCSV = "csv delay" |
|
fieldHtlcLimit = "htlc limit" |
|
fieldMinDep = "min depth" |
|
fieldReserve = "reserve" |
|
fieldMinIn = "min htlc in" |
|
fieldInFlightTotal = "in flight total" |
|
fieldUpfrontShutdown = "upfront shutdown" |
|
) |
|
|
|
// fieldMismatchError returns a merge error for a named field when we get two |
|
// channel acceptor responses which have different values set. |
|
func fieldMismatchError(name string, current, new interface{}) error { |
|
return fmt.Errorf("multiple values set for: %v, %v and %v", |
|
name, current, new) |
|
} |
|
|
|
// mergeInt64 merges two int64 values, failing if they have different non-zero |
|
// values. |
|
func mergeInt64(name string, current, new int64) (int64, error) { |
|
switch { |
|
case current == 0: |
|
return new, nil |
|
|
|
case new == 0: |
|
return current, nil |
|
|
|
case current != new: |
|
return 0, fieldMismatchError(name, current, new) |
|
|
|
default: |
|
return new, nil |
|
} |
|
} |
|
|
|
// mergeMillisatoshi merges two msat values, failing if they have different |
|
// non-zero values. |
|
func mergeMillisatoshi(name string, current, |
|
new lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) { |
|
|
|
switch { |
|
case current == 0: |
|
return new, nil |
|
|
|
case new == 0: |
|
return current, nil |
|
|
|
case current != new: |
|
return 0, fieldMismatchError(name, current, new) |
|
|
|
default: |
|
return new, nil |
|
} |
|
} |
|
|
|
// mergeDeliveryAddress merges two delivery address values, failing if they have |
|
// different non-zero values. |
|
func mergeDeliveryAddress(name string, current, |
|
new lnwire.DeliveryAddress) (lnwire.DeliveryAddress, error) { |
|
|
|
switch { |
|
case current == nil: |
|
return new, nil |
|
|
|
case new == nil: |
|
return current, nil |
|
|
|
case !bytes.Equal(current, new): |
|
return nil, fieldMismatchError(name, current, new) |
|
|
|
default: |
|
return new, nil |
|
} |
|
} |
|
|
|
// mergeResponse takes two channel accept responses, and attempts to merge their |
|
// fields, failing if any fields conflict (are non-zero and not equal). It |
|
// returns a new response that has all the merged fields in it. |
|
func mergeResponse(current, new ChannelAcceptResponse) (ChannelAcceptResponse, |
|
error) { |
|
|
|
csv, err := mergeInt64( |
|
fieldCSV, int64(current.CSVDelay), int64(new.CSVDelay), |
|
) |
|
if err != nil { |
|
return current, err |
|
} |
|
current.CSVDelay = uint16(csv) |
|
|
|
htlcLimit, err := mergeInt64( |
|
fieldHtlcLimit, int64(current.HtlcLimit), |
|
int64(new.HtlcLimit), |
|
) |
|
if err != nil { |
|
return current, err |
|
} |
|
current.HtlcLimit = uint16(htlcLimit) |
|
|
|
minDepth, err := mergeInt64( |
|
fieldMinDep, int64(current.MinAcceptDepth), |
|
int64(new.MinAcceptDepth), |
|
) |
|
if err != nil { |
|
return current, err |
|
} |
|
current.MinAcceptDepth = uint16(minDepth) |
|
|
|
reserve, err := mergeInt64( |
|
fieldReserve, int64(current.Reserve), int64(new.Reserve), |
|
) |
|
if err != nil { |
|
return current, err |
|
} |
|
current.Reserve = btcutil.Amount(reserve) |
|
|
|
current.MinHtlcIn, err = mergeMillisatoshi( |
|
fieldMinIn, current.MinHtlcIn, new.MinHtlcIn, |
|
) |
|
if err != nil { |
|
return current, err |
|
} |
|
|
|
current.InFlightTotal, err = mergeMillisatoshi( |
|
fieldInFlightTotal, current.InFlightTotal, |
|
new.InFlightTotal, |
|
) |
|
if err != nil { |
|
return current, err |
|
} |
|
|
|
current.UpfrontShutdown, err = mergeDeliveryAddress( |
|
fieldUpfrontShutdown, current.UpfrontShutdown, |
|
new.UpfrontShutdown, |
|
) |
|
if err != nil { |
|
return current, err |
|
} |
|
|
|
return current, nil |
|
}
|
|
|