routing: Move tools inside lnd. Refactor and delete unneeded stuff
Use [33]byte for graph vertex representation. Delete unneeded stuff: 1. DeepEqual for graph comparison 2. EdgePath 3. 2-thread BFS 4. Table transfer messages and neighborhood radius 5. Beacons Refactor: 1. Change ID to Vertex 2. Test use table driven approach 3. Add comments 4. Make graph internal representation private 5. Use wire.OutPoint as EdgeId 6. Decouple routing messages from routing implementation 7. Delete Async methods 8. Delete unneeded channels and priority buffer from manager 9. Delete unneeded interfaces in internal graph realisation 10. Renamed ID to Vertex
This commit is contained in:
1 parent
da3028e10c
commit
327768f4ad
37 files changed
+3152
-308
No files matched your search
@@ -62,6 +62,14 @@ func (c CreditsAmount) ToSatoshi() int64 {
|
||||
return int64(c / 1000)
|
||||
}
|
||||
|
||||
type ChannelOperation struct {
|
||||
NodePubKey1, NodePubKey2 [33]byte
|
||||
ChannelId *wire.OutPoint
|
||||
Capacity int64
|
||||
Weight float64
|
||||
Operation byte
|
||||
}
|
||||
|
||||
// writeElement is a one-stop shop to write the big endian representation of
|
||||
// any element which is to be serialized for the wire protocol. The passed
|
||||
// io.Writer should be backed by an appropriatly sized byte slice, or be able
|
||||
@@ -193,6 +201,11 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case [33]byte:
|
||||
// TODO(roasbeef): should be factor out to caller logic...
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case wire.BitcoinNet:
|
||||
var b [4]byte
|
||||
binary.BigEndian.PutUint32(b[:], uint32(e))
|
||||
@@ -282,6 +295,34 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
// TODO(roasbeef): *MsgTx
|
||||
case int64, float64:
|
||||
err := binary.Write(w, binary.BigEndian, e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case []ChannelOperation:
|
||||
err := writeElement(w, uint64(len(e)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i:=0; i<len(e); i++ {
|
||||
err := writeElement(w, e[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case ChannelOperation:
|
||||
err := writeElements(w,
|
||||
e.NodePubKey1,
|
||||
e.NodePubKey2,
|
||||
e.ChannelId,
|
||||
e.Capacity,
|
||||
e.Weight,
|
||||
e.Operation,
|
||||
)
|
||||
if err != nil{
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Unknown type in writeElement: %T", e)
|
||||
}
|
||||
@@ -447,6 +488,10 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
if _, err = io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case *[33]byte:
|
||||
if _, err = io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case *wire.BitcoinNet:
|
||||
var b [4]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
@@ -536,6 +581,37 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
index := binary.BigEndian.Uint32(idxBytes[:])
|
||||
|
||||
*e = wire.NewOutPoint(hash, index)
|
||||
case *int64, *float64:
|
||||
err := binary.Read(r, binary.BigEndian, e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case *[]ChannelOperation:
|
||||
var nChannels uint64
|
||||
err := readElement(r, &nChannels)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = make([]ChannelOperation, nChannels)
|
||||
for i:=uint64(0); i < nChannels; i++ {
|
||||
err := readElement(r, &((*e)[i]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case *ChannelOperation:
|
||||
err := readElements(r,
|
||||
&e.NodePubKey1,
|
||||
&e.NodePubKey2,
|
||||
&e.ChannelId,
|
||||
&e.Capacity,
|
||||
&e.Weight,
|
||||
&e.Operation,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("Unknown type in readElement: %T", e)
|
||||
}
|
||||
|
||||
@@ -114,10 +114,6 @@ func makeEmptyMessage(command uint32) (Message, error) {
|
||||
msg = &NeighborAckMessage{}
|
||||
case CmdNeighborRstMessage:
|
||||
msg = &NeighborRstMessage{}
|
||||
case CmdRoutingTableRequestMessage:
|
||||
msg = &RoutingTableRequestMessage{}
|
||||
case CmdRoutingTableTransferMessage:
|
||||
msg = &RoutingTableTransferMessage{}
|
||||
case CmdPing:
|
||||
msg = &Ping{}
|
||||
case CmdPong:
|
||||
|
||||
@@ -7,22 +7,20 @@ package lnwire
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/BitfuryLightning/tools/rt"
|
||||
)
|
||||
|
||||
type NeighborHelloMessage struct {
|
||||
RT *rt.RoutingTable
|
||||
// List of channels
|
||||
Channels []ChannelOperation
|
||||
}
|
||||
|
||||
func (msg *NeighborHelloMessage) Decode(r io.Reader, pver uint32) error {
|
||||
rt1, err := rt.UnmarshallRoutingTable(r)
|
||||
msg.RT = rt1
|
||||
err := readElements(r, &msg.Channels)
|
||||
return err
|
||||
}
|
||||
|
||||
func (msg *NeighborHelloMessage) Encode(w io.Writer, pver uint32) error {
|
||||
err := msg.RT.Marshall(w)
|
||||
err := writeElement(w, msg.Channels)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -41,7 +39,7 @@ func (msg *NeighborHelloMessage) Validate() error {
|
||||
}
|
||||
|
||||
func (msg *NeighborHelloMessage) String() string {
|
||||
return fmt.Sprintf("NeighborHelloMessage{%v}", msg.RT)
|
||||
return fmt.Sprintf("NeighborHelloMessage{%v}", msg.Channels)
|
||||
}
|
||||
|
||||
var _ Message = (*NeighborHelloMessage)(nil)
|
||||
@@ -7,46 +7,80 @@ package lnwire
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/BitfuryLightning/tools/rt"
|
||||
"github.com/BitfuryLightning/tools/rt/graph"
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
|
||||
func samplePubKey(b byte) [33]byte {
|
||||
var a [33]byte
|
||||
for i:=0; i<33; i++ {
|
||||
a[i] = b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func sampleOutPoint(b byte) wire.OutPoint {
|
||||
var w wire.OutPoint
|
||||
for i:=0; i<len(w.Hash); i++ {
|
||||
w.Hash[i] = b
|
||||
}
|
||||
w.Index = uint32(b)
|
||||
return w
|
||||
}
|
||||
|
||||
func genNeighborHelloMessage() *NeighborHelloMessage {
|
||||
p1 := samplePubKey(1)
|
||||
p2 := samplePubKey(2)
|
||||
p3 := samplePubKey(3)
|
||||
e1 := sampleOutPoint(4)
|
||||
e2 := sampleOutPoint(5)
|
||||
|
||||
msg := NeighborHelloMessage{
|
||||
Channels: []ChannelOperation{
|
||||
{
|
||||
NodePubKey1: p1,
|
||||
NodePubKey2: p2,
|
||||
ChannelId: &e1,
|
||||
Capacity: 100000,
|
||||
Weight: 1.0,
|
||||
Operation: 0,
|
||||
},
|
||||
{
|
||||
NodePubKey1: p2,
|
||||
NodePubKey2: p3,
|
||||
ChannelId: &e2,
|
||||
Capacity: 210000,
|
||||
Weight: 2.0,
|
||||
Operation: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
return &msg
|
||||
}
|
||||
|
||||
func TestNeighborHelloMessageEncodeDecode(t *testing.T) {
|
||||
Id1 := graph.NewID(1)
|
||||
Id2 := graph.NewID(2)
|
||||
rt1 := rt.NewRoutingTable()
|
||||
rt1.AddChannel(Id1, Id2, graph.NewEdgeID("1"), &rt.ChannelInfo{1, 1})
|
||||
msg1 := genNeighborHelloMessage()
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
msg1 := NeighborHelloMessage{RT: rt1}
|
||||
err := msg1.Encode(b, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't encode message ", err)
|
||||
}
|
||||
msg2 := new(NeighborHelloMessage)
|
||||
err = msg2.Decode(b, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't decode message ", err)
|
||||
}
|
||||
if msg2.RT == nil {
|
||||
t.Fatal("After decoding RT should not be nil")
|
||||
}
|
||||
if !msg2.RT.HasChannel(Id1, Id2, graph.NewEdgeID("1")) {
|
||||
t.Errorf("msg2.RT.HasChannel(Id1, Id2) = false, want true")
|
||||
}
|
||||
if !msg2.RT.HasChannel(Id2, Id1, graph.NewEdgeID("1")) {
|
||||
t.Errorf("msg2.RT.HasChannel(Id2, Id1) = false, want true")
|
||||
|
||||
// Assert equality of the two instances.
|
||||
if !reflect.DeepEqual(msg1, msg2) {
|
||||
t.Fatalf("encode/decode error messages don't match %v vs %v",
|
||||
msg1, msg2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNeighborHelloMessageReadWrite(t *testing.T) {
|
||||
Id1 := graph.NewID(1)
|
||||
Id2 := graph.NewID(2)
|
||||
rt1 := rt.NewRoutingTable()
|
||||
rt1.AddChannel(Id1, Id2, graph.NewEdgeID("1"), &rt.ChannelInfo{1, 1})
|
||||
msg1 := genNeighborHelloMessage()
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
msg1 := &NeighborHelloMessage{RT: rt1}
|
||||
_, err := WriteMessage(b, msg1, 0, wire.SimNet)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't write message %v", err)
|
||||
@@ -55,17 +89,10 @@ func TestNeighborHelloMessageReadWrite(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Can't read message %v", err)
|
||||
}
|
||||
msg2c, ok := msg2.(*NeighborHelloMessage)
|
||||
if !ok {
|
||||
t.Fatalf("Can't convert to *NeighborHelloMessage")
|
||||
}
|
||||
if msg2c.RT == nil {
|
||||
t.Fatal("After decoding RT should not be nil")
|
||||
}
|
||||
if !msg2c.RT.HasChannel(Id1, Id2, graph.NewEdgeID("1")) {
|
||||
t.Errorf("msg2.RT.HasChannel(Id1, Id2) = false, want true")
|
||||
}
|
||||
if !msg2c.RT.HasChannel(Id2, Id1, graph.NewEdgeID("1")) {
|
||||
t.Errorf("msg2.RT.HasChannel(Id2, Id1) = false, want true")
|
||||
|
||||
// Assert equality of the two instances.
|
||||
if !reflect.DeepEqual(msg1, msg2) {
|
||||
t.Fatalf("encode/decode error messages don't match %v vs %v",
|
||||
msg1, msg2)
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -21,15 +21,26 @@ func (msg *NeighborRstMessage) Command() uint32 {
|
||||
}
|
||||
|
||||
func (msg *NeighborRstMessage) Encode(w io.Writer, pver uint32) error {
|
||||
return nil
|
||||
_, err := w.Write([]byte("NeighborRstMessage"))
|
||||
return err
|
||||
}
|
||||
|
||||
func (msg *NeighborRstMessage) Decode(r io.Reader, pver uint32) error {
|
||||
// 18 is the length of "NeighborRstMessage"
|
||||
var b [18]byte
|
||||
_, err := r.Read(b[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if string(b[:]) != "NeighborRstMessage" {
|
||||
return fmt.Errorf("Incorrect content of NeighborRstMessage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *NeighborRstMessage) MaxPayloadLength(uint32) uint32 {
|
||||
return 0
|
||||
// 18 is the length of "NeighborRstMessage"
|
||||
return 18
|
||||
}
|
||||
|
||||
func (msg *NeighborRstMessage) Validate() error {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2016 Bitfury Group Limited
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file LICENSE or http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
)
|
||||
|
||||
func TestNeighborRstMessageEncodeDecode(t *testing.T) {
|
||||
b := new(bytes.Buffer)
|
||||
msg1 := NeighborRstMessage{}
|
||||
err := msg1.Encode(b, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't encode message ", err)
|
||||
}
|
||||
msg2 := new(NeighborRstMessage)
|
||||
err = msg2.Decode(b, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't decode message %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNeighborRstMessageReadWrite(t *testing.T){
|
||||
b := new(bytes.Buffer)
|
||||
msg1 := &NeighborRstMessage{}
|
||||
_, err := WriteMessage(b, msg1, 0, wire.SimNet)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't write message %v", err)
|
||||
}
|
||||
_, msg2, _, err := ReadMessage(b, 0, wire.SimNet)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't read message %v", err)
|
||||
}
|
||||
_, ok := msg2.(*NeighborRstMessage)
|
||||
if !ok {
|
||||
t.Fatalf("Can't convert to *NeighborRstMessage")
|
||||
}
|
||||
}
|
||||
|
||||
+4
-11
@@ -5,28 +5,21 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/BitfuryLightning/tools/rt"
|
||||
)
|
||||
|
||||
type NeighborUpdMessage struct {
|
||||
DiffBuff *rt.DifferenceBuffer
|
||||
Updates []ChannelOperation
|
||||
}
|
||||
|
||||
func (msg *NeighborUpdMessage) Decode(r io.Reader, pver uint32) error {
|
||||
decoder := gob.NewDecoder(r)
|
||||
diffBuff := new(rt.DifferenceBuffer)
|
||||
err := decoder.Decode(diffBuff)
|
||||
msg.DiffBuff = diffBuff
|
||||
err := readElements(r, &msg.Updates)
|
||||
return err
|
||||
}
|
||||
|
||||
func (msg *NeighborUpdMessage) Encode(w io.Writer, pver uint32) error {
|
||||
encoder := gob.NewEncoder(w)
|
||||
err := encoder.Encode(msg.DiffBuff)
|
||||
err := writeElements(w, msg.Updates)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -45,7 +38,7 @@ func (msg *NeighborUpdMessage) Validate() error {
|
||||
}
|
||||
|
||||
func (msg *NeighborUpdMessage) String() string {
|
||||
return fmt.Sprintf("NeighborUpdMessage{%v}", *msg.DiffBuff)
|
||||
return fmt.Sprintf("NeighborUpdMessage{%v}", msg.Updates)
|
||||
}
|
||||
|
||||
var _ Message = (*NeighborUpdMessage)(nil)
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2016 Bitfury Group Limited
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file LICENSE or http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func genNeighborUpdMessage() *NeighborUpdMessage {
|
||||
p1 := samplePubKey(1)
|
||||
p2 := samplePubKey(2)
|
||||
p3 := samplePubKey(3)
|
||||
e1 := sampleOutPoint(4)
|
||||
e2 := sampleOutPoint(5)
|
||||
|
||||
msg := NeighborUpdMessage{
|
||||
Updates: []ChannelOperation{
|
||||
{
|
||||
NodePubKey1: p1,
|
||||
NodePubKey2: p2,
|
||||
ChannelId: &e1,
|
||||
Capacity: 100000,
|
||||
Weight: 1.0,
|
||||
Operation: 0,
|
||||
},
|
||||
{
|
||||
NodePubKey1: p2,
|
||||
NodePubKey2: p3,
|
||||
ChannelId: &e2,
|
||||
Capacity: 210000,
|
||||
Weight: 2.0,
|
||||
Operation: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
return &msg
|
||||
}
|
||||
|
||||
func TestNeighborUpdMessageEncodeDecode(t *testing.T) {
|
||||
msg1 := genNeighborUpdMessage()
|
||||
b := new(bytes.Buffer)
|
||||
err := msg1.Encode(b, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't encode message: %v", err)
|
||||
}
|
||||
msg2 := new(NeighborUpdMessage)
|
||||
err = msg2.Decode(b, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't decode message: %v", err)
|
||||
}
|
||||
|
||||
// Assert equality of the two instances.
|
||||
if !reflect.DeepEqual(msg1, msg2) {
|
||||
t.Fatalf("encode/decode error messages don't match %v vs %v",
|
||||
msg1, msg2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNeighborUpdMessageReadWrite(t *testing.T) {
|
||||
msg1 := genNeighborUpdMessage()
|
||||
b := new(bytes.Buffer)
|
||||
_, err := WriteMessage(b, msg1, 0, wire.SimNet)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't write message %v", err)
|
||||
}
|
||||
_, msg2, _, err := ReadMessage(b, 0, wire.SimNet)
|
||||
if err != nil {
|
||||
t.Fatalf("Can't read message %v", err)
|
||||
}
|
||||
_, ok := msg2.(*NeighborUpdMessage)
|
||||
if !ok {
|
||||
t.Fatalf("Can't convert to *NeighborUpdMessage")
|
||||
}
|
||||
// Assert equality of the two instances.
|
||||
if !reflect.DeepEqual(msg1, msg2) {
|
||||
t.Fatalf("encode/decode error messages don't match %v vs %v",
|
||||
msg1, msg2)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright (c) 2016 Bitfury Group Limited
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file LICENSE or http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type RoutingTableRequestMessage struct {
|
||||
}
|
||||
|
||||
func (msg *RoutingTableRequestMessage) String() string {
|
||||
return fmt.Sprintf("RoutingTableRequestMessage{}")
|
||||
}
|
||||
|
||||
func (msg *RoutingTableRequestMessage) Command() uint32 {
|
||||
return CmdRoutingTableRequestMessage
|
||||
}
|
||||
|
||||
func (msg *RoutingTableRequestMessage) Encode(w io.Writer, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *RoutingTableRequestMessage) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *RoutingTableRequestMessage) MaxPayloadLength(uint32) uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (msg *RoutingTableRequestMessage) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ Message = (*RoutingTableRequestMessage)(nil)
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright (c) 2016 Bitfury Group Limited
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file LICENSE or http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/BitfuryLightning/tools/rt"
|
||||
)
|
||||
|
||||
type RoutingTableTransferMessage struct {
|
||||
RT *rt.RoutingTable
|
||||
}
|
||||
|
||||
func (msg *RoutingTableTransferMessage) String() string {
|
||||
return fmt.Sprintf("RoutingTableTransferMessage{%v %v %v}", msg.RT)
|
||||
}
|
||||
|
||||
func (msg *RoutingTableTransferMessage) Decode(r io.Reader, pver uint32) error {
|
||||
decoder := gob.NewDecoder(r)
|
||||
rt1 := rt.NewRoutingTable()
|
||||
err := decoder.Decode(rt1.G)
|
||||
msg.RT = rt1
|
||||
return err
|
||||
}
|
||||
|
||||
func (msg *RoutingTableTransferMessage) Encode(w io.Writer, pver uint32) error {
|
||||
encoder := gob.NewEncoder(w)
|
||||
err := encoder.Encode(msg.RT.G)
|
||||
return err
|
||||
}
|
||||
|
||||
func (msg *RoutingTableTransferMessage) Command() uint32 {
|
||||
return CmdRoutingTableTransferMessage
|
||||
}
|
||||
|
||||
func (msg *RoutingTableTransferMessage) MaxPayloadLength(uint32) uint32 {
|
||||
// TODO: Insert some estimations
|
||||
return 1000000
|
||||
}
|
||||
|
||||
func (msg *RoutingTableTransferMessage) Validate() error {
|
||||
// TODO: Add validation
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ Message = (*RoutingTableTransferMessage)(nil)
|
||||
Reference in new issue
Block a user