github.com/decred/dcrlnd@v0.7.6/netann/channel_update.go (about) 1 package netann 2 3 import ( 4 "bytes" 5 "fmt" 6 "time" 7 8 "github.com/decred/dcrd/dcrec/secp256k1/v4" 9 "github.com/decred/dcrlnd/channeldb" 10 "github.com/decred/dcrlnd/keychain" 11 "github.com/decred/dcrlnd/lnwallet" 12 "github.com/decred/dcrlnd/lnwire" 13 ) 14 15 // ErrUnableToExtractChanUpdate is returned when a channel update cannot be 16 // found for one of our active channels. 17 var ErrUnableToExtractChanUpdate = fmt.Errorf("unable to extract ChannelUpdate") 18 19 // ChannelUpdateModifier is a closure that makes in-place modifications to an 20 // lnwire.ChannelUpdate. 21 type ChannelUpdateModifier func(*lnwire.ChannelUpdate) 22 23 // ChanUpdSetDisable is a functional option that sets the disabled channel flag 24 // if disabled is true, and clears the bit otherwise. 25 func ChanUpdSetDisable(disabled bool) ChannelUpdateModifier { 26 return func(update *lnwire.ChannelUpdate) { 27 if disabled { 28 // Set the bit responsible for marking a channel as 29 // disabled. 30 update.ChannelFlags |= lnwire.ChanUpdateDisabled 31 } else { 32 // Clear the bit responsible for marking a channel as 33 // disabled. 34 update.ChannelFlags &= ^lnwire.ChanUpdateDisabled 35 } 36 } 37 } 38 39 // ChanUpdSetTimestamp is a functional option that sets the timestamp of the 40 // update to the current time, or increments it if the timestamp is already in 41 // the future. 42 func ChanUpdSetTimestamp(update *lnwire.ChannelUpdate) { 43 newTimestamp := uint32(time.Now().Unix()) 44 if newTimestamp <= update.Timestamp { 45 // Increment the prior value to ensure the timestamp 46 // monotonically increases, otherwise the update won't 47 // propagate. 48 newTimestamp = update.Timestamp + 1 49 } 50 update.Timestamp = newTimestamp 51 } 52 53 // SignChannelUpdate applies the given modifiers to the passed 54 // lnwire.ChannelUpdate, then signs the resulting update. The provided update 55 // should be the most recent, valid update, otherwise the timestamp may not 56 // monotonically increase from the prior. 57 // 58 // NOTE: This method modifies the given update. 59 func SignChannelUpdate(signer lnwallet.MessageSigner, keyLoc keychain.KeyLocator, 60 update *lnwire.ChannelUpdate, mods ...ChannelUpdateModifier) error { 61 62 // Apply the requested changes to the channel update. 63 for _, modifier := range mods { 64 modifier(update) 65 } 66 67 // Create the DER-encoded ECDSA signature over the message digest. 68 sig, err := SignAnnouncement(signer, keyLoc, update) 69 if err != nil { 70 return err 71 } 72 73 // Parse the DER-encoded signature into a fixed-size 64-byte array. 74 update.Signature, err = lnwire.NewSigFromSignature(sig) 75 if err != nil { 76 return err 77 } 78 79 return nil 80 } 81 82 // ExtractChannelUpdate attempts to retrieve a lnwire.ChannelUpdate message from 83 // an edge's info and a set of routing policies. 84 // 85 // NOTE: The passed policies can be nil. 86 func ExtractChannelUpdate(ownerPubKey []byte, 87 info *channeldb.ChannelEdgeInfo, 88 policies ...*channeldb.ChannelEdgePolicy) ( 89 *lnwire.ChannelUpdate, error) { 90 91 // Helper function to extract the owner of the given policy. 92 owner := func(edge *channeldb.ChannelEdgePolicy) []byte { 93 var pubKey *secp256k1.PublicKey 94 if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 { 95 pubKey, _ = info.NodeKey1() 96 } else { 97 pubKey, _ = info.NodeKey2() 98 } 99 100 // If pubKey was not found, just return nil. 101 if pubKey == nil { 102 return nil 103 } 104 105 return pubKey.SerializeCompressed() 106 } 107 108 // Extract the channel update from the policy we own, if any. 109 for _, edge := range policies { 110 if edge != nil && bytes.Equal(ownerPubKey, owner(edge)) { 111 return ChannelUpdateFromEdge(info, edge) 112 } 113 } 114 115 return nil, ErrUnableToExtractChanUpdate 116 } 117 118 // UnsignedChannelUpdateFromEdge reconstructs an unsigned ChannelUpdate from the 119 // given edge info and policy. 120 func UnsignedChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, 121 policy *channeldb.ChannelEdgePolicy) *lnwire.ChannelUpdate { 122 123 return &lnwire.ChannelUpdate{ 124 ChainHash: info.ChainHash, 125 ShortChannelID: lnwire.NewShortChanIDFromInt(policy.ChannelID), 126 Timestamp: uint32(policy.LastUpdate.Unix()), 127 ChannelFlags: policy.ChannelFlags, 128 MessageFlags: policy.MessageFlags, 129 TimeLockDelta: policy.TimeLockDelta, 130 HtlcMinimumMAtoms: policy.MinHTLC, 131 HtlcMaximumMAtoms: policy.MaxHTLC, 132 BaseFee: uint32(policy.FeeBaseMAtoms), 133 FeeRate: uint32(policy.FeeProportionalMillionths), 134 ExtraOpaqueData: policy.ExtraOpaqueData, 135 } 136 } 137 138 // ChannelUpdateFromEdge reconstructs a signed ChannelUpdate from the given edge 139 // info and policy. 140 func ChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo, 141 policy *channeldb.ChannelEdgePolicy) (*lnwire.ChannelUpdate, error) { 142 143 update := UnsignedChannelUpdateFromEdge(info, policy) 144 145 var err error 146 update.Signature, err = lnwire.NewSigFromRawSignature(policy.SigBytes) 147 if err != nil { 148 return nil, err 149 } 150 151 return update, nil 152 }