From 791e33fccedf8c751a2a6a50e1370f9137f0aec7 Mon Sep 17 00:00:00 2001 From: Yusef Napora Date: Fri, 8 Nov 2019 11:09:02 -0500 Subject: [PATCH] add helpers to make routing records for Host --- host/helpers.go | 23 ++++++++++++++++++++++- routing/state.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/host/helpers.go b/host/helpers.go index a24beb1..e045631 100644 --- a/host/helpers.go +++ b/host/helpers.go @@ -1,6 +1,11 @@ package host -import "github.com/libp2p/go-libp2p-core/peer" +import ( + "errors" + "github.com/libp2p/go-libp2p-core/crypto" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/routing" +) // InfoFromHost returns a peer.AddrInfo struct with the Host's ID and all of its Addrs. func InfoFromHost(h Host) *peer.AddrInfo { @@ -9,3 +14,19 @@ func InfoFromHost(h Host) *peer.AddrInfo { Addrs: h.Addrs(), } } + +// RoutingStateFromHost returns a routing.RoutingState record that contains the Host's +// ID and all of its listen Addrs. +func RoutingStateFromHost(h Host) *routing.RoutingState { + return routing.RoutingStateFromAddrInfo(InfoFromHost(h)) +} + +// SignedRoutingStateFromHost +func SignedRoutingStateFromHost(h Host) (*crypto.SignedEnvelope, error) { + privKey := h.Peerstore().PrivKey(h.ID()) + if privKey == nil { + return nil, errors.New("unable to find host's private key in peerstore") + } + + return RoutingStateFromHost(h).ToSignedEnvelope(privKey) +} diff --git a/routing/state.go b/routing/state.go index 490f99c..619b1b6 100644 --- a/routing/state.go +++ b/routing/state.go @@ -7,11 +7,16 @@ import ( "github.com/libp2p/go-libp2p-core/peer" ma "github.com/multiformats/go-multiaddr" pb "github.com/libp2p/go-libp2p-core/routing/pb" + "time" ) // The domain string used for routing state records contained in a SignedEnvelope. const StateEnvelopeDomain = "libp2p-routing-record" +// The type hint used to identify routing state records in a SignedEnvelope. +// TODO: register multicodec +var StateEnvelopeTypeHint = []byte("/libp2p/routing-record") + // AnnotatedAddr will extend the Multiaddr type with additional metadata, as // extensions are added to the routing state record spec. It's defined now to // make refactoring simpler in the future. @@ -36,6 +41,18 @@ type RoutingState struct { Addresses []*AnnotatedAddr } +func RoutingStateFromAddrInfo(info *peer.AddrInfo) *RoutingState { + annotated := make([]*AnnotatedAddr, len(info.Addrs)) + for i, a := range info.Addrs { + annotated[i] = &AnnotatedAddr{Multiaddr: a} + } + return &RoutingState{ + PeerID: info.ID, + Seq: statelessSeqNo(), + Addresses: annotated, + } +} + // UnmarshalRoutingState unpacks a peer RoutingState record from a serialized protobuf representation. func UnmarshalRoutingState(serialized []byte) (*RoutingState, error) { msg := pb.RoutingStateRecord{} @@ -72,6 +89,16 @@ func RoutingStateFromEnvelope(envelope *crypto.SignedEnvelope) (*RoutingState, e return state, nil } +// ToSignedEnvelope wraps a Marshal'd RoutingState record in a SignedEnvelope using the +// given private signing key. +func (s *RoutingState) ToSignedEnvelope(key crypto.PrivKey) (*crypto.SignedEnvelope, error) { + payload, err := s.Marshal() + if err != nil { + return nil, err + } + return crypto.MakeEnvelope(key, StateEnvelopeDomain, StateEnvelopeTypeHint, payload) +} + // Marshal serializes a RoutingState record to protobuf and returns its byte representation. func (s *RoutingState) Marshal() ([]byte, error) { id, err := s.PeerID.MarshalBinary() @@ -95,6 +122,13 @@ func (s *RoutingState) Multiaddrs() []ma.Multiaddr { return out } +func statelessSeqNo() uint64 { + // use current time in milliseconds as seq number + // nanoseconds would overflow in 2262, but millis gives us + // a few hundred thousand years + return uint64(time.Now().UnixNano() / 1e6) +} + func addrsFromProtobuf(addrs []*pb.RoutingStateRecord_AddressInfo) []*AnnotatedAddr { out := make([]*AnnotatedAddr, 0) for _, addr := range addrs {