123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package netann
- import (
- "bytes"
- "fmt"
- "time"
- "github.com/btcsuite/btcd/btcec/v2"
- "github.com/lightningnetwork/lnd/channeldb/models"
- "github.com/lightningnetwork/lnd/keychain"
- "github.com/lightningnetwork/lnd/lnwallet"
- "github.com/lightningnetwork/lnd/lnwire"
- )
- // ErrUnableToExtractChanUpdate is returned when a channel update cannot be
- // found for one of our active channels.
- var ErrUnableToExtractChanUpdate = fmt.Errorf("unable to extract ChannelUpdate")
- // ChannelUpdateModifier is a closure that makes in-place modifications to an
- // lnwire.ChannelUpdate.
- type ChannelUpdateModifier func(*lnwire.ChannelUpdate)
- // ChanUpdSetDisable is a functional option that sets the disabled channel flag
- // if disabled is true, and clears the bit otherwise.
- func ChanUpdSetDisable(disabled bool) ChannelUpdateModifier {
- return func(update *lnwire.ChannelUpdate) {
- if disabled {
- // Set the bit responsible for marking a channel as
- // disabled.
- update.ChannelFlags |= lnwire.ChanUpdateDisabled
- } else {
- // Clear the bit responsible for marking a channel as
- // disabled.
- update.ChannelFlags &= ^lnwire.ChanUpdateDisabled
- }
- }
- }
- // ChanUpdSetTimestamp is a functional option that sets the timestamp of the
- // update to the current time, or increments it if the timestamp is already in
- // the future.
- func ChanUpdSetTimestamp(update *lnwire.ChannelUpdate) {
- newTimestamp := uint32(time.Now().Unix())
- if newTimestamp <= update.Timestamp {
- // Increment the prior value to ensure the timestamp
- // monotonically increases, otherwise the update won't
- // propagate.
- newTimestamp = update.Timestamp + 1
- }
- update.Timestamp = newTimestamp
- }
- // SignChannelUpdate applies the given modifiers to the passed
- // lnwire.ChannelUpdate, then signs the resulting update. The provided update
- // should be the most recent, valid update, otherwise the timestamp may not
- // monotonically increase from the prior.
- //
- // NOTE: This method modifies the given update.
- func SignChannelUpdate(signer lnwallet.MessageSigner, keyLoc keychain.KeyLocator,
- update *lnwire.ChannelUpdate, mods ...ChannelUpdateModifier) error {
- // Apply the requested changes to the channel update.
- for _, modifier := range mods {
- modifier(update)
- }
- // Create the DER-encoded ECDSA signature over the message digest.
- sig, err := SignAnnouncement(signer, keyLoc, update)
- if err != nil {
- return err
- }
- // Parse the DER-encoded signature into a fixed-size 64-byte array.
- update.Signature, err = lnwire.NewSigFromSignature(sig)
- if err != nil {
- return err
- }
- return nil
- }
- // ExtractChannelUpdate attempts to retrieve a lnwire.ChannelUpdate message from
- // an edge's info and a set of routing policies.
- //
- // NOTE: The passed policies can be nil.
- func ExtractChannelUpdate(ownerPubKey []byte,
- info *models.ChannelEdgeInfo,
- policies ...*models.ChannelEdgePolicy) (
- *lnwire.ChannelUpdate, error) {
- // Helper function to extract the owner of the given policy.
- owner := func(edge *models.ChannelEdgePolicy) []byte {
- var pubKey *btcec.PublicKey
- if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 {
- pubKey, _ = info.NodeKey1()
- } else {
- pubKey, _ = info.NodeKey2()
- }
- // If pubKey was not found, just return nil.
- if pubKey == nil {
- return nil
- }
- return pubKey.SerializeCompressed()
- }
- // Extract the channel update from the policy we own, if any.
- for _, edge := range policies {
- if edge != nil && bytes.Equal(ownerPubKey, owner(edge)) {
- return ChannelUpdateFromEdge(info, edge)
- }
- }
- return nil, ErrUnableToExtractChanUpdate
- }
- // UnsignedChannelUpdateFromEdge reconstructs an unsigned ChannelUpdate from the
- // given edge info and policy.
- func UnsignedChannelUpdateFromEdge(info *models.ChannelEdgeInfo,
- policy *models.ChannelEdgePolicy) *lnwire.ChannelUpdate {
- return &lnwire.ChannelUpdate{
- ChainHash: info.ChainHash,
- ShortChannelID: lnwire.NewShortChanIDFromInt(policy.ChannelID),
- Timestamp: uint32(policy.LastUpdate.Unix()),
- ChannelFlags: policy.ChannelFlags,
- MessageFlags: policy.MessageFlags,
- TimeLockDelta: policy.TimeLockDelta,
- HtlcMinimumMsat: policy.MinHTLC,
- HtlcMaximumMsat: policy.MaxHTLC,
- BaseFee: uint32(policy.FeeBaseMSat),
- FeeRate: uint32(policy.FeeProportionalMillionths),
- ExtraOpaqueData: policy.ExtraOpaqueData,
- }
- }
- // ChannelUpdateFromEdge reconstructs a signed ChannelUpdate from the given edge
- // info and policy.
- func ChannelUpdateFromEdge(info *models.ChannelEdgeInfo,
- policy *models.ChannelEdgePolicy) (*lnwire.ChannelUpdate, error) {
- update := UnsignedChannelUpdateFromEdge(info, policy)
- var err error
- update.Signature, err = lnwire.NewSigFromECDSARawSignature(
- policy.SigBytes,
- )
- if err != nil {
- return nil, err
- }
- return update, nil
- }
|