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