Skip to content

Commit b068fc0

Browse files
committed
channeldb: add encoding for ChannelEdgePolicy2
1 parent f5f2514 commit b068fc0

File tree

4 files changed

+352
-12
lines changed

4 files changed

+352
-12
lines changed

channeldb/edge_info_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ func TestEdgeInfoSerialisation(t *testing.T) {
8181

8282
// Sometimes add an AuthProof.
8383
if r.Intn(2)%2 == 0 {
84+
n := r.Intn(80)
85+
8486
//nolint:lll
8587
authProof := &models.ChannelAuthProof1{
86-
NodeSig1Bytes: make([]byte, 33),
87-
NodeSig2Bytes: make([]byte, 33),
88-
BitcoinSig1Bytes: make([]byte, 33),
89-
BitcoinSig2Bytes: make([]byte, 33),
88+
NodeSig1Bytes: make([]byte, n),
89+
NodeSig2Bytes: make([]byte, n),
90+
BitcoinSig1Bytes: make([]byte, n),
91+
BitcoinSig2Bytes: make([]byte, n),
9092
}
9193

9294
_, err = r.Read(

channeldb/edge_policy.go

Lines changed: 196 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package channeldb
22

33
import (
4+
"bufio"
45
"bytes"
56
"encoding/binary"
67
"errors"
@@ -12,6 +13,30 @@ import (
1213
"github.com/lightningnetwork/lnd/channeldb/models"
1314
"github.com/lightningnetwork/lnd/kvdb"
1415
"github.com/lightningnetwork/lnd/lnwire"
16+
"github.com/lightningnetwork/lnd/tlv"
17+
)
18+
19+
const (
20+
EdgePolicy2MsgType = tlv.Type(0)
21+
EdgePolicy2ToNode = tlv.Type(1)
22+
23+
// chanEdgePolicyNewEncodingPrefix is a byte used in the channel edge
24+
// policy encoding to signal that the new style encoding which is
25+
// prefixed with a type byte is being used instead of the legacy
26+
// encoding which would start with 0x02 due to the fact that the
27+
// encoding would start with a DER encoded ecdsa signature.
28+
chanEdgePolicyNewEncodingPrefix = 0xff
29+
)
30+
31+
// edgePolicyEncoding indicates how the bytes for a channel edge policy have
32+
// been serialised.
33+
type edgePolicyEncodingType uint8
34+
35+
const (
36+
// edgePolicy2EncodingType will be used as a prefix for edge policies
37+
// advertised using the ChannelUpdate2 message. The type indicates how
38+
// the bytes following should be deserialized.
39+
edgePolicy2EncodingType edgePolicyEncodingType = 0
1540
)
1641

1742
func putChanEdgePolicy(edges kvdb.RwBucket, edge *models.ChannelEdgePolicy1,
@@ -63,7 +88,14 @@ func putChanEdgePolicy(edges kvdb.RwBucket, edge *models.ChannelEdgePolicy1,
6388
return err
6489
}
6590

66-
oldUpdateTime := uint64(oldEdgePolicy.LastUpdate.Unix())
91+
oldPol, ok := oldEdgePolicy.(*models.ChannelEdgePolicy1)
92+
if !ok {
93+
return fmt.Errorf("expected "+
94+
"*models.ChannelEdgePolicy1, got: %T",
95+
oldEdgePolicy)
96+
}
97+
98+
oldUpdateTime := uint64(oldPol.LastUpdate.Unix())
6799

68100
var oldIndexKey [8 + 8]byte
69101
byteOrder.PutUint64(oldIndexKey[:8], oldUpdateTime)
@@ -169,7 +201,13 @@ func fetchChanEdgePolicy(edges kvdb.RBucket, chanID []byte, nodePub []byte) (
169201
return nil, err
170202
}
171203

172-
return ep, nil
204+
pol, ok := ep.(*models.ChannelEdgePolicy1)
205+
if !ok {
206+
return nil, fmt.Errorf("expected *models.ChannelEdgePolicy1, "+
207+
"got: %T", ep)
208+
}
209+
210+
return pol, nil
173211
}
174212

175213
func fetchChanEdgePolicies(edgeIndex kvdb.RBucket, edges kvdb.RBucket,
@@ -201,8 +239,56 @@ func fetchChanEdgePolicies(edgeIndex kvdb.RBucket, edges kvdb.RBucket,
201239
return edge1, edge2, nil
202240
}
203241

204-
func serializeChanEdgePolicy(w io.Writer, edge *models.ChannelEdgePolicy1,
205-
to []byte) error {
242+
func serializeChanEdgePolicy(w io.Writer,
243+
edgePolicy models.ChannelEdgePolicy, toNode []byte) error {
244+
245+
var (
246+
withTypeByte bool
247+
typeByte edgePolicyEncodingType
248+
serialize func(w io.Writer) error
249+
)
250+
251+
switch policy := edgePolicy.(type) {
252+
case *models.ChannelEdgePolicy1:
253+
serialize = func(w io.Writer) error {
254+
copy(policy.ToNode[:], toNode)
255+
256+
return serializeChanEdgePolicy1(w, policy)
257+
}
258+
case *models.ChannelEdgePolicy2:
259+
withTypeByte = true
260+
typeByte = edgePolicy2EncodingType
261+
262+
serialize = func(w io.Writer) error {
263+
copy(policy.ToNode[:], toNode)
264+
265+
return serializeChanEdgePolicy2(w, policy)
266+
}
267+
default:
268+
return fmt.Errorf("unhandled implementation of "+
269+
"ChannelEdgePolicy: %T", edgePolicy)
270+
}
271+
272+
if withTypeByte {
273+
// First, write the identifying encoding byte to signal that
274+
// this is not using the legacy encoding.
275+
_, err := w.Write([]byte{chanEdgePolicyNewEncodingPrefix})
276+
if err != nil {
277+
return err
278+
}
279+
280+
// Now, write the encoding type.
281+
_, err = w.Write([]byte{byte(typeByte)})
282+
if err != nil {
283+
return err
284+
}
285+
}
286+
287+
return serialize(w)
288+
}
289+
290+
func serializeChanEdgePolicy1(w io.Writer,
291+
edge *models.ChannelEdgePolicy1) error {
206292

207293
err := wire.WriteVarBytes(w, 0, edge.SigBytes)
208294
if err != nil {
@@ -241,7 +327,7 @@ func serializeChanEdgePolicy(w io.Writer, edge *models.ChannelEdgePolicy1,
241327
return err
242328
}
243329

244-
if _, err := w.Write(to); err != nil {
330+
if _, err := w.Write(edge.ToNode[:]); err != nil {
245331
return err
246332
}
247333

@@ -267,7 +353,34 @@ func serializeChanEdgePolicy(w io.Writer, edge *models.ChannelEdgePolicy1,
267353
return wire.WriteVarBytes(w, 0, opaqueBuf.Bytes())
268354
}
269355

270-
func deserializeChanEdgePolicy(r io.Reader) (*models.ChannelEdgePolicy1,
356+
func serializeChanEdgePolicy2(w io.Writer,
357+
edge *models.ChannelEdgePolicy2) error {
358+
359+
if len(edge.ExtraOpaqueData) > MaxAllowedExtraOpaqueBytes {
360+
return ErrTooManyExtraOpaqueBytes(len(edge.ExtraOpaqueData))
361+
}
362+
363+
var b bytes.Buffer
364+
if err := edge.Encode(&b, 0); err != nil {
365+
return err
366+
}
367+
368+
msg := b.Bytes()
369+
370+
records := []tlv.Record{
371+
tlv.MakePrimitiveRecord(EdgePolicy2MsgType, &msg),
372+
tlv.MakePrimitiveRecord(EdgePolicy2ToNode, &edge.ToNode),
373+
}
374+
375+
stream, err := tlv.NewStream(records...)
376+
if err != nil {
377+
return err
378+
}
379+
380+
return stream.Encode(w)
381+
}
382+
383+
func deserializeChanEdgePolicy(r io.Reader) (models.ChannelEdgePolicy,
271384
error) {
272385

273386
// Deserialize the policy. Note that in case an optional field is not
@@ -282,7 +395,7 @@ func deserializeChanEdgePolicy(r io.Reader) (*models.ChannelEdgePolicy1,
282395
return edge, deserializeErr
283396
}
284397

285-
func deserializeChanEdgePolicyRaw(r io.Reader) (*models.ChannelEdgePolicy1,
398+
func deserializeChanEdgePolicy1Raw(r io.Reader) (*models.ChannelEdgePolicy1,
286399
error) {
287400

288401
var edge models.ChannelEdgePolicy1
@@ -368,3 +481,79 @@ func deserializeChanEdgePolicyRaw(r io.Reader) (*models.ChannelEdgePolicy1,
368481

369482
return &edge, nil
370483
}
484+
485+
func deserializeChanEdgePolicyRaw(reader io.Reader) (models.ChannelEdgePolicy,
486+
error) {
487+
488+
// Wrap the io.Reader in a bufio.Reader so that we can peak the first
489+
// byte of the stream without actually consuming from the stream.
490+
r := bufio.NewReader(reader)
491+
492+
firstByte, err := r.Peek(1)
493+
if err != nil {
494+
return nil, err
495+
}
496+
497+
if firstByte[0] != chanEdgePolicyNewEncodingPrefix {
498+
return deserializeChanEdgePolicy1Raw(r)
499+
}
500+
501+
// Pop the encoding type byte.
502+
var scratch [1]byte
503+
if _, err = r.Read(scratch[:]); err != nil {
504+
return nil, err
505+
}
506+
507+
// Now, read the encoding type byte.
508+
if _, err = r.Read(scratch[:]); err != nil {
509+
return nil, err
510+
}
511+
512+
encoding := edgePolicyEncodingType(scratch[0])
513+
switch encoding {
514+
case edgePolicy2EncodingType:
515+
return deserializeChanEdgePolicy2Raw(r)
516+
517+
default:
518+
return nil, fmt.Errorf("unknown edge policy encoding type: %d",
519+
encoding)
520+
}
521+
}
522+
523+
func deserializeChanEdgePolicy2Raw(r io.Reader) (*models.ChannelEdgePolicy2,
524+
error) {
525+
526+
var (
527+
msgBytes []byte
528+
toNode [33]byte
529+
)
530+
531+
records := []tlv.Record{
532+
tlv.MakePrimitiveRecord(EdgePolicy2MsgType, &msgBytes),
533+
tlv.MakePrimitiveRecord(EdgePolicy2ToNode, &toNode),
534+
}
535+
536+
stream, err := tlv.NewStream(records...)
537+
if err != nil {
538+
return nil, err
539+
}
540+
541+
err = stream.Decode(r)
542+
if err != nil {
543+
return nil, err
544+
}
545+
546+
var (
547+
chanUpdate lnwire.ChannelUpdate2
548+
reader = bytes.NewReader(msgBytes)
549+
)
550+
err = chanUpdate.Decode(reader, 0)
551+
if err != nil {
552+
return nil, err
553+
}
554+
555+
return &models.ChannelEdgePolicy2{
556+
ChannelUpdate2: chanUpdate,
557+
ToNode: toNode,
558+
}, nil
559+
}

0 commit comments

Comments
 (0)