diff --git a/README.md b/README.md
index 1e60e3979446ee639aeea7ce072611ab8c009dbb..b44b25dec3513099e66976052fbdadc8c50d49f1 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+
diff --git a/examples/multipro/LICENSE b/examples/multipro/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..c7386b3c940d8aa7baea2dd6fec2908fed562b89
--- /dev/null
+++ b/examples/multipro/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Juan Batiz-Benet
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/examples/multipro/README.md b/examples/multipro/README.md
index 15d4e02a74769321bd4a173ea37941c08b866e35..343ac0c61b1ecb76181fcba44a4a5154f1afd8c3 100644
--- a/examples/multipro/README.md
+++ b/examples/multipro/README.md
@@ -30,8 +30,14 @@ From `multipro` base source folder:
## Details
The example creates two LibP2P Hosts supporting 2 protocols: ping and echo.
+
Each protocol consists RPC-style requests and respones and each request and response is a typed protobufs message (and a go data object).
+
This is a different pattern then defining a whole p2p protocol as 1 protobuf message with lots of optional fields (as can be observed in various p2p-lib protocols using protobufs such as dht).
+
The example shows how to match async received responses with their requests. This is useful when processing a response requires access to the request data.
+## Author
+
+@avive
diff --git a/examples/multipro/node.go b/examples/multipro/node.go
index 39c9d67d2a02021cbc87da573e742584f8bf6fff..0d6357081c5bdbc483e376114d1643d1845b789f 100644
--- a/examples/multipro/node.go
+++ b/examples/multipro/node.go
@@ -5,6 +5,8 @@ import (
"github.com/gogo/protobuf/proto"
host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
+
+ crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
"log"
)
@@ -46,7 +48,7 @@ func (n *Node) authenticateMessage(message proto.Message, data *p2p.MessageData)
return false
}
- return n.verifyData(bin, []byte(sign), peerId, []byte(data.NodePubKey))
+ return n.verifyData(bin, []byte(sign), peerId, data.NodePubKey)
}
func (n *Node) signProtoMessage(message proto.Message) ([]byte, error) {
@@ -66,20 +68,31 @@ func (n *Node) signData(data []byte) ([]byte, error) {
// precondition: we have info about the signer peer in the local peer store
func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyData []byte) bool {
- // todo: restore pub key from message and not from the local peer store and use it
- key := n.Peerstore().PubKey(peerId)
+ key, err := crypto.UnmarshalPublicKey(pubKeyData)
+
+ if err != nil {
+ log.Println(err, "Failed to extract key from message key data")
+ return false
+ }
+
+ // extract node id from the provided public key
+ idFromKey, err := peer.IDFromPublicKey(key)
- //todo: fix this
- //key, err := key.UnmarshalPublicKey(pubKeyData)
+ if err != nil {
+ log.Println(err, "Failed to extract peer id from public key")
+ return false
+ }
- if key == nil {
- log.Println("Failed to find public key for %s in local peer store.", peerId.String())
+ // verify that message author node id matches the provided public key
+ if idFromKey != peerId {
+ log.Println(err, "Node id and provided public key mismatch")
return false
}
res, err := key.Verify(data, signature)
+
if err != nil {
- log.Println ("Error authenticating data")
+ log.Println(err, "Error authenticating data")
return false
}
diff --git a/examples/multipro/protocol.go b/examples/multipro/protocol.go
index 0b57d89859e38b3512359e33909d55aa7fc061e7..6fe6f60804a75ae238c35c2655c80b890157b37d 100644
--- a/examples/multipro/protocol.go
+++ b/examples/multipro/protocol.go
@@ -33,7 +33,8 @@ func sendProtoMessage(data proto.Message, s inet.Stream) bool {
// messageId - unique for requests, copied from request for responses
func NewMessageData(node *Node, messageId string, gossip bool) *p2p.MessageData {
- // Create protobufs bin data for a public key
+ // Add protobufs bin data for message author public key
+ // this is useful for authenticating messages forwarded by a node authored by another node
nodePubKey, err := node.Peerstore().PubKey(node.ID()).Bytes()
if err != nil {