diff --git a/examples/multipro/echo.go b/examples/multipro/echo.go index 158a54a8..609f458f 100644 --- a/examples/multipro/echo.go +++ b/examples/multipro/echo.go @@ -12,6 +12,7 @@ import ( "github.com/ipfs/go-ipfs/thirdparty/assert" p2p "github.com/libp2p/go-libp2p/examples/multipro/pb" protobufCodec "github.com/multiformats/go-multicodec/protobuf" + "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" ) // pattern: /protocol-name/request-or-response-message/version @@ -51,13 +52,23 @@ func (e EchoProtocol) onEchoRequest(s inet.Stream) { MessageData: NewMessageData(e.node.ID().String(), data.MessageData.Id, false), Message: data.Message} + // sign the data + signature, err := e.node.signProtoMessage(resp) + if err != nil { + log.Fatal("failed to sign response") + return + } + + // add the signature to the message + resp.MessageData.Sign = string(signature) + s, respErr := e.node.NewStream(context.Background(), s.Conn().RemotePeer(), echoResponse) if respErr != nil { log.Fatal(respErr) return } - ok := sendDataObject(resp, s) + ok := sendProtoMessage(resp, s) if ok { log.Printf("%s: Echo response to %s sent.", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String()) @@ -89,21 +100,30 @@ func (e EchoProtocol) onEchoResponse(s inet.Stream) { e.done <- true } -func (e EchoProtocol) Echo(node *Node) bool { - log.Printf("%s: Sending echo to: %s....", e.node.ID(), node.ID()) +func (e EchoProtocol) Echo(host host.Host) bool { + log.Printf("%s: Sending echo to: %s....", e.node.ID(), host.ID()) // create message data req := &p2p.EchoRequest{ MessageData: NewMessageData(e.node.ID().String(), uuid.New().String(), false), Message: fmt.Sprintf("Echo from %s", e.node.ID())} - s, err := e.node.NewStream(context.Background(), node.ID(), echoRequest) + signature, err := e.node.signProtoMessage(req) + if err != nil { + log.Fatal("failed to sign message") + return false + } + + // add the signature to the message + req.MessageData.Sign = string(signature) + + s, err := e.node.NewStream(context.Background(), host.ID(), echoRequest) if err != nil { log.Fatal(err) return false } - ok := sendDataObject(req, s) + ok := sendProtoMessage(req, s) if !ok { return false @@ -111,6 +131,6 @@ func (e EchoProtocol) Echo(node *Node) bool { // store request so response handler has access to it e.requests[req.MessageData.Id] = req - log.Printf("%s: Echo to: %s was sent. Message Id: %s, Message: %s", e.node.ID(), node.ID(), req.MessageData.Id, req.Message) + log.Printf("%s: Echo to: %s was sent. Message Id: %s, Message: %s", e.node.ID(), host.ID(), req.MessageData.Id, req.Message) return true } diff --git a/examples/multipro/main.go b/examples/multipro/main.go index d6f7a1aa..13d690e5 100644 --- a/examples/multipro/main.go +++ b/examples/multipro/main.go @@ -47,10 +47,10 @@ func main() { log.Printf("This is a conversation between %s and %s\n", h1.ID(), h2.ID()) // send messages using the protocols - h1.Ping(h2) - h2.Ping(h1) - h1.Echo(h2) - h2.Echo(h1) + h1.Ping(h2.Host) + h2.Ping(h1.Host) + h1.Echo(h2.Host) + h2.Echo(h1.Host) // block until all responses have been processed for i := 0; i < 4; i++ { diff --git a/examples/multipro/node.go b/examples/multipro/node.go index 0a10d574..7771e1a4 100644 --- a/examples/multipro/node.go +++ b/examples/multipro/node.go @@ -3,8 +3,19 @@ package main import ( host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer" + "github.com/gogo/protobuf/proto" ) +func (n Node) signProtoMessage(message proto.Message) ([]byte, error) { + // sign the data + data, err := proto.Marshal(message) + if err != nil { + return nil, err + } + + return n.signData(data) +} + func (n Node) signData(data []byte) ([]byte, error) { key := n.Peerstore().PrivKey(n.ID()) res, err := key.Sign(data) @@ -17,11 +28,12 @@ func (n Node) verifyData(data []byte, signature []byte, signerHostId peer.ID) bo return res == true && err == nil } -// Node type - implements one or more p2p protocols +// Node type - a host with one or more implemented p2p protocols type Node struct { host.Host // lib-p2p host *PingProtocol // ping protocol impl *EchoProtocol // echo protocol impl + // add other protocols here... } // create a new node with its implemented protocols diff --git a/examples/multipro/ping.go b/examples/multipro/ping.go index eec20668..06d60d05 100644 --- a/examples/multipro/ping.go +++ b/examples/multipro/ping.go @@ -11,6 +11,7 @@ import ( uuid "github.com/google/uuid" p2p "github.com/libp2p/go-libp2p/examples/multipro/pb" protobufCodec "github.com/multiformats/go-multicodec/protobuf" + "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" ) // pattern: /protocol-name/request-or-response-message/version @@ -45,18 +46,29 @@ func (p PingProtocol) onPingRequest(s inet.Stream) { log.Printf("%s: Received ping request from %s. Message: %s", s.Conn().LocalPeer(), s.Conn().RemotePeer(), data.Message) - // send response to sender + // generate response message log.Printf("%s: Sending ping response to %s. Message id: %s...", s.Conn().LocalPeer(), s.Conn().RemotePeer(), data.MessageData.Id) resp := &p2p.PingResponse{MessageData: NewMessageData(p.node.ID().String(), data.MessageData.Id, false), Message: fmt.Sprintf("Ping response from %s", p.node.ID())} + // sign the data + signature, err := p.node.signProtoMessage(resp) + if err != nil { + log.Fatal("failed to sign response") + return + } + + // add the signature to the message + resp.MessageData.Sign = string(signature) + + // send the response s, respErr := p.node.NewStream(context.Background(), s.Conn().RemotePeer(), pingResponse) if respErr != nil { log.Fatal(respErr) return } - ok := sendDataObject(resp, s) + ok := sendProtoMessage(resp, s) if ok { log.Printf("%s: Ping response to %s sent.", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String()) @@ -86,20 +98,30 @@ func (p PingProtocol) onPingResponse(s inet.Stream) { p.done <- true } -func (p PingProtocol) Ping(node *Node) bool { - log.Printf("%s: Sending ping to: %s....", p.node.ID(), node.ID()) +func (p PingProtocol) Ping(host host.Host) bool { + log.Printf("%s: Sending ping to: %s....", p.node.ID(), host.ID()) // create message data req := &p2p.PingRequest{MessageData: NewMessageData(p.node.ID().String(), uuid.New().String(), false), Message: fmt.Sprintf("Ping from %s", p.node.ID())} - s, err := p.node.NewStream(context.Background(), node.Host.ID(), pingRequest) + // sign the data + signature, err := p.node.signProtoMessage(req) + if err != nil { + log.Fatal("failed to sign pb data") + return false + } + + // add the signature to the message + req.MessageData.Sign = string(signature) + + s, err := p.node.NewStream(context.Background(), host.ID(), pingRequest) if err != nil { log.Fatal(err) return false } - ok := sendDataObject(req, s) + ok := sendProtoMessage(req, s) if !ok { return false @@ -107,6 +129,6 @@ func (p PingProtocol) Ping(node *Node) bool { // store ref request so response handler has access to it p.requests[req.MessageData.Id] = req - log.Printf("%s: Ping to: %s was sent. Message Id: %s, Message: %s", p.node.ID(), node.ID(), req.MessageData.Id, req.Message) + log.Printf("%s: Ping to: %s was sent. Message Id: %s, Message: %s", p.node.ID(), host.ID(), req.MessageData.Id, req.Message) return true } diff --git a/examples/multipro/protocol.go b/examples/multipro/protocol.go index b2672342..6cf849d4 100644 --- a/examples/multipro/protocol.go +++ b/examples/multipro/protocol.go @@ -9,6 +9,7 @@ import ( "time" //host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" //"bytes" + "github.com/gogo/protobuf/proto" ) // node version @@ -17,7 +18,7 @@ const clientVersion = "go-p2p-node/0.0.1" // helper method - writes a protobuf go data object to a network stream // data - reference of protobuf go data object to send (not the object itself) // s - network stream to write the data to -func sendDataObject(data interface{}, s inet.Stream) bool { +func sendProtoMessage(data proto.Message, s inet.Stream) bool { writer := bufio.NewWriter(s) enc := protobufCodec.Multicodec(nil).Encoder(writer) err := enc.Encode(data)