github.com/decred/dcrlnd@v0.7.6/lnwire/open_channel.go (about) 1 package lnwire 2 3 import ( 4 "bytes" 5 "io" 6 7 "github.com/decred/dcrd/chaincfg/chainhash" 8 "github.com/decred/dcrd/dcrec/secp256k1/v4" 9 "github.com/decred/dcrd/dcrutil/v4" 10 "github.com/decred/dcrlnd/tlv" 11 ) 12 13 // FundingFlag represents the possible bit mask values for the ChannelFlags 14 // field within the OpenChannel struct. 15 type FundingFlag uint8 16 17 const ( 18 // FFAnnounceChannel is a FundingFlag that when set, indicates the 19 // initiator of a funding flow wishes to announce the channel to the 20 // greater network. 21 FFAnnounceChannel FundingFlag = 1 << iota 22 ) 23 24 // OpenChannel is the message Alice sends to Bob if we should like to create a 25 // channel with Bob where she's the sole provider of funds to the channel. 26 // Single funder channels simplify the initial funding workflow, are supported 27 // by nodes backed by SPV clients, and have a simpler security models than dual 28 // funded channels. 29 type OpenChannel struct { 30 // ChainHash is the target chain that the initiator wishes to open a 31 // channel within. 32 ChainHash chainhash.Hash 33 34 // PendingChannelID serves to uniquely identify the future channel 35 // created by the initiated single funder workflow. 36 PendingChannelID [32]byte 37 38 // FundingAmount is the amount of atoms that the initiator of the 39 // channel wishes to use as the total capacity of the channel. The 40 // initial balance of the funding will be this value minus the push 41 // amount (if set). 42 FundingAmount dcrutil.Amount 43 44 // PushAmount is the value that the initiating party wishes to "push" 45 // to the responding as part of the first commitment state. If the 46 // responder accepts, then this will be their initial balance. 47 PushAmount MilliAtom 48 49 // DustLimit is the specific dust limit the sender of this message 50 // would like enforced on their version of the commitment transaction. 51 // Any output below this value will be "trimmed" from the commitment 52 // transaction, with the amount of the HTLC going to dust. 53 DustLimit dcrutil.Amount 54 55 // MaxValueInFlight represents the maximum amount of coins that can be 56 // pending within the channel at any given time. If the amount of funds 57 // in limbo exceeds this amount, then the channel will be failed. 58 MaxValueInFlight MilliAtom 59 60 // ChannelReserve is the amount that the receiving party MUST 61 // maintain a balance above at all times. This is a safety mechanism to 62 // ensure that both sides always have skin in the game during the 63 // channel's lifetime. 64 ChannelReserve dcrutil.Amount 65 66 // HtlcMinimum is the smallest HTLC that the sender of this message 67 // will accept. 68 HtlcMinimum MilliAtom 69 70 // FeePerKiloByte is the initial fee rate that the initiator suggests 71 // for both commitment transaction. This value is expressed in atoms 72 // per kilobyte. 73 // 74 // TODO(halseth): make AtomsPerKWeight when fee estimation is in own 75 // package. Currently this will cause an import cycle. 76 FeePerKiloByte uint32 77 78 // CsvDelay is the number of blocks to use for the relative time lock 79 // in the pay-to-self output of both commitment transactions. 80 CsvDelay uint16 81 82 // MaxAcceptedHTLCs is the total number of incoming HTLC's that the 83 // sender of this channel will accept. 84 MaxAcceptedHTLCs uint16 85 86 // FundingKey is the key that should be used on behalf of the sender 87 // within the 2-of-2 multi-sig output that it contained within the 88 // funding transaction. 89 FundingKey *secp256k1.PublicKey 90 91 // RevocationPoint is the base revocation point for the sending party. 92 // Any commitment transaction belonging to the receiver of this message 93 // should use this key and their per-commitment point to derive the 94 // revocation key for the commitment transaction. 95 RevocationPoint *secp256k1.PublicKey 96 97 // PaymentPoint is the base payment point for the sending party. This 98 // key should be combined with the per commitment point for a 99 // particular commitment state in order to create the key that should 100 // be used in any output that pays directly to the sending party, and 101 // also within the HTLC covenant transactions. 102 PaymentPoint *secp256k1.PublicKey 103 104 // DelayedPaymentPoint is the delay point for the sending party. This 105 // key should be combined with the per commitment point to derive the 106 // keys that are used in outputs of the sender's commitment transaction 107 // where they claim funds. 108 DelayedPaymentPoint *secp256k1.PublicKey 109 110 // HtlcPoint is the base point used to derive the set of keys for this 111 // party that will be used within the HTLC public key scripts. This 112 // value is combined with the receiver's revocation base point in order 113 // to derive the keys that are used within HTLC scripts. 114 HtlcPoint *secp256k1.PublicKey 115 116 // FirstCommitmentPoint is the first commitment point for the sending 117 // party. This value should be combined with the receiver's revocation 118 // base point in order to derive the revocation keys that are placed 119 // within the commitment transaction of the sender. 120 FirstCommitmentPoint *secp256k1.PublicKey 121 122 // ChannelFlags is a bit-field which allows the initiator of the 123 // channel to specify further behavior surrounding the channel. 124 // Currently, the least significant bit of this bit field indicates the 125 // initiator of the channel wishes to advertise this channel publicly. 126 ChannelFlags FundingFlag 127 128 // UpfrontShutdownScript is the script to which the channel funds should 129 // be paid when mutually closing the channel. This field is optional, and 130 // and has a length prefix, so a zero will be written if it is not set 131 // and its length followed by the script will be written if it is set. 132 UpfrontShutdownScript DeliveryAddress 133 134 // ChannelType is the explicit channel type the initiator wishes to 135 // open. 136 ChannelType *ChannelType 137 138 // LeaseExpiry represents the absolute expiration height of a channel 139 // lease. This is a custom TLV record that will only apply when a leased 140 // channel is being opened using the script enforced lease commitment 141 // type. 142 LeaseExpiry *LeaseExpiry 143 144 // ExtraData is the set of data that was appended to this message to 145 // fill out the full maximum transport message size. These fields can 146 // be used to specify optional data such as custom TLV fields. 147 // 148 // NOTE: Since the upfront shutdown script MUST be present (though can 149 // be zero-length) if any TLV data is available, the script will be 150 // extracted and removed from this blob when decoding. ExtraData will 151 // contain all TLV records _except_ the DeliveryAddress record in that 152 // case. 153 ExtraData ExtraOpaqueData 154 } 155 156 // A compile time check to ensure OpenChannel implements the lnwire.Message 157 // interface. 158 var _ Message = (*OpenChannel)(nil) 159 160 // Encode serializes the target OpenChannel into the passed io.Writer 161 // implementation. Serialization will observe the rules defined by the passed 162 // protocol version. 163 func (o *OpenChannel) Encode(w *bytes.Buffer, pver uint32) error { 164 recordProducers := []tlv.RecordProducer{&o.UpfrontShutdownScript} 165 if o.ChannelType != nil { 166 recordProducers = append(recordProducers, o.ChannelType) 167 } 168 if o.LeaseExpiry != nil { 169 recordProducers = append(recordProducers, o.LeaseExpiry) 170 } 171 err := EncodeMessageExtraData(&o.ExtraData, recordProducers...) 172 if err != nil { 173 return err 174 } 175 176 if err := WriteBytes(w, o.ChainHash[:]); err != nil { 177 return err 178 } 179 180 if err := WriteBytes(w, o.PendingChannelID[:]); err != nil { 181 return err 182 } 183 184 if err := WriteSatoshi(w, o.FundingAmount); err != nil { 185 return err 186 } 187 188 if err := WriteMilliAtom(w, o.PushAmount); err != nil { 189 return err 190 } 191 192 if err := WriteSatoshi(w, o.DustLimit); err != nil { 193 return err 194 } 195 196 if err := WriteMilliAtom(w, o.MaxValueInFlight); err != nil { 197 return err 198 } 199 200 if err := WriteSatoshi(w, o.ChannelReserve); err != nil { 201 return err 202 } 203 204 if err := WriteMilliAtom(w, o.HtlcMinimum); err != nil { 205 return err 206 } 207 208 if err := WriteUint32(w, o.FeePerKiloByte); err != nil { 209 return err 210 } 211 212 if err := WriteUint16(w, o.CsvDelay); err != nil { 213 return err 214 } 215 216 if err := WriteUint16(w, o.MaxAcceptedHTLCs); err != nil { 217 return err 218 } 219 220 if err := WritePublicKey(w, o.FundingKey); err != nil { 221 return err 222 } 223 224 if err := WritePublicKey(w, o.RevocationPoint); err != nil { 225 return err 226 } 227 228 if err := WritePublicKey(w, o.PaymentPoint); err != nil { 229 return err 230 } 231 232 if err := WritePublicKey(w, o.DelayedPaymentPoint); err != nil { 233 return err 234 } 235 236 if err := WritePublicKey(w, o.HtlcPoint); err != nil { 237 return err 238 239 } 240 241 if err := WritePublicKey(w, o.FirstCommitmentPoint); err != nil { 242 return err 243 } 244 245 if err := WriteFundingFlag(w, o.ChannelFlags); err != nil { 246 return err 247 } 248 249 return WriteBytes(w, o.ExtraData) 250 } 251 252 // Decode deserializes the serialized OpenChannel stored in the passed 253 // io.Reader into the target OpenChannel using the deserialization rules 254 // defined by the passed protocol version. 255 // 256 // This is part of the lnwire.Message interface. 257 func (o *OpenChannel) Decode(r io.Reader, pver uint32) error { 258 // Read all the mandatory fields in the open message. 259 err := ReadElements(r, 260 o.ChainHash[:], 261 o.PendingChannelID[:], 262 &o.FundingAmount, 263 &o.PushAmount, 264 &o.DustLimit, 265 &o.MaxValueInFlight, 266 &o.ChannelReserve, 267 &o.HtlcMinimum, 268 &o.FeePerKiloByte, 269 &o.CsvDelay, 270 &o.MaxAcceptedHTLCs, 271 &o.FundingKey, 272 &o.RevocationPoint, 273 &o.PaymentPoint, 274 &o.DelayedPaymentPoint, 275 &o.HtlcPoint, 276 &o.FirstCommitmentPoint, 277 &o.ChannelFlags, 278 ) 279 if err != nil { 280 return err 281 } 282 283 // For backwards compatibility, the optional extra data blob for 284 // OpenChannel must contain an entry for the upfront shutdown script. 285 // We'll read it out and attempt to parse it. 286 var tlvRecords ExtraOpaqueData 287 if err := ReadElements(r, &tlvRecords); err != nil { 288 return err 289 } 290 291 // Next we'll parse out the set of known records, keeping the raw tlv 292 // bytes untouched to ensure we don't drop any bytes erroneously. 293 var ( 294 chanType ChannelType 295 leaseExpiry LeaseExpiry 296 ) 297 typeMap, err := tlvRecords.ExtractRecords( 298 &o.UpfrontShutdownScript, &chanType, &leaseExpiry, 299 ) 300 if err != nil { 301 return err 302 } 303 304 // Set the corresponding TLV types if they were included in the stream. 305 if val, ok := typeMap[ChannelTypeRecordType]; ok && val == nil { 306 o.ChannelType = &chanType 307 } 308 if val, ok := typeMap[LeaseExpiryRecordType]; ok && val == nil { 309 o.LeaseExpiry = &leaseExpiry 310 } 311 312 o.ExtraData = tlvRecords 313 314 return nil 315 } 316 317 // MsgType returns the MessageType code which uniquely identifies this message 318 // as an OpenChannel on the wire. 319 // 320 // This is part of the lnwire.Message interface. 321 func (o *OpenChannel) MsgType() MessageType { 322 return MsgOpenChannel 323 }