diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index ec8025bc0a44..9d5574e27db1 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -211,7 +211,7 @@ func initConfig(nBitsForKeypair int) (*config.Config, error) { API: "/ip4/127.0.0.1/tcp/5001", }, - Bootstrap: bootstrapPeers, + Bootstrap: config.BootstrapPeerStrings(bootstrapPeers), Datastore: *ds, Logs: *logConfig, Identity: identity, diff --git a/core/bootstrap.go b/core/bootstrap.go index b1b0bfaa4d1e..3de057dacafe 100644 --- a/core/bootstrap.go +++ b/core/bootstrap.go @@ -223,20 +223,17 @@ func bootstrapConnect(ctx context.Context, return nil } -func toPeer(bootstrap config.BootstrapPeer) (p peer.PeerInfo, err error) { - id, err := peer.IDB58Decode(bootstrap.PeerID) - if err != nil { - return - } - maddr, err := ma.NewMultiaddr(bootstrap.Address) - if err != nil { - return - } - p = peer.PeerInfo{ - ID: id, - Addrs: []ma.Multiaddr{maddr}, +func toPeer(bp config.BootstrapPeer) peer.PeerInfo { + // for now, we drop the "ipfs addr" part of the multiaddr. the rest + // of the codebase currently uses addresses without the peerid part. + m := bp.Multiaddr() + s := ma.Split(m) + m = ma.Join(s[len(s)-1]) + + return peer.PeerInfo{ + ID: bp.ID(), + Addrs: []ma.Multiaddr{m}, } - return } func randomSubsetOfPeers(in []peer.PeerInfo, max int) []peer.PeerInfo { diff --git a/core/commands/bootstrap.go b/core/commands/bootstrap.go index c3cfeee7b59b..049ce3ae04c7 100644 --- a/core/commands/bootstrap.go +++ b/core/commands/bootstrap.go @@ -3,6 +3,7 @@ package commands import ( "bytes" "io" + "sort" cmds "github.com/jbenet/go-ipfs/commands" repo "github.com/jbenet/go-ipfs/repo" @@ -19,11 +20,11 @@ import ( // Note: this is here -- and not inside cmd/ipfs/init.go -- because of an // import dependency issue. TODO: move this into a config/default/ package. var DefaultBootstrapAddresses = []string{ - "/ip4/104.131.131.82/tcp/4001/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io - "/ip4/104.236.176.52/tcp/4001/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune (to be neptune.i.ipfs.io) - "/ip4/104.236.179.241/tcp/4001/QmSoLpPVmHKQ4XTPdz8tjDFgdeRFkpV8JgYq8JVJ69RrZm", // pluto (to be pluto.i.ipfs.io) - "/ip4/162.243.248.213/tcp/4001/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus (to be uranus.i.ipfs.io) - "/ip4/128.199.219.111/tcp/4001/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn (to be saturn.i.ipfs.io) + "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io + "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune (to be neptune.i.ipfs.io) + "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLpPVmHKQ4XTPdz8tjDFgdeRFkpV8JgYq8JVJ69RrZm", // pluto (to be pluto.i.ipfs.io) + "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus (to be uranus.i.ipfs.io) + "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn (to be saturn.i.ipfs.io) } type BootstrapOutput struct { @@ -196,7 +197,11 @@ var bootstrapListCmd = &cmds.Command{ return nil, err } - peers := cfg.Bootstrap + peers, err := cfg.BootstrapPeers() + if err != nil { + return nil, err + } + return &BootstrapOutput{peers}, nil }, Type: BootstrapOutput{}, @@ -218,9 +223,10 @@ func bootstrapMarshaler(res cmds.Response) (io.Reader, error) { func bootstrapWritePeers(w io.Writer, prefix string, peers []config.BootstrapPeer) error { - for _, peer := range peers { - s := prefix + peer.Address + "/" + peer.PeerID + "\n" - _, err := w.Write([]byte(s)) + pstrs := config.BootstrapPeerStrings(peers) + sort.Stable(sort.StringSlice(pstrs)) + for _, peer := range pstrs { + _, err := w.Write([]byte(peer + "\n")) if err != nil { return err } @@ -234,14 +240,14 @@ func bootstrapAdd(r repo.Repo, cfg *config.Config, peers []config.BootstrapPeer) for _, peer := range peers { duplicate := false for _, peer2 := range cfg.Bootstrap { - if peer.Address == peer2.Address && peer.PeerID == peer2.PeerID { + if peer.Equal(peer2) { duplicate = true break } } if !duplicate { - cfg.Bootstrap = append(cfg.Bootstrap, peer) + cfg.Bootstrap = append(cfg.Bootstrap, peer.String()) added = append(added, peer) } } @@ -257,10 +263,15 @@ func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.Bootstra removed := make([]config.BootstrapPeer, 0, len(toRemove)) keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap)) - for _, peer := range cfg.Bootstrap { + peers, err := cfg.BootstrapPeers() + if err != nil { + return nil, err + } + + for _, peer := range peers { found := false for _, peer2 := range toRemove { - if peer.Address == peer2.Address && peer.PeerID == peer2.PeerID { + if peer.Equal(peer2) { found = true removed = append(removed, peer) break @@ -271,7 +282,7 @@ func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.Bootstra keep = append(keep, peer) } } - cfg.Bootstrap = keep + cfg.SetBootstrapPeers(keep) if err := r.SetConfig(cfg); err != nil { return nil, err @@ -281,8 +292,10 @@ func bootstrapRemove(r repo.Repo, cfg *config.Config, toRemove []config.Bootstra } func bootstrapRemoveAll(r repo.Repo, cfg *config.Config) ([]config.BootstrapPeer, error) { - removed := make([]config.BootstrapPeer, len(cfg.Bootstrap)) - copy(removed, cfg.Bootstrap) + removed, err := cfg.BootstrapPeers() + if err != nil { + return nil, err + } cfg.Bootstrap = nil if err := r.SetConfig(cfg); err != nil { diff --git a/core/core.go b/core/core.go index d5ece35e9bf6..23aff76d7254 100644 --- a/core/core.go +++ b/core/core.go @@ -343,13 +343,14 @@ func (n *IpfsNode) loadPrivateKey() error { } func (n *IpfsNode) loadBootstrapPeers() ([]peer.PeerInfo, error) { + parsed, err := n.Repo.Config().BootstrapPeers() + if err != nil { + return nil, err + } + var peers []peer.PeerInfo - for _, bootstrap := range n.Repo.Config().Bootstrap { - p, err := toPeer(bootstrap) - if err != nil { - return nil, err - } - peers = append(peers, p) + for _, bpeer := range parsed { + peers = append(peers, toPeer(bpeer)) } return peers, nil } diff --git a/repo/config/bootstrap_peers.go b/repo/config/bootstrap_peers.go index db59f975f965..fff453b6a6e1 100644 --- a/repo/config/bootstrap_peers.go +++ b/repo/config/bootstrap_peers.go @@ -2,51 +2,30 @@ package config import ( "errors" - "strings" - ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" - mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" + iaddr "github.com/jbenet/go-ipfs/util/ipfsaddr" ) // BootstrapPeer is a peer used to bootstrap the network. -type BootstrapPeer struct { - Address string - PeerID string // until multiaddr supports ipfs, use another field. +type BootstrapPeer iaddr.IPFSAddr + +// ErrInvalidPeerAddr signals an address is not a valid peer address. +var ErrInvalidPeerAddr = errors.New("invalid peer address") + +func (c *Config) BootstrapPeers() ([]BootstrapPeer, error) { + return ParseBootstrapPeers(c.Bootstrap) } -func (bp *BootstrapPeer) String() string { - return bp.Address + "/" + bp.PeerID +func (c *Config) SetBootstrapPeers(bps []BootstrapPeer) { + c.Bootstrap = BootstrapPeerStrings(bps) } func ParseBootstrapPeer(addr string) (BootstrapPeer, error) { - // to be replaced with just multiaddr parsing, once ptp is a multiaddr protocol - idx := strings.LastIndex(addr, "/") - if idx == -1 { - return BootstrapPeer{}, errors.New("invalid address") - } - addrS := addr[:idx] - peeridS := addr[idx+1:] - - // make sure addrS parses as a multiaddr. - if len(addrS) > 0 { - maddr, err := ma.NewMultiaddr(addrS) - if err != nil { - return BootstrapPeer{}, err - } - - addrS = maddr.String() - } - - // make sure idS parses as a peer.ID - _, err := mh.FromB58String(peeridS) + ia, err := iaddr.ParseString(addr) if err != nil { - return BootstrapPeer{}, err + return nil, err } - - return BootstrapPeer{ - Address: addrS, - PeerID: peeridS, - }, nil + return BootstrapPeer(ia), err } func ParseBootstrapPeers(addrs []string) ([]BootstrapPeer, error) { @@ -60,3 +39,11 @@ func ParseBootstrapPeers(addrs []string) ([]BootstrapPeer, error) { } return peers, nil } + +func BootstrapPeerStrings(bps []BootstrapPeer) []string { + bpss := make([]string, len(bps)) + for i, p := range bps { + bpss[i] = p.String() + } + return bpss +} diff --git a/repo/config/config.go b/repo/config/config.go index 4c1086e8bcca..dbbbd71b94d8 100644 --- a/repo/config/config.go +++ b/repo/config/config.go @@ -16,14 +16,14 @@ var log = u.Logger("config") // Config is used to load IPFS config files. type Config struct { - Identity Identity // local node's peer identity - Datastore Datastore // local node's storage - Addresses Addresses // local node's addresses - Mounts Mounts // local node's mount points - Version Version // local node's version management - Bootstrap []BootstrapPeer // local nodes's bootstrap peers - Tour Tour // local node's tour position - Logs Logs // local node's event log configuration + Identity Identity // local node's peer identity + Datastore Datastore // local node's storage + Addresses Addresses // local node's addresses + Mounts Mounts // local node's mount points + Version Version // local node's version management + Bootstrap []string // local nodes's bootstrap peer addresses + Tour Tour // local node's tour position + Logs Logs // local node's event log configuration } const ( diff --git a/test/3nodetest/client/run.sh b/test/3nodetest/client/run.sh index 5c7c59a6efe8..5143905a232b 100644 --- a/test/3nodetest/client/run.sh +++ b/test/3nodetest/client/run.sh @@ -1,4 +1,4 @@ -ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE +ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE echo "3nodetest> starting client daemon" diff --git a/test/3nodetest/server/run.sh b/test/3nodetest/server/run.sh index d357faa11726..e37d86153dad 100644 --- a/test/3nodetest/server/run.sh +++ b/test/3nodetest/server/run.sh @@ -1,12 +1,12 @@ # must be connected to bootstrap node -ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE +ipfs bootstrap add /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE # wait for daemon to start/bootstrap # alternatively use ipfs swarm connect echo "3nodetest> starting server daemon" ipfs daemon & sleep 3 -# TODO instead of bootrapping: ipfs swarm connect /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE +# TODO instead of bootrapping: ipfs swarm connect /ip4/$BOOTSTRAP_PORT_4011_TCP_ADDR/tcp/$BOOTSTRAP_PORT_4011_TCP_PORT/ipfs/QmNXuBh8HFsWq68Fid8dMbGNQTh7eG6hV9rr1fQyfmfomE # must mount this volume from data container ipfs add -q /data/filetiny > tmptiny diff --git a/util/ipfsaddr/ipfsaddr.go b/util/ipfsaddr/ipfsaddr.go index 4c1f54a1a4e9..42fb659f0ea4 100644 --- a/util/ipfsaddr/ipfsaddr.go +++ b/util/ipfsaddr/ipfsaddr.go @@ -15,6 +15,8 @@ var ErrInvalidAddr = errors.New("invalid ipfs address") type IPFSAddr interface { ID() peer.ID Multiaddr() ma.Multiaddr + String() string + Equal(b interface{}) bool } type ipfsAddr struct { @@ -30,6 +32,20 @@ func (a ipfsAddr) Multiaddr() ma.Multiaddr { return a.ma } +func (a ipfsAddr) String() string { + return a.ma.String() +} + +func (a ipfsAddr) Equal(b interface{}) bool { + if ib, ok := b.(IPFSAddr); ok { + return a.Multiaddr().Equal(ib.Multiaddr()) + } + if mb, ok := b.(ma.Multiaddr); ok { + return a.Multiaddr().Equal(mb) + } + return false +} + // ParseString parses a string representation of an address into an IPFSAddr func ParseString(str string) (a IPFSAddr, err error) { if str == "" {