lnwire: add support for Features in NodeAnnouncement

Add support for Features in NodeAnnouncment according to spec.
This commit is contained in:
bryanvu authored and Olaoluwa Osuntokun committed 2017-03-29 12:03:43 -07:00
1 parent 3087bec4db
commit 085b7333cb
10 files changed
+145 -32

No files matched your search

+13
View File
@@ -9,6 +9,7 @@ import (
"time"
"github.com/boltdb/bolt"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/wire"
@@ -830,6 +831,9 @@ type LightningNode struct {
// TODO(roasbeef): hook into serialization once full verification is in
AuthSig *btcec.Signature
// Features is the list of protocol features supported by this node.
Features *lnwire.FeatureVector
db *DB
// TODO(roasbeef): discovery will need storage to keep it's last IP
@@ -1309,6 +1313,10 @@ func putLightningNode(nodeBucket *bolt.Bucket, aliasBucket *bolt.Bucket, node *L
return err
}
if err := node.Features.Encode(&b); err != nil {
return err
}
numAddresses := uint16(len(node.Addresses))
byteOrder.PutUint16(scratch[:2], numAddresses)
if _, err := b.Write(scratch[:2]); err != nil {
@@ -1395,6 +1403,11 @@ func deserializeLightningNode(r io.Reader) (*LightningNode, error) {
return nil, err
}
node.Features, err = lnwire.NewFeatureVectorFromReader(r)
if err != nil {
return nil, err
}
if _, err := r.Read(scratch[:2]); err != nil {
return nil, err
}
+93 -20
View File
@@ -14,6 +14,7 @@ import (
"time"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/wire"
@@ -35,6 +36,8 @@ var (
}
_, _ = testSig.R.SetString("63724406601629180062774974542967536251589935445068131219452686511677818569431", 10)
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
testFeatures = lnwire.NewFeatureVector([]lnwire.Feature{})
)
func createTestVertex(db *DB) (*LightningNode, error) {
@@ -48,10 +51,11 @@ func createTestVertex(db *DB) (*LightningNode, error) {
pub := priv.PubKey().SerializeCompressed()
return &LightningNode{
LastUpdate: time.Unix(updateTime, 0),
Addresses: testAddrs,
PubKey: priv.PubKey(),
Color: color.RGBA{1, 2, 3, 0},
Alias: "kek" + string(pub[:]),
Features: testFeatures,
Addresses: testAddrs,
db: db,
}, nil
}
@@ -70,10 +74,11 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
_, testPub := btcec.PrivKeyFromBytes(btcec.S256(), key[:])
node := &LightningNode{
LastUpdate: time.Unix(1232342, 0),
Addresses: testAddrs,
PubKey: testPub,
Color: color.RGBA{1, 2, 3, 0},
Alias: "kek",
Features: testFeatures,
Addresses: testAddrs,
db: db,
}
@@ -97,9 +102,8 @@ func TestNodeInsertionAndDeletion(t *testing.T) {
}
// The two nodes should match exactly!
if !reflect.DeepEqual(node, dbNode) {
t.Fatalf("retrieved node doesn't match: expected %#v\n, got %#v\n",
node, dbNode)
if err := compareNodes(node, dbNode); err != nil {
t.Fatalf("nodes don't match: %v", err)
}
// Next, delete the node from the graph, this should purge all data
@@ -194,9 +198,8 @@ func TestSourceNode(t *testing.T) {
if err != nil {
t.Fatalf("unable to fetch source node: %v", err)
}
if !reflect.DeepEqual(testNode, sourceNode) {
t.Fatalf("nodes don't match, expected %#v \n got %#v",
testNode, sourceNode)
if err := compareNodes(testNode, sourceNode); err != nil {
t.Fatalf("nodes don't match: %v", err)
}
}
@@ -454,13 +457,11 @@ func TestEdgeInfoUpdates(t *testing.T) {
if err != nil {
t.Fatalf("unable to fetch channel by ID: %v", err)
}
if !reflect.DeepEqual(dbEdge1, edge1) {
t.Fatalf("edge doesn't match: expected %#v, \n got %#v", edge1,
dbEdge1)
if err := compareEdgePolicies(dbEdge1, edge1); err != nil {
t.Fatalf("edge doesn't match: %v", err)
}
if !reflect.DeepEqual(dbEdge2, edge2) {
t.Fatalf("edge doesn't match: expected %#v, \n got %#v", edge2,
dbEdge2)
if err := compareEdgePolicies(dbEdge2, edge2); err != nil {
t.Fatalf("edge doesn't match: %v", err)
}
assertEdgeInfoEqual(t, dbEdgeInfo, edgeInfo)
@@ -470,13 +471,11 @@ func TestEdgeInfoUpdates(t *testing.T) {
if err != nil {
t.Fatalf("unable to fetch channel by ID: %v", err)
}
if !reflect.DeepEqual(dbEdge1, edge1) {
t.Fatalf("edge doesn't match: expected %#v, \n got %#v", edge1,
dbEdge1)
if err := compareEdgePolicies(dbEdge1, edge1); err != nil {
t.Fatalf("edge doesn't match: %v", err)
}
if !reflect.DeepEqual(dbEdge2, edge2) {
t.Fatalf("edge doesn't match: expected %#v, \n got %#v", edge2,
dbEdge2)
if err := compareEdgePolicies(dbEdge2, edge2); err != nil {
t.Fatalf("edge doesn't match: %v", err)
}
assertEdgeInfoEqual(t, dbEdgeInfo, edgeInfo)
}
@@ -830,3 +829,77 @@ func TestGraphPruning(t *testing.T) {
assertPruneTip(t, graph, &blockHash, blockHeight)
asserNumChans(t, graph, 0)
}
// compareNodes is used to compare two LightningNodes while excluding the
// Features struct, which cannot be compared as the semantics for reserializing
// the featuresMap have not been defined.
func compareNodes(a, b *LightningNode) error {
if !reflect.DeepEqual(a.LastUpdate, b.LastUpdate) {
return fmt.Errorf("LastUpdate doesn't match: expected %#v, \n"+
"got %#v", a.LastUpdate, b.LastUpdate)
}
if !reflect.DeepEqual(a.Addresses, b.Addresses) {
return fmt.Errorf("Addresses doesn't match: expected %#v, \n "+
"got %#v", a.Addresses, b.Addresses)
}
if !reflect.DeepEqual(a.PubKey, b.PubKey) {
return fmt.Errorf("PubKey doesn't match: expected %#v, \n "+
"got %#v", a.PubKey, b.PubKey)
}
if !reflect.DeepEqual(a.Color, b.Color) {
return fmt.Errorf("Color doesn't match: expected %#v, \n "+
"got %#v", a.Color, b.Color)
}
if !reflect.DeepEqual(a.Alias, b.Alias) {
return fmt.Errorf("Alias doesn't match: expected %#v, \n "+
"got %#v", a.Alias, b.Alias)
}
if !reflect.DeepEqual(a.db, b.db) {
return fmt.Errorf("db doesn't match: expected %#v, \n "+
"got %#v", a.db, b.db)
}
return nil
}
// compareEdgePolicies is used to compare two ChannelEdgePolices using
// compareNodes, so as to exclude comparisons of the Nodes' Features struct.
func compareEdgePolicies(a, b *ChannelEdgePolicy) error {
if a.ChannelID != b.ChannelID {
return fmt.Errorf("ChannelID doesn't match: expected %v, "+
"got %v", a.ChannelID, b.ChannelID)
}
if !reflect.DeepEqual(a.LastUpdate, b.LastUpdate) {
return fmt.Errorf("LastUpdate doesn't match: expected %#v, \n "+
"got %#v", a.LastUpdate, b.LastUpdate)
}
if a.Flags != b.Flags {
return fmt.Errorf("Flags doesn't match: expected %v, "+
"got %v", a.Flags, b.Flags)
}
if a.TimeLockDelta != b.TimeLockDelta {
return fmt.Errorf("TimeLockDelta doesn't match: expected %v, "+
"got %v", a.TimeLockDelta, b.TimeLockDelta)
}
if a.MinHTLC != b.MinHTLC {
return fmt.Errorf("MinHTLC doesn't match: expected %v, "+
"got %v", a.MinHTLC, b.MinHTLC)
}
if a.FeeBaseMSat != b.FeeBaseMSat {
return fmt.Errorf("FeeBaseMSat doesn't match: expected %v, "+
"got %v", a.FeeBaseMSat, b.FeeBaseMSat)
}
if a.FeeProportionalMillionths != b.FeeProportionalMillionths {
return fmt.Errorf("FeeProportionalMillionths doesn't match: "+
"expected %v, got %v", a.FeeProportionalMillionths,
b.FeeProportionalMillionths)
}
if err := compareNodes(a.Node, b.Node); err != nil {
return err
}
if !reflect.DeepEqual(a.db, b.db) {
return fmt.Errorf("db doesn't match: expected %#v, \n "+
"got %#v", a.db, b.db)
}
return nil
}