From 3d32c4e90ec9bb4f6e6197260407f171b67a7f3b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 22 Dec 2016 12:24:48 -0800 Subject: [PATCH] lnwire: separate ChannelID into a distinct struct, add tests This commit separates out the ChannelID into a new file, with additional helper methods for conversion and formatting. With this commit, the struct is now more general purpose and can be used in the new routing package, database, and other related sub-systems. --- lnwire/channel_announcement.go | 28 ++----------------- lnwire/channel_announcement_test.go | 5 ++-- lnwire/channel_id.go | 40 +++++++++++++++++++++++++++ lnwire/channel_id_test.go | 39 ++++++++++++++++++++++++++ lnwire/channel_update_announcement.go | 2 +- lnwire/node_announcement.go | 7 +++-- 6 files changed, 90 insertions(+), 31 deletions(-) create mode 100644 lnwire/channel_id.go create mode 100644 lnwire/channel_id_test.go diff --git a/lnwire/channel_announcement.go b/lnwire/channel_announcement.go index 1854dc7c..3595fda7 100644 --- a/lnwire/channel_announcement.go +++ b/lnwire/channel_announcement.go @@ -3,35 +3,13 @@ package lnwire import ( "bytes" "fmt" + "io" + "github.com/go-errors/errors" "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/wire" - "io" ) -// ChannelID represent the set of data which is needed to retrieve all -// necessary data to validate the channel existance. -type ChannelID struct { - // BlockHeight is the height of the block where funding - // transaction located. - // NOTE: This field is limited to 3 bytes. - BlockHeight uint32 - - // TxIndex is a position of funding transaction within a block. - // NOTE: This field is limited to 3 bytes. - TxIndex uint32 - - // TxPosition indicating transaction output which pays to the - // channel. - TxPosition uint16 -} - -func (c *ChannelID) String() string { - return fmt.Sprintf("BlockHeight:\t\t\t%v\n", c.BlockHeight) + - fmt.Sprintf("TxIndex:\t\t\t%v\n", c.TxIndex) + - fmt.Sprintf("TxPosition:\t\t\t%v\n", c.TxPosition) -} - // ChannelAnnouncement message is used to announce the existence of a channel // between two peers in the overlay, which is propagated by the discovery // service over broadcast handler. @@ -200,7 +178,7 @@ func (c *ChannelAnnouncement) String() string { return fmt.Sprintf("\n--- Begin ChannelAnnouncement ---\n") + fmt.Sprintf("FirstNodeSig:\t\t%v\n", c.FirstNodeSig) + fmt.Sprintf("SecondNodeSig:\t\t%v\n", c.SecondNodeSig) + - fmt.Sprintf("ChannelID:\t\t%v\n", c.ChannelID.String()) + + fmt.Sprintf("ChannelID:\t\t%v\n", c.ChannelID.ToUint64()) + fmt.Sprintf("FirstBitcoinSig:\t\t%v\n", c.FirstBitcoinSig) + fmt.Sprintf("SecondBitcoinSig:\t\t%v\n", c.SecondBitcoinSig) + fmt.Sprintf("FirstNodeSig:\t\t%v\n", c.FirstNodeSig) + diff --git a/lnwire/channel_announcement_test.go b/lnwire/channel_announcement_test.go index a0009d07..abcb22a7 100644 --- a/lnwire/channel_announcement_test.go +++ b/lnwire/channel_announcement_test.go @@ -2,10 +2,11 @@ package lnwire import ( "bytes" - "github.com/roasbeef/btcd/btcec" - "github.com/roasbeef/btcd/wire" "reflect" "testing" + + "github.com/roasbeef/btcd/btcec" + "github.com/roasbeef/btcd/wire" ) func TestChannelAnnoucementEncodeDecode(t *testing.T) { diff --git a/lnwire/channel_id.go b/lnwire/channel_id.go new file mode 100644 index 00000000..030cbcf0 --- /dev/null +++ b/lnwire/channel_id.go @@ -0,0 +1,40 @@ +package lnwire + +// ChannelID represent the set of data which is needed to retrieve all +// necessary data to validate the channel existence. +type ChannelID struct { + // BlockHeight is the height of the block where funding transaction + // located. + // + // NOTE: This field is limited to 3 bytes. + BlockHeight uint32 + + // TxIndex is a position of funding transaction within a block. + // + // NOTE: This field is limited to 3 bytes. + TxIndex uint32 + + // TxPosition indicating transaction output which pays to the + // channel. + TxPosition uint16 +} + +// NewChanIDFromInt returns a new ChannelID which is the decoded version of the +// compact channel ID encoded within the uint64. The format of the compact +// channel ID is as follows: 3 bytes for the block height, 3 bytes for the +// transaction index, and 2 bytes for the output index. +func NewChanIDFromInt(chanID uint64) ChannelID { + return ChannelID{ + BlockHeight: uint32(chanID >> 40), + TxIndex: uint32(chanID>>16) & 0xFFFFFF, + TxPosition: uint16(chanID), + } +} + +// ToUint64 converts the ChannelID into a compact format encoded within a +// uint64 (8 bytes). +func (c *ChannelID) ToUint64() uint64 { + // TODO(roasbeef): explicit error on overflow? + return ((uint64(c.BlockHeight) << 40) | (uint64(c.TxIndex) << 16) | + (uint64(c.TxPosition))) +} diff --git a/lnwire/channel_id_test.go b/lnwire/channel_id_test.go new file mode 100644 index 00000000..e2c235ff --- /dev/null +++ b/lnwire/channel_id_test.go @@ -0,0 +1,39 @@ +package lnwire + +import ( + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +func TestChannelIDEncoding(t *testing.T) { + var testCases = []ChannelID{ + { + BlockHeight: (1 << 24) - 1, + TxIndex: (1 << 24) - 1, + TxPosition: (1 << 16) - 1, + }, + { + BlockHeight: 2304934, + TxIndex: 2345, + TxPosition: 5, + }, + { + BlockHeight: 9304934, + TxIndex: 2345, + TxPosition: 5233, + }, + } + + for _, testCase := range testCases { + chanInt := testCase.ToUint64() + + newChanID := NewChanIDFromInt(chanInt) + + if !reflect.DeepEqual(testCase, newChanID) { + t.Fatalf("chan ID's don't match: expected %v got %v", + spew.Sdump(testCase), spew.Sdump(newChanID)) + } + } +} diff --git a/lnwire/channel_update_announcement.go b/lnwire/channel_update_announcement.go index 363d6570..a4358bc1 100644 --- a/lnwire/channel_update_announcement.go +++ b/lnwire/channel_update_announcement.go @@ -158,7 +158,7 @@ func (c *ChannelUpdateAnnouncement) MaxPayloadLength(pver uint32) uint32 { func (c *ChannelUpdateAnnouncement) String() string { return fmt.Sprintf("\n--- Begin ChannelUpdateAnnouncement ---\n") + fmt.Sprintf("Signature:\t\t%v\n", c.Signature) + - fmt.Sprintf("ChannelID:\t\t%v\n", c.ChannelID.String()) + + fmt.Sprintf("ChannelID:\t\t%v\n", c.ChannelID.ToUint64()) + fmt.Sprintf("Timestamp:\t\t%v\n", c.Timestamp) + fmt.Sprintf("Flags:\t\t%v\n", c.Flags) + fmt.Sprintf("Expiry:\t\t%v\n", c.Expiry) + diff --git a/lnwire/node_announcement.go b/lnwire/node_announcement.go index 33829ec7..43e48469 100644 --- a/lnwire/node_announcement.go +++ b/lnwire/node_announcement.go @@ -3,11 +3,12 @@ package lnwire import ( "bytes" "fmt" + "io" + "net" + "github.com/go-errors/errors" "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/wire" - "io" - "net" ) var ( @@ -72,7 +73,7 @@ type NodeAnnouncement struct { // the node is accepting incoming connections. Address *net.TCPAddr - // NodeID is a public key which is used as node identificator. + // NodeID is a public key which is used as node identification. NodeID *btcec.PublicKey // RGBColor is used to customize their node's appearance in maps and graphs