diff --git a/p2p/discover/table.go b/p2p/discover/table.go index 26526330b..ea9680404 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -87,6 +87,16 @@ func newTable(t transport, ourID NodeID, ourAddr *net.UDPAddr) *Table { return tab } +// Self returns the local node ID. +func (tab *Table) Self() NodeID { + return tab.self.ID +} + +// Close terminates the network listener. +func (tab *Table) Close() { + tab.net.close() +} + // Bootstrap sets the bootstrap nodes. These nodes are used to connect // to the network if the table is empty. Bootstrap will also attempt to // fill the table by performing random lookup operations on the @@ -319,27 +329,38 @@ func (n NodeID) GoString() string { // HexID converts a hex string to a NodeID. // The string may be prefixed with 0x. -func HexID(in string) NodeID { +func HexID(in string) (NodeID, error) { if strings.HasPrefix(in, "0x") { in = in[2:] } var id NodeID b, err := hex.DecodeString(in) if err != nil { - panic(err) + return id, err } else if len(b) != len(id) { - panic("wrong length") + return id, fmt.Errorf("wrong length, need %d hex bytes", len(id)) } copy(id[:], b) + return id, nil +} + +// MustHexID converts a hex string to a NodeID. +// It panics if the string is not a valid NodeID. +func MustHexID(in string) NodeID { + id, err := HexID(in) + if err != nil { + panic(err) + } return id } -func newNodeID(priv *ecdsa.PrivateKey) (id NodeID) { - pubkey := elliptic.Marshal(priv.Curve, priv.X, priv.Y) - if len(pubkey)-1 != len(id) { - panic(fmt.Errorf("invalid key: need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pubkey))) +func PubkeyID(pub *ecdsa.PublicKey) NodeID { + var id NodeID + pbytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y) + if len(pbytes)-1 != len(id) { + panic(fmt.Errorf("invalid key: need %d bit pubkey, got %d bits", (len(id)+1)*8, len(pbytes))) } - copy(id[:], pubkey[1:]) + copy(id[:], pbytes[1:]) return id } diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go index 88563fe65..90f89b147 100644 --- a/p2p/discover/table_test.go +++ b/p2p/discover/table_test.go @@ -22,8 +22,8 @@ var ( func TestHexID(t *testing.T) { ref := NodeID{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 106, 217, 182, 31, 165, 174, 1, 67, 7, 235, 220, 150, 66, 83, 173, 205, 159, 44, 10, 57, 42, 161, 26, 188} - id1 := HexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") - id2 := HexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") + id1 := MustHexID("0x000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") + id2 := MustHexID("000000000000000000000000000000000000000000000000000000000000000000000000000000806ad9b61fa5ae014307ebdc964253adcd9f2c0a392aa11abc") if id1 != ref { t.Errorf("wrong id1\ngot %v\nwant %v", id1[:], ref[:]) @@ -41,7 +41,7 @@ func TestNodeID_recover(t *testing.T) { t.Fatalf("signing error: %v", err) } - pub := newNodeID(prv) + pub := PubkeyID(&prv.PublicKey) recpub, err := recoverNodeID(hash, sig) if err != nil { t.Fatalf("recovery error: %v", err) diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go index ec1f62dac..449139c1d 100644 --- a/p2p/discover/udp.go +++ b/p2p/discover/udp.go @@ -120,8 +120,8 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string) (*Table, error) { if err != nil { return nil, err } - net.Table = newTable(net, newNodeID(priv), realaddr) - log.DebugDetailf("Listening on %v, my ID %x\n", realaddr, net.self.ID[:]) + net.Table = newTable(net, PubkeyID(&priv.PublicKey), realaddr) + log.Debugf("Listening on %v, my ID %x\n", realaddr, net.self.ID[:]) return net.Table, nil } diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go index f2ab2b661..8ed6ec9c0 100644 --- a/p2p/discover/udp_test.go +++ b/p2p/discover/udp_test.go @@ -19,8 +19,8 @@ func TestUDP_ping(t *testing.T) { n1, _ := ListenUDP(newkey(), "127.0.0.1:0") n2, _ := ListenUDP(newkey(), "127.0.0.1:0") - defer n1.net.close() - defer n2.net.close() + defer n1.Close() + defer n2.Close() if err := n1.net.ping(n2.self); err != nil { t.Fatalf("ping error: %v", err) @@ -49,8 +49,8 @@ func TestUDP_findnode(t *testing.T) { n1, _ := ListenUDP(newkey(), "127.0.0.1:0") n2, _ := ListenUDP(newkey(), "127.0.0.1:0") - defer n1.net.close() - defer n2.net.close() + defer n1.Close() + defer n2.Close() entry := &Node{ID: NodeID{1}, Addr: &net.UDPAddr{IP: net.IP{1, 2, 3, 4}, Port: 15}} n2.add([]*Node{entry}) @@ -77,7 +77,7 @@ func TestUDP_replytimeout(t *testing.T) { defer fd.Close() n1, _ := ListenUDP(newkey(), "127.0.0.1:0") - defer n1.net.close() + defer n1.Close() n2 := n1.bumpOrAdd(randomID(n1.self.ID, 10), fd.LocalAddr().(*net.UDPAddr)) if err := n1.net.ping(n2); err != errTimeout { @@ -97,8 +97,8 @@ func TestUDP_findnodeMultiReply(t *testing.T) { n1, _ := ListenUDP(newkey(), "127.0.0.1:0") n2, _ := ListenUDP(newkey(), "127.0.0.1:0") udp2 := n2.net.(*udp) - defer n1.net.close() - defer n2.net.close() + defer n1.Close() + defer n2.Close() nodes := make([]*Node, bucketSize) for i := range nodes {