diff --git a/blocks/blockstore/write_cache_test.go b/blocks/blockstore/write_cache_test.go index 2be86590314..c2175a1fc70 100644 --- a/blocks/blockstore/write_cache_test.go +++ b/blocks/blockstore/write_cache_test.go @@ -1,10 +1,11 @@ package blockstore import ( + "testing" + ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" syncds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync" "github.com/jbenet/go-ipfs/blocks" - "testing" ) func TestReturnsErrorWhenSizeNegative(t *testing.T) { diff --git a/core/commands/swarm.go b/core/commands/swarm.go index 743f4690486..1d43fa0784e 100644 --- a/core/commands/swarm.go +++ b/core/commands/swarm.go @@ -149,8 +149,12 @@ func splitAddresses(addrs []string) (maddrs []ma.Multiaddr, pids []peer.ID, err if err != nil { return nil, nil, cmds.ClientError("invalid peer address: " + err.Error()) } + id, err := peer.DecodePrettyID(path.Base(addr)) + if err != nil { + return nil, nil, err + } + pids[i] = id maddrs[i] = a - pids[i] = peer.DecodePrettyID(path.Base(addr)) } return } @@ -165,7 +169,7 @@ func peersWithAddresses(ps peer.Peerstore, addrs []string) ([]peer.Peer, error) peers := make([]peer.Peer, len(pids)) for i, pid := range pids { - p, err := ps.Get(pid) + p, err := ps.FindOrCreate(pid) if err != nil { return nil, err } diff --git a/core/core.go b/core/core.go index 007c01b8087..0f1b2b1e2bd 100644 --- a/core/core.go +++ b/core/core.go @@ -223,7 +223,7 @@ func initIdentity(cfg *config.Identity, peers peer.Peerstore, online bool) (peer // get peer from peerstore (so it is constructed there) id := peer.ID(b58.Decode(cfg.PeerID)) - self, err := peers.Get(id) + self, err := peers.FindOrCreate(id) if err != nil { return nil, err } @@ -265,7 +265,12 @@ func initConnections(ctx context.Context, cfg *config.Config, pstore peer.Peerst } // setup peer - npeer, err := pstore.Get(peer.DecodePrettyID(p.PeerID)) + id, err := peer.DecodePrettyID(p.PeerID) + if err != nil { + log.Criticalf("Bootstrapping error: %v", err) + continue + } + npeer, err := pstore.FindOrCreate(id) if err != nil { log.Criticalf("Bootstrapping error: %v", err) continue diff --git a/core/mock.go b/core/mock.go index ab1149787ce..7f6faa0b40f 100644 --- a/core/mock.go +++ b/core/mock.go @@ -25,12 +25,13 @@ func NewMockNode() (*IpfsNode, error) { return nil, err } - p, err := peer.WithKeyPair(sk, pk) + nd.Peerstore = peer.NewPeerstore() + + p, err := nd.Peerstore.WithKeyPair(sk, pk) if err != nil { return nil, err } - nd.Peerstore = peer.NewPeerstore() nd.Identity, err = nd.Peerstore.Add(p) if err != nil { return nil, err diff --git a/crypto/spipe/handshake.go b/crypto/spipe/handshake.go index 7a546156018..f0c581b9620 100644 --- a/crypto/spipe/handshake.go +++ b/crypto/spipe/handshake.go @@ -14,9 +14,10 @@ import ( "crypto/sha1" "crypto/sha256" "crypto/sha512" - bfish "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish" "hash" + bfish "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.crypto/blowfish" + proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" ci "github.com/jbenet/go-ipfs/crypto" @@ -368,7 +369,7 @@ func getOrConstructPeer(peers peer.Peerstore, rpk ci.PubKey) (peer.Peer, error) return nil, err } - npeer, err := peers.Get(rid) + npeer, err := peers.FindOrCreate(rid) if err != nil { return nil, err // unexpected error happened. } diff --git a/crypto/spipe/spipe_test.go b/crypto/spipe/spipe_test.go index 716b73311b3..56ccbea08cf 100644 --- a/crypto/spipe/spipe_test.go +++ b/crypto/spipe/spipe_test.go @@ -9,6 +9,7 @@ import ( "github.com/jbenet/go-ipfs/peer" "github.com/jbenet/go-ipfs/util" "github.com/jbenet/go-ipfs/util/pipes" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) func getPeer(tb testing.TB) peer.Peer { @@ -17,7 +18,7 @@ func getPeer(tb testing.TB) peer.Peer { tb.Fatal(err) } - p, err := peer.WithKeyPair(privk, pubk) + p, err := testutil.NewPeerWithKeyPair(privk, pubk) if err != nil { tb.Fatal(err) } diff --git a/exchange/bitswap/bitswap_test.go b/exchange/bitswap/bitswap_test.go index d26a8ffc9cf..4d0b5e59d1d 100644 --- a/exchange/bitswap/bitswap_test.go +++ b/exchange/bitswap/bitswap_test.go @@ -10,8 +10,8 @@ import ( blocks "github.com/jbenet/go-ipfs/blocks" blocksutil "github.com/jbenet/go-ipfs/blocks/blocksutil" tn "github.com/jbenet/go-ipfs/exchange/bitswap/testnet" - peer "github.com/jbenet/go-ipfs/peer" mock "github.com/jbenet/go-ipfs/routing/mock" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) func TestClose(t *testing.T) { @@ -53,7 +53,7 @@ func TestProviderForKeyButNetworkCannotFind(t *testing.T) { g := NewSessionGenerator(net, rs) block := blocks.NewBlock([]byte("block")) - rs.Announce(peer.WithIDString("testing"), block.Key()) // but not on network + rs.Announce(testutil.NewPeerWithIDString("testing"), block.Key()) // but not on network solo := g.Next() diff --git a/exchange/bitswap/message/message_test.go b/exchange/bitswap/message/message_test.go index de64b79259f..5fe98634c40 100644 --- a/exchange/bitswap/message/message_test.go +++ b/exchange/bitswap/message/message_test.go @@ -6,8 +6,8 @@ import ( blocks "github.com/jbenet/go-ipfs/blocks" pb "github.com/jbenet/go-ipfs/exchange/bitswap/message/internal/pb" - peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) func TestAppendWanted(t *testing.T) { @@ -89,7 +89,7 @@ func TestCopyProtoByValue(t *testing.T) { func TestToNetMethodSetsPeer(t *testing.T) { m := New() - p := peer.WithIDString("X") + p := testutil.NewPeerWithIDString("X") netmsg, err := m.ToNet(p) if err != nil { t.Fatal(err) @@ -107,7 +107,7 @@ func TestToNetFromNetPreservesWantList(t *testing.T) { original.AddWanted(u.Key("T")) original.AddWanted(u.Key("F")) - p := peer.WithIDString("X") + p := testutil.NewPeerWithIDString("X") netmsg, err := original.ToNet(p) if err != nil { t.Fatal(err) @@ -138,7 +138,7 @@ func TestToAndFromNetMessage(t *testing.T) { original.AddBlock(blocks.NewBlock([]byte("F"))) original.AddBlock(blocks.NewBlock([]byte("M"))) - p := peer.WithIDString("X") + p := testutil.NewPeerWithIDString("X") netmsg, err := original.ToNet(p) if err != nil { t.Fatal(err) diff --git a/exchange/bitswap/strategy/strategy_test.go b/exchange/bitswap/strategy/strategy_test.go index d07af601bf4..e063dff688e 100644 --- a/exchange/bitswap/strategy/strategy_test.go +++ b/exchange/bitswap/strategy/strategy_test.go @@ -7,6 +7,7 @@ import ( blocks "github.com/jbenet/go-ipfs/blocks" message "github.com/jbenet/go-ipfs/exchange/bitswap/message" peer "github.com/jbenet/go-ipfs/peer" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) type peerAndStrategist struct { @@ -16,7 +17,7 @@ type peerAndStrategist struct { func newPeerAndStrategist(idStr string) peerAndStrategist { return peerAndStrategist{ - Peer: peer.WithIDString(idStr), + Peer: testutil.NewPeerWithIDString(idStr), Strategy: New(true), } } diff --git a/exchange/bitswap/testnet/network_test.go b/exchange/bitswap/testnet/network_test.go index 6f57aad50ad..0bfb0cb1ee4 100644 --- a/exchange/bitswap/testnet/network_test.go +++ b/exchange/bitswap/testnet/network_test.go @@ -9,6 +9,7 @@ import ( bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network" peer "github.com/jbenet/go-ipfs/peer" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) func TestSendRequestToCooperativePeer(t *testing.T) { @@ -18,8 +19,8 @@ func TestSendRequestToCooperativePeer(t *testing.T) { t.Log("Get two network adapters") - initiator := net.Adapter(peer.WithIDString("initiator")) - recipient := net.Adapter(peer.WithID(idOfRecipient)) + initiator := net.Adapter(testutil.NewPeerWithIDString("initiator")) + recipient := net.Adapter(testutil.NewPeerWithID(idOfRecipient)) expectedStr := "response from recipient" recipient.SetDelegate(lambda(func( @@ -43,7 +44,7 @@ func TestSendRequestToCooperativePeer(t *testing.T) { message := bsmsg.New() message.AddBlock(blocks.NewBlock([]byte("data"))) response, err := initiator.SendRequest( - context.Background(), peer.WithID(idOfRecipient), message) + context.Background(), testutil.NewPeerWithID(idOfRecipient), message) if err != nil { t.Fatal(err) } @@ -61,8 +62,8 @@ func TestSendRequestToCooperativePeer(t *testing.T) { func TestSendMessageAsyncButWaitForResponse(t *testing.T) { net := VirtualNetwork() idOfResponder := []byte("responder") - waiter := net.Adapter(peer.WithIDString("waiter")) - responder := net.Adapter(peer.WithID(idOfResponder)) + waiter := net.Adapter(testutil.NewPeerWithIDString("waiter")) + responder := net.Adapter(testutil.NewPeerWithID(idOfResponder)) var wg sync.WaitGroup @@ -107,7 +108,7 @@ func TestSendMessageAsyncButWaitForResponse(t *testing.T) { messageSentAsync := bsmsg.New() messageSentAsync.AddBlock(blocks.NewBlock([]byte("data"))) errSending := waiter.SendMessage( - context.Background(), peer.WithID(idOfResponder), messageSentAsync) + context.Background(), testutil.NewPeerWithID(idOfResponder), messageSentAsync) if errSending != nil { t.Fatal(errSending) } diff --git a/exchange/bitswap/testutils.go b/exchange/bitswap/testutils.go index 402a5b1d26b..7f8ef85469d 100644 --- a/exchange/bitswap/testutils.go +++ b/exchange/bitswap/testutils.go @@ -16,6 +16,7 @@ func NewSessionGenerator( return SessionGenerator{ net: net, rs: rs, + ps: peer.NewPeerstore(), seq: 0, } } @@ -24,11 +25,12 @@ type SessionGenerator struct { seq int net tn.Network rs mock.RoutingServer + ps peer.Peerstore } func (g *SessionGenerator) Next() Instance { g.seq++ - return session(g.net, g.rs, []byte(string(g.seq))) + return session(g.net, g.rs, g.ps, []byte(string(g.seq))) } func (g *SessionGenerator) Instances(n int) []Instance { @@ -51,8 +53,8 @@ type Instance struct { // NB: It's easy make mistakes by providing the same peer ID to two different // sessions. To safeguard, use the SessionGenerator to generate sessions. It's // just a much better idea. -func session(net tn.Network, rs mock.RoutingServer, id peer.ID) Instance { - p := peer.WithID(id) +func session(net tn.Network, rs mock.RoutingServer, ps peer.Peerstore, id peer.ID) Instance { + p := ps.WithID(id) adapter := net.Adapter(p) htc := rs.Client(p) diff --git a/importer/importer_test.go b/importer/importer_test.go index 21af40670fe..fca8e3d61c9 100644 --- a/importer/importer_test.go +++ b/importer/importer_test.go @@ -12,7 +12,7 @@ import ( "github.com/jbenet/go-ipfs/importer/chunk" uio "github.com/jbenet/go-ipfs/unixfs/io" u "github.com/jbenet/go-ipfs/util" - "github.com/jbenet/go-ipfs/util/testutil" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) // NOTE: diff --git a/namesys/resolve_test.go b/namesys/resolve_test.go index d7d49c5a64b..eef5e68258c 100644 --- a/namesys/resolve_test.go +++ b/namesys/resolve_test.go @@ -5,13 +5,13 @@ import ( ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" ci "github.com/jbenet/go-ipfs/crypto" - "github.com/jbenet/go-ipfs/peer" mock "github.com/jbenet/go-ipfs/routing/mock" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) func TestRoutingResolve(t *testing.T) { - local := peer.WithIDString("testID") + local := testutil.NewPeerWithIDString("testID") lds := ds.NewMapDatastore() d := mock.NewMockRouter(local, lds) diff --git a/net/conn/dial_test.go b/net/conn/dial_test.go index f3d3808d0b5..c98ac77ea20 100644 --- a/net/conn/dial_test.go +++ b/net/conn/dial_test.go @@ -5,6 +5,7 @@ import ( ci "github.com/jbenet/go-ipfs/crypto" peer "github.com/jbenet/go-ipfs/peer" + testutil "github.com/jbenet/go-ipfs/util/testutil" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" @@ -21,7 +22,7 @@ func setupPeer(addr string) (peer.Peer, error) { return nil, err } - p, err := peer.WithKeyPair(sk, pk) + p, err := testutil.NewPeerWithKeyPair(sk, pk) if err != nil { return nil, err } diff --git a/net/mux/mux_test.go b/net/mux/mux_test.go index d445ff77901..7401541c483 100644 --- a/net/mux/mux_test.go +++ b/net/mux/mux_test.go @@ -11,6 +11,7 @@ import ( msg "github.com/jbenet/go-ipfs/net/message" pb "github.com/jbenet/go-ipfs/net/mux/internal/pb" peer "github.com/jbenet/go-ipfs/peer" + testutil "github.com/jbenet/go-ipfs/util/testutil" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ) @@ -30,7 +31,7 @@ func newPeer(t *testing.T, id string) peer.Peer { return nil } - return peer.WithID(peer.ID(mh)) + return testutil.NewPeerWithID(peer.ID(mh)) } func testMsg(t *testing.T, m msg.NetMessage, data []byte) { diff --git a/net/service/service_test.go b/net/service/service_test.go index 7152289aafc..798400ee0cb 100644 --- a/net/service/service_test.go +++ b/net/service/service_test.go @@ -7,6 +7,7 @@ import ( msg "github.com/jbenet/go-ipfs/net/message" peer "github.com/jbenet/go-ipfs/peer" + testutil "github.com/jbenet/go-ipfs/util/testutil" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" @@ -32,7 +33,7 @@ func newPeer(t *testing.T, id string) peer.Peer { return nil } - return peer.WithID(peer.ID(mh)) + return testutil.NewPeerWithID(peer.ID(mh)) } func TestServiceHandler(t *testing.T) { diff --git a/net/swarm/simul_test.go b/net/swarm/simul_test.go index 114a4dcbfcc..8db207f25af 100644 --- a/net/swarm/simul_test.go +++ b/net/swarm/simul_test.go @@ -6,6 +6,7 @@ import ( "testing" peer "github.com/jbenet/go-ipfs/peer" + "github.com/jbenet/go-ipfs/util/testutil" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ) @@ -28,7 +29,7 @@ func TestSimultOpen(t *testing.T) { var wg sync.WaitGroup connect := func(s *Swarm, dst peer.Peer) { // copy for other peer - cp := peer.WithID(dst.ID()) + cp := testutil.NewPeerWithID(dst.ID()) cp.AddAddress(dst.Addresses()[0]) if _, err := s.Dial(cp); err != nil { diff --git a/net/swarm/swarm_test.go b/net/swarm/swarm_test.go index 4d948831741..d3014b81ab5 100644 --- a/net/swarm/swarm_test.go +++ b/net/swarm/swarm_test.go @@ -10,6 +10,7 @@ import ( msg "github.com/jbenet/go-ipfs/net/message" peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" @@ -43,7 +44,7 @@ func setupPeer(t *testing.T, addr string) peer.Peer { t.Fatal(err) } - p, err := peer.WithKeyPair(sk, pk) + p, err := testutil.NewPeerWithKeyPair(sk, pk) if err != nil { t.Fatal(err) } @@ -84,7 +85,7 @@ func SubtestSwarm(t *testing.T, addrs []string, MsgNum int) { connect := func(s *Swarm, dst peer.Peer) { // copy for other peer - cp, err := s.peers.Get(dst.ID()) + cp, err := s.peers.FindOrCreate(dst.ID()) if err != nil { t.Fatal(err) } diff --git a/peer/peer.go b/peer/peer.go index fcb8d16cf7f..8ba003fc6a6 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -37,8 +37,12 @@ func (id ID) Pretty() string { } // DecodePrettyID returns a b58-encoded string of the ID -func DecodePrettyID(s string) ID { - return b58.Decode(s) +func DecodePrettyID(s string) (ID, error) { + m, err := mh.FromB58String(s) + if err != nil { + return nil, err + } + return ID(m), err } // IDFromPubKey retrieves a Public Key from the peer given by pk @@ -390,34 +394,3 @@ func (p *peer) SetVersions(agent, protocol string) { p.agentVersion = agent p.protocolVersion = protocol } - -// WithKeyPair returns a Peer object with given keys. -func WithKeyPair(sk ic.PrivKey, pk ic.PubKey) (Peer, error) { - if sk == nil && pk == nil { - return nil, fmt.Errorf("PeerWithKeyPair nil keys") - } - - pk2 := sk.GetPublic() - if pk == nil { - pk = pk2 - } else if !pk.Equals(pk2) { - return nil, fmt.Errorf("key mismatch. pubkey is not privkey's pubkey") - } - - pkid, err := IDFromPubKey(pk) - if err != nil { - return nil, fmt.Errorf("Failed to hash public key: %v", err) - } - - return &peer{id: pkid, pubKey: pk, privKey: sk}, nil -} - -// WithID constructs a peer with given ID. -func WithID(id ID) Peer { - return &peer{id: id} -} - -// WithIDString constructs a peer with given ID (string). -func WithIDString(id string) Peer { - return WithID(ID(id)) -} diff --git a/peer/peer_test.go b/peer/peer_test.go index 4a7aad9e80b..7224882fc42 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -27,7 +27,7 @@ func TestNetAddress(t *testing.T) { return } - p := WithID(ID(mh)) + p := NewPeerstore().WithID(ID(mh)) p.AddAddress(tcp) p.AddAddress(udp) p.AddAddress(tcp) @@ -48,7 +48,7 @@ func TestNetAddress(t *testing.T) { } func TestStringMethodWithSmallId(t *testing.T) { - p := WithID([]byte(string(0))) + p := NewPeerstore().WithID([]byte(string(0))) p1, ok := p.(*peer) if !ok { t.Fatal("WithID doesn't return a peer") diff --git a/peer/peerstore.go b/peer/peerstore.go index dcdfd95d15d..db66c90dfa7 100644 --- a/peer/peerstore.go +++ b/peer/peerstore.go @@ -1,52 +1,47 @@ package peer import ( - "errors" "sync" + ic "github.com/jbenet/go-ipfs/crypto" u "github.com/jbenet/go-ipfs/util" - - ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" + errors "github.com/jbenet/go-ipfs/util/debugerror" ) // Peerstore provides a threadsafe collection for peers. type Peerstore interface { - Get(ID) (Peer, error) + FindOrCreate(ID) (Peer, error) Add(Peer) (Peer, error) Delete(ID) error All() (*Map, error) + + WithKeyPair(sk ic.PrivKey, pk ic.PubKey) (Peer, error) + WithID(id ID) Peer + WithIDString(id string) Peer } type peerstore struct { sync.RWMutex - peers ds.Datastore + data map[string]Peer // key is string(ID) } // NewPeerstore creates a threadsafe collection of peers. func NewPeerstore() Peerstore { return &peerstore{ - peers: ds.NewMapDatastore(), + data: make(map[string]Peer), } } -func (p *peerstore) Get(i ID) (Peer, error) { - p.Lock() - defer p.Unlock() +func (ps *peerstore) FindOrCreate(i ID) (Peer, error) { + ps.Lock() + defer ps.Unlock() if i == nil { panic("wat") } - k := u.Key(i).DsKey() - val, err := p.peers.Get(k) - switch err { - - // some other datastore error - default: - return nil, err - - // not found, construct it ourselves, add it to datastore, and return. - case ds.ErrNotFound: + p, ok := ps.data[i.String()] + if !ok { // not found, construct it ourselves, add it to datastore, and return. // TODO(brian) kinda dangerous, no? If ID is invalid and doesn't // correspond to an actual valid peer ID, this peerstore will return an @@ -57,84 +52,81 @@ func (p *peerstore) Get(i ID) (Peer, error) { // // Potential bad case: Suppose values arrive from untrusted providers // in the DHT. - - peer := &peer{id: i} - if err := p.peers.Put(k, peer); err != nil { - return nil, err - } - return peer, nil + p = &peer{id: i} + ps.data[i.String()] = p + } // no error, got it back fine - case nil: - peer, ok := val.(*peer) - if !ok { - return nil, errors.New("stored value was not a Peer") - } - return peer, nil - } + return p, nil } func (p *peerstore) Add(peer Peer) (Peer, error) { p.Lock() defer p.Unlock() - k := peer.Key().DsKey() - val, err := p.peers.Get(k) - switch err { - // some other datastore error - default: - return nil, err - - // not found? just add and return. - case ds.ErrNotFound: - err := p.peers.Put(k, peer) - return peer, err - - // no error, already here. - case nil: - peer2, ok := val.(Peer) - if !ok { - return nil, errors.New("stored value was not a Peer") - } - - if peer == peer2 { - return peer, nil - } - - // must do some merging. - peer2.Update(peer) - return peer2, nil + existing, ok := p.data[peer.Key().String()] + if !ok { // not found? just add and return. + p.data[peer.Key().String()] = peer + return peer, nil + } + // already here. + if peer == existing { + return peer, nil } + existing.Update(peer) // must do some merging. + return existing, nil } func (p *peerstore) Delete(i ID) error { p.Lock() defer p.Unlock() - k := u.Key(i).DsKey() - return p.peers.Delete(k) + delete(p.data, i.String()) + return nil } func (p *peerstore) All() (*Map, error) { - p.RLock() - defer p.RUnlock() + p.Lock() + defer p.Unlock() - l, err := p.peers.KeyList() - if err != nil { - return nil, err + ps := Map{} + for k, v := range p.data { + ps[u.Key(k)] = v + } + return &ps, nil +} + +// WithKeyPair returns a Peer object with given keys. +func (ps *peerstore) WithKeyPair(sk ic.PrivKey, pk ic.PubKey) (Peer, error) { + if sk == nil && pk == nil { + return nil, errors.Errorf("PeerWithKeyPair nil keys") + } + + pk2 := sk.GetPublic() + if pk == nil { + pk = pk2 + } else if !pk.Equals(pk2) { + return nil, errors.Errorf("key mismatch. pubkey is not privkey's pubkey") } - ps := &Map{} - for _, k := range l { - val, err := p.peers.Get(k) - if err != nil { - continue - } - - pval, ok := val.(*peer) - if ok { - (*ps)[pval.Key()] = pval - } + pkid, err := IDFromPubKey(pk) + if err != nil { + return nil, errors.Errorf("Failed to hash public key: %v", err) } - return ps, nil + + p := &peer{id: pkid, pubKey: pk, privKey: sk} + ps.Add(p) + return p, nil +} + +// WithID constructs a peer with given ID. +func (ps *peerstore) WithID(id ID) Peer { + p := &peer{id: id} + ps.Add(p) + return p +} + +// WithIDString constructs a peer with given ID (string). +func (ps *peerstore) WithIDString(id string) Peer { + return ps.WithID(ID(id)) } diff --git a/peer/peerstore_test.go b/peer/peerstore_test.go index 5068ddc5588..808e48eb143 100644 --- a/peer/peerstore_test.go +++ b/peer/peerstore_test.go @@ -7,13 +7,13 @@ import ( ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" ) -func setupPeer(id string, addr string) (Peer, error) { +func setupPeer(ps Peerstore, id string, addr string) (Peer, error) { tcp, err := ma.NewMultiaddr(addr) if err != nil { return nil, err } - p := WithIDString(id) + p := ps.WithIDString(id) p.AddAddress(tcp) return p, nil } @@ -22,8 +22,8 @@ func TestPeerstore(t *testing.T) { ps := NewPeerstore() - p11, _ := setupPeer("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31", "/ip4/127.0.0.1/tcp/1234") - p21, _ := setupPeer("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a32", "/ip4/127.0.0.1/tcp/2345") + p11, _ := setupPeer(ps, "11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31", "/ip4/127.0.0.1/tcp/1234") + p21, _ := setupPeer(ps, "11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a32", "/ip4/127.0.0.1/tcp/2345") // p31, _ := setupPeer("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", "/ip4/127.0.0.1/tcp/3456") // p41, _ := setupPeer("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a34", "/ip4/127.0.0.1/tcp/4567") @@ -36,7 +36,7 @@ func TestPeerstore(t *testing.T) { t.Error("these should be the same") } - p12, err := ps.Get(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31")) + p12, err := ps.FindOrCreate(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31")) if err != nil { t.Error(err) } @@ -53,7 +53,7 @@ func TestPeerstore(t *testing.T) { t.Error("These should be the same") } - p22, err := ps.Get(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a32")) + p22, err := ps.FindOrCreate(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a32")) if err != nil { t.Error(err) } @@ -62,7 +62,7 @@ func TestPeerstore(t *testing.T) { t.Error(errors.New("peers should be the same")) } - _, err = ps.Get(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")) + _, err = ps.FindOrCreate(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")) if err != nil { t.Error(errors.New("should not have an error here")) } @@ -73,12 +73,12 @@ func TestPeerstore(t *testing.T) { } // reconstruct! - _, err = ps.Get(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31")) + _, err = ps.FindOrCreate(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31")) if err != nil { t.Error(errors.New("should not have an error anyway. reconstruct!")) } - p22, err = ps.Get(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a32")) + p22, err = ps.FindOrCreate(ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a32")) if err != nil { t.Error(err) } diff --git a/peer/queue/queue_test.go b/peer/queue/queue_test.go index 7bc1b42f17d..7cc177ad09a 100644 --- a/peer/queue/queue_test.go +++ b/peer/queue/queue_test.go @@ -8,12 +8,13 @@ import ( peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ) func newPeer(id string) peer.Peer { - return peer.WithIDString(id) + return testutil.NewPeerWithIDString(id) } func TestQueue(t *testing.T) { @@ -69,7 +70,7 @@ func TestQueue(t *testing.T) { func newPeerTime(t time.Time) peer.Peer { s := fmt.Sprintf("hmmm time: %v", t) h := u.Hash([]byte(s)) - return peer.WithID(peer.ID(h)) + return testutil.NewPeerWithID(peer.ID(h)) } func TestSyncQueue(t *testing.T) { diff --git a/repo/logs.go b/repo/logs.go index 0ec141eee3a..b598965001c 100644 --- a/repo/logs.go +++ b/repo/logs.go @@ -1,9 +1,9 @@ package repo import ( + config "github.com/jbenet/go-ipfs/config" util "github.com/jbenet/go-ipfs/util" eventlog "github.com/jbenet/go-ipfs/util/eventlog" - config "github.com/jbenet/go-ipfs/config" ) func ConfigureEventLogger(config config.Logs) error { diff --git a/routing/dht/dht.go b/routing/dht/dht.go index 0277f644bc3..1d9c3a47a92 100644 --- a/routing/dht/dht.go +++ b/routing/dht/dht.go @@ -500,7 +500,7 @@ func (dht *IpfsDHT) betterPeersToQuery(pmes *pb.Message, count int) []peer.Peer // getPeer searches the peerstore for a peer with the given peer ID func (dht *IpfsDHT) getPeer(id peer.ID) (peer.Peer, error) { - p, err := dht.peerstore.Get(id) + p, err := dht.peerstore.FindOrCreate(id) if err != nil { err = fmt.Errorf("Failed to get peer from peerstore: %s", err) log.Error(err) diff --git a/routing/dht/dht_test.go b/routing/dht/dht_test.go index e62145d5b27..30ef2d3aa23 100644 --- a/routing/dht/dht_test.go +++ b/routing/dht/dht_test.go @@ -15,6 +15,7 @@ import ( netservice "github.com/jbenet/go-ipfs/net/service" peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" "fmt" "time" @@ -68,7 +69,7 @@ func makePeer(addr ma.Multiaddr) peer.Peer { if err != nil { panic(err) } - p, err := peer.WithKeyPair(sk, pk) + p, err := testutil.NewPeerWithKeyPair(sk, pk) if err != nil { panic(err) } diff --git a/routing/dht/ext_test.go b/routing/dht/ext_test.go index 791c1066c83..fa536edd496 100644 --- a/routing/dht/ext_test.go +++ b/routing/dht/ext_test.go @@ -7,14 +7,14 @@ import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" - ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" msg "github.com/jbenet/go-ipfs/net/message" mux "github.com/jbenet/go-ipfs/net/mux" peer "github.com/jbenet/go-ipfs/peer" - "github.com/jbenet/go-ipfs/routing" + routing "github.com/jbenet/go-ipfs/routing" pb "github.com/jbenet/go-ipfs/routing/dht/pb" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" "sync" "time" @@ -210,7 +210,7 @@ func TestGetFailures(t *testing.T) { func _randPeer() peer.Peer { id := make(peer.ID, 16) crand.Read(id) - p := peer.WithID(id) + p := testutil.NewPeerWithID(id) return p } diff --git a/routing/dht/providers_test.go b/routing/dht/providers_test.go index 1ae85fbc40d..7d8aaa304b7 100644 --- a/routing/dht/providers_test.go +++ b/routing/dht/providers_test.go @@ -5,6 +5,7 @@ import ( "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ) @@ -14,7 +15,7 @@ func TestProviderManager(t *testing.T) { mid := peer.ID("testing") p := NewProviderManager(ctx, mid) a := u.Key("test") - p.AddProvider(a, peer.WithIDString("testingprovider")) + p.AddProvider(a, testutil.NewPeerWithIDString("testingprovider")) resp := p.GetProviders(ctx, a) if len(resp) != 1 { t.Fatal("Could not retrieve provider.") diff --git a/routing/dht/records.go b/routing/dht/records.go index 0a3b4f4e0ca..0ea455a17eb 100644 --- a/routing/dht/records.go +++ b/routing/dht/records.go @@ -44,7 +44,7 @@ func (dht *IpfsDHT) makePutRecord(key u.Key, value []byte) (*pb.Record, error) { func (dht *IpfsDHT) getPublicKey(pid peer.ID) (ci.PubKey, error) { log.Debug("getPublicKey for: %s", pid) - p, err := dht.peerstore.Get(pid) + p, err := dht.peerstore.FindOrCreate(pid) if err == nil { return p.PubKey(), nil } @@ -67,7 +67,7 @@ func (dht *IpfsDHT) getPublicKey(pid peer.ID) (ci.PubKey, error) { func (dht *IpfsDHT) verifyRecord(r *pb.Record) error { // First, validate the signature - p, err := dht.peerstore.Get(peer.ID(r.GetAuthor())) + p, err := dht.peerstore.FindOrCreate(peer.ID(r.GetAuthor())) if err != nil { return err } diff --git a/routing/mock/routing_test.go b/routing/mock/routing_test.go index 196e00b5e62..536d7b01891 100644 --- a/routing/mock/routing_test.go +++ b/routing/mock/routing_test.go @@ -7,6 +7,7 @@ import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" + testutil "github.com/jbenet/go-ipfs/util/testutil" ) func TestKeyNotFound(t *testing.T) { @@ -20,7 +21,7 @@ func TestKeyNotFound(t *testing.T) { func TestSetAndGet(t *testing.T) { pid := peer.ID([]byte("the peer id")) - p := peer.WithID(pid) + p := testutil.NewPeerWithID(pid) k := u.Key("42") rs := VirtualRoutingServer() err := rs.Announce(p, k) @@ -40,7 +41,7 @@ func TestSetAndGet(t *testing.T) { } func TestClientFindProviders(t *testing.T) { - peer := peer.WithIDString("42") + peer := testutil.NewPeerWithIDString("42") rs := VirtualRoutingServer() client := rs.Client(peer) @@ -79,7 +80,7 @@ func TestClientOverMax(t *testing.T) { k := u.Key("hello") numProvidersForHelloKey := 100 for i := 0; i < numProvidersForHelloKey; i++ { - peer := peer.WithIDString(string(i)) + peer := testutil.NewPeerWithIDString(string(i)) err := rs.Announce(peer, k) if err != nil { t.Fatal(err) @@ -92,7 +93,7 @@ func TestClientOverMax(t *testing.T) { } max := 10 - peer := peer.WithIDString("TODO") + peer := testutil.NewPeerWithIDString("TODO") client := rs.Client(peer) providersFromClient := client.FindProvidersAsync(context.Background(), k, max) @@ -114,7 +115,7 @@ func TestCanceledContext(t *testing.T) { i := 0 go func() { // infinite stream for { - peer := peer.WithIDString(string(i)) + peer := testutil.NewPeerWithIDString(string(i)) err := rs.Announce(peer, k) if err != nil { t.Fatal(err) @@ -123,7 +124,7 @@ func TestCanceledContext(t *testing.T) { } }() - local := peer.WithIDString("peer id doesn't matter") + local := testutil.NewPeerWithIDString("peer id doesn't matter") client := rs.Client(local) t.Log("warning: max is finite so this test is non-deterministic") diff --git a/util/eventlog/entry.go b/util/eventlog/entry.go index ec293f98e99..ef0b3d814b1 100644 --- a/util/eventlog/entry.go +++ b/util/eventlog/entry.go @@ -3,8 +3,8 @@ package eventlog import ( "time" - "github.com/jbenet/go-ipfs/util" "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/maybebtc/logrus" + "github.com/jbenet/go-ipfs/util" ) type entry struct { diff --git a/util/testutil/gen.go b/util/testutil/gen.go index 186740ea982..b652d40d3be 100644 --- a/util/testutil/gen.go +++ b/util/testutil/gen.go @@ -28,5 +28,5 @@ func RandPeer() peer.Peer { id := make([]byte, 16) crand.Read(id) mhid := u.Hash(id) - return peer.WithID(peer.ID(mhid)) + return NewPeerWithID(peer.ID(mhid)) } diff --git a/util/testutil/mock.go b/util/testutil/mock.go new file mode 100644 index 00000000000..488a26044dd --- /dev/null +++ b/util/testutil/mock.go @@ -0,0 +1,19 @@ +package testutil + +import ( + "github.com/jbenet/go-ipfs/peer" + + ic "github.com/jbenet/go-ipfs/crypto" +) + +func NewPeerWithKeyPair(sk ic.PrivKey, pk ic.PubKey) (peer.Peer, error) { + return peer.NewPeerstore().WithKeyPair(sk, pk) +} + +func NewPeerWithID(id peer.ID) peer.Peer { + return peer.NewPeerstore().WithID(id) +} + +func NewPeerWithIDString(id string) peer.Peer { + return peer.NewPeerstore().WithIDString(id) +}