Merge pull request #108 from libp2p/identify-send-key
identify: send + consume public keys too
This commit is contained in:
commit
2b78e7435f
|
@ -6,6 +6,8 @@ import (
|
|||
|
||||
semver "github.com/coreos/go-semver/semver"
|
||||
ggio "github.com/gogo/protobuf/io"
|
||||
ic "github.com/ipfs/go-libp2p-crypto"
|
||||
peer "github.com/ipfs/go-libp2p-peer"
|
||||
pstore "github.com/ipfs/go-libp2p-peerstore"
|
||||
ma "github.com/jbenet/go-multiaddr"
|
||||
host "github.com/libp2p/go-libp2p/p2p/host"
|
||||
|
@ -164,6 +166,18 @@ func (ids *IDService) populateMessage(mes *pb.Identify, c inet.Conn) {
|
|||
}
|
||||
log.Debugf("%s sent listen addrs to %s: %s", c.LocalPeer(), c.RemotePeer(), laddrs)
|
||||
|
||||
// set our public key
|
||||
ownKey := ids.Host.Peerstore().PubKey(ids.Host.ID())
|
||||
if ownKey == nil {
|
||||
log.Errorf("did not have own public key in Peerstore")
|
||||
} else {
|
||||
if kb, err := ownKey.Bytes(); err != nil {
|
||||
log.Errorf("failed to convert key to bytes")
|
||||
} else {
|
||||
mes.PublicKey = kb
|
||||
}
|
||||
}
|
||||
|
||||
// set protocol versions
|
||||
pv := LibP2PVersion
|
||||
av := ClientVersion
|
||||
|
@ -219,6 +233,83 @@ func (ids *IDService) consumeMessage(mes *pb.Identify, c inet.Conn) {
|
|||
|
||||
ids.Host.Peerstore().Put(p, "ProtocolVersion", pv)
|
||||
ids.Host.Peerstore().Put(p, "AgentVersion", av)
|
||||
|
||||
// get the key from the other side. we may not have it (no-auth transport)
|
||||
ids.consumeReceivedPubKey(c, mes.PublicKey)
|
||||
}
|
||||
|
||||
func (ids *IDService) consumeReceivedPubKey(c inet.Conn, kb []byte) {
|
||||
lp := c.LocalPeer()
|
||||
rp := c.RemotePeer()
|
||||
|
||||
if kb == nil {
|
||||
log.Debugf("%s did not receive public key for remote peer: %s", lp, rp)
|
||||
return
|
||||
}
|
||||
|
||||
newKey, err := ic.UnmarshalPublicKey(kb)
|
||||
if err != nil {
|
||||
log.Errorf("%s cannot unmarshal key from remote peer: %s", lp, rp)
|
||||
return
|
||||
}
|
||||
|
||||
// verify key matches peer.ID
|
||||
np, err := peer.IDFromPublicKey(newKey)
|
||||
if err != nil {
|
||||
log.Debugf("%s cannot get peer.ID from key of remote peer: %s, %s", lp, rp, err)
|
||||
return
|
||||
}
|
||||
|
||||
if np != rp {
|
||||
// if the newKey's peer.ID does not match known peer.ID...
|
||||
|
||||
if rp == "" && np != "" {
|
||||
// if local peerid is empty, then use the new, sent key.
|
||||
err := ids.Host.Peerstore().AddPubKey(rp, newKey)
|
||||
if err != nil {
|
||||
log.Debugf("%s could not add key for %s to peerstore: %s", lp, rp, err)
|
||||
}
|
||||
|
||||
} else {
|
||||
// we have a local peer.ID and it does not match the sent key... error.
|
||||
log.Errorf("%s received key for remote peer %s mismatch: %s", lp, rp, np)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
currKey := ids.Host.Peerstore().PubKey(rp)
|
||||
if currKey == nil {
|
||||
// no key? no auth transport. set this one.
|
||||
err := ids.Host.Peerstore().AddPubKey(rp, newKey)
|
||||
if err != nil {
|
||||
log.Debugf("%s could not add key for %s to peerstore: %s", lp, rp, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ok, we have a local key, we should verify they match.
|
||||
if currKey.Equals(newKey) {
|
||||
return // ok great. we're done.
|
||||
}
|
||||
|
||||
// weird, got a different key... but the different key MATCHES the peer.ID.
|
||||
// this odd. let's log error and investigate. this should basically never happen
|
||||
// and it means we have something funky going on and possibly a bug.
|
||||
log.Errorf("%s identify got a different key for: %s", lp, rp)
|
||||
|
||||
// okay... does ours NOT match the remote peer.ID?
|
||||
cp, err := peer.IDFromPublicKey(currKey)
|
||||
if err != nil {
|
||||
log.Errorf("%s cannot get peer.ID from local key of remote peer: %s, %s", lp, rp, err)
|
||||
return
|
||||
}
|
||||
if cp != rp {
|
||||
log.Errorf("%s local key for remote peer %s yields different peer.ID: %s", lp, rp, cp)
|
||||
return
|
||||
}
|
||||
|
||||
// okay... curr key DOES NOT match new key. both match peer.ID. wat?
|
||||
log.Errorf("%s local key and received key for %s do not match, but match peer.ID", lp, rp)
|
||||
}
|
||||
|
||||
// HasConsistentTransport returns true if the address 'a' shares a
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
ic "github.com/ipfs/go-libp2p-crypto"
|
||||
peer "github.com/ipfs/go-libp2p-peer"
|
||||
host "github.com/libp2p/go-libp2p/p2p/host"
|
||||
identify "github.com/libp2p/go-libp2p/p2p/protocol/identify"
|
||||
|
@ -41,6 +42,7 @@ func subtestIDService(t *testing.T, postDialWait time.Duration) {
|
|||
t.Log("test peer1 has peer2 addrs correctly")
|
||||
testKnowsAddrs(t, h1, h2p, h2.Peerstore().Addrs(h2p)) // has them
|
||||
testHasProtocolVersions(t, h1, h2p)
|
||||
testHasPublicKey(t, h1, h2p, h2.Peerstore().PubKey(h2p)) // h1 should have h2's public key
|
||||
|
||||
// now, this wait we do have to do. it's the wait for the Listening side
|
||||
// to be done identifying the connection.
|
||||
|
@ -57,6 +59,7 @@ func subtestIDService(t *testing.T, postDialWait time.Duration) {
|
|||
t.Log("test peer2 has peer1 addrs correctly")
|
||||
testKnowsAddrs(t, h2, h1p, addrs) // has them
|
||||
testHasProtocolVersions(t, h2, h1p)
|
||||
testHasPublicKey(t, h2, h1p, h1.Peerstore().PubKey(h1p)) // h1 should have h2's public key
|
||||
}
|
||||
|
||||
func testKnowsAddrs(t *testing.T, h host.Host, p peer.ID, expected []ma.Multiaddr) {
|
||||
|
@ -95,6 +98,25 @@ func testHasProtocolVersions(t *testing.T, h host.Host, p peer.ID) {
|
|||
}
|
||||
}
|
||||
|
||||
func testHasPublicKey(t *testing.T, h host.Host, p peer.ID, shouldBe ic.PubKey) {
|
||||
k := h.Peerstore().PubKey(p)
|
||||
if k == nil {
|
||||
t.Error("no public key")
|
||||
return
|
||||
}
|
||||
if !k.Equals(shouldBe) {
|
||||
t.Error("key mismatch")
|
||||
return
|
||||
}
|
||||
|
||||
p2, err := peer.IDFromPublicKey(k)
|
||||
if err != nil {
|
||||
t.Error("could not make key")
|
||||
} else if p != p2 {
|
||||
t.Error("key does not match peerid")
|
||||
}
|
||||
}
|
||||
|
||||
// TestIDServiceWait gives the ID service 100ms to finish after dialing
|
||||
// this is becasue it used to be concurrent. Now, Dial wait till the
|
||||
// id service is done.
|
||||
|
|
Loading…
Reference in New Issue