1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-29 17:36:38 +08:00

Merge pull request #497 from jbenet/bootstrap-add-default

bootstrap add --default option
This commit is contained in:
Juan Batiz-Benet
2015-01-06 06:08:13 -08:00
4 changed files with 133 additions and 99 deletions

View File

@ -12,6 +12,7 @@ import (
cmds "github.com/jbenet/go-ipfs/commands"
config "github.com/jbenet/go-ipfs/config"
core "github.com/jbenet/go-ipfs/core"
corecmds "github.com/jbenet/go-ipfs/core/commands"
imp "github.com/jbenet/go-ipfs/importer"
chunk "github.com/jbenet/go-ipfs/importer/chunk"
ci "github.com/jbenet/go-ipfs/p2p/crypto"
@ -179,6 +180,11 @@ func initConfig(configFilename string, dspathOverride string, nBitsForKeypair in
return nil, err
}
bootstrapPeers, err := corecmds.DefaultBootstrapPeers()
if err != nil {
return nil, err
}
conf := &config.Config{
// setup the node's default addresses.
@ -191,39 +197,10 @@ func initConfig(configFilename string, dspathOverride string, nBitsForKeypair in
API: "/ip4/127.0.0.1/tcp/5001",
},
Bootstrap: []*config.BootstrapPeer{
&config.BootstrapPeer{ // Use these hardcoded bootstrap peers for now.
// mars.i.ipfs.io
PeerID: "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
Address: "/ip4/104.131.131.82/tcp/4001",
},
&config.BootstrapPeer{
// Neptune
PeerID: "QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z",
Address: "/ip4/104.236.176.52/tcp/4001",
},
&config.BootstrapPeer{
// Pluto
PeerID: "QmSoLpPVmHKQ4XTPdz8tjDFgdeRFkpV8JgYq8JVJ69RrZm",
Address: "/ip4/104.236.179.241/tcp/4001",
},
&config.BootstrapPeer{
// Uranus
PeerID: "QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm",
Address: "/ip4/162.243.248.213/tcp/4001",
},
&config.BootstrapPeer{
// Saturn
PeerID: "QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
Address: "/ip4/128.199.219.111/tcp/4001",
},
},
Bootstrap: bootstrapPeers,
Datastore: ds,
Logs: logConfig,
Identity: identity,
Logs: logConfig,
Identity: identity,
// setup the node mount points.
Mounts: config.Mounts{

View File

@ -3,8 +3,13 @@ package config
import (
"encoding/base64"
"errors"
"os"
"path/filepath"
"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"
ic "github.com/jbenet/go-ipfs/p2p/crypto"
u "github.com/jbenet/go-ipfs/util"
@ -55,6 +60,49 @@ func (bp *BootstrapPeer) String() string {
return bp.Address + "/" + bp.PeerID
}
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)
if err != nil {
return BootstrapPeer{}, err
}
return BootstrapPeer{
Address: addrS,
PeerID: peeridS,
}, nil
}
func ParseBootstrapPeers(addrs []string) ([]BootstrapPeer, error) {
peers := make([]BootstrapPeer, len(addrs))
var err error
for i, addr := range addrs {
peers[i], err = ParseBootstrapPeer(addr)
if err != nil {
return nil, err
}
}
return peers, nil
}
// Tour stores the ipfs tour read-list and resume point
type Tour struct {
Last string // last tour topic read
@ -63,14 +111,14 @@ type Tour struct {
// 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 []BootstrapPeer // local nodes's bootstrap peers
Tour Tour // local node's tour position
Logs Logs // local node's event log configuration
}
// DefaultPathRoot is the path to the default config dir location.

View File

@ -29,7 +29,7 @@ func superviseConnections(parent context.Context,
h host.Host,
route *dht.IpfsDHT, // TODO depend on abstract interface for testing purposes
store peer.Peerstore,
peers []*config.BootstrapPeer) error {
peers []config.BootstrapPeer) error {
for {
ctx, _ := context.WithTimeout(parent, connectiontimeout)
@ -51,7 +51,7 @@ func bootstrap(ctx context.Context,
h host.Host,
r *dht.IpfsDHT,
ps peer.Peerstore,
boots []*config.BootstrapPeer) error {
boots []config.BootstrapPeer) error {
connectedPeers := h.Network().Peers()
if len(connectedPeers) >= recoveryThreshold {
@ -137,7 +137,7 @@ func connect(ctx context.Context, ps peer.Peerstore, r *dht.IpfsDHT, peers []pee
return nil
}
func toPeer(bootstrap *config.BootstrapPeer) (p peer.PeerInfo, err error) {
func toPeer(bootstrap config.BootstrapPeer) (p peer.PeerInfo, err error) {
id, err := peer.IDB58Decode(bootstrap.PeerID)
if err != nil {
return

View File

@ -3,18 +3,29 @@ package commands
import (
"bytes"
"io"
"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"
cmds "github.com/jbenet/go-ipfs/commands"
config "github.com/jbenet/go-ipfs/config"
u "github.com/jbenet/go-ipfs/util"
errors "github.com/jbenet/go-ipfs/util/debugerror"
)
// DefaultBootstrapAddresses are the hardcoded bootstrap addresses
// for ipfs. they are nodes run by the ipfs team. docs on these later.
// As with all p2p networks, bootstrap is an important security concern.
//
// 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)
}
type BootstrapOutput struct {
Peers []*config.BootstrapPeer
Peers []config.BootstrapPeer
}
var peerOptionDesc = "A peer to add to the bootstrap list (in the format '<multiaddr>/<peerID>')"
@ -52,10 +63,15 @@ in the bootstrap list).
},
Arguments: []cmds.Argument{
cmds.StringArg("peer", true, true, peerOptionDesc),
cmds.StringArg("peer", false, true, peerOptionDesc),
},
Options: []cmds.Option{
cmds.BoolOption("default", "add default bootstrap nodes"),
},
Run: func(req cmds.Request) (interface{}, error) {
input, err := bootstrapInputToPeers(req.Arguments())
inputPeers, err := config.ParseBootstrapPeers(req.Arguments())
if err != nil {
return nil, err
}
@ -70,11 +86,30 @@ in the bootstrap list).
return nil, err
}
added, err := bootstrapAdd(filename, cfg, input)
deflt, _, err := req.Option("default").Bool()
if err != nil {
return nil, err
}
if deflt {
// parse separately for meaningful, correct error.
defltPeers, err := DefaultBootstrapPeers()
if err != nil {
return nil, err
}
inputPeers = append(inputPeers, defltPeers...)
}
added, err := bootstrapAdd(filename, cfg, inputPeers)
if err != nil {
return nil, err
}
if len(inputPeers) == 0 {
return nil, cmds.ClientError("no bootstrap peers to add")
}
return &BootstrapOutput{added}, nil
},
Type: &BootstrapOutput{},
@ -106,7 +141,7 @@ var bootstrapRemoveCmd = &cmds.Command{
cmds.BoolOption("all", "Remove all bootstrap peers."),
},
Run: func(req cmds.Request) (interface{}, error) {
input, err := bootstrapInputToPeers(req.Arguments())
input, err := config.ParseBootstrapPeers(req.Arguments())
if err != nil {
return nil, err
}
@ -126,7 +161,7 @@ var bootstrapRemoveCmd = &cmds.Command{
return nil, err
}
var removed []*config.BootstrapPeer
var removed []config.BootstrapPeer
if all {
removed, err = bootstrapRemoveAll(filename, cfg)
} else {
@ -185,7 +220,7 @@ func bootstrapMarshaler(res cmds.Response) ([]byte, error) {
return buf.Bytes(), err
}
func bootstrapWritePeers(w io.Writer, prefix string, peers []*config.BootstrapPeer) error {
func bootstrapWritePeers(w io.Writer, prefix string, peers []config.BootstrapPeer) error {
for _, peer := range peers {
s := prefix + peer.Address + "/" + peer.PeerID + "\n"
@ -197,46 +232,8 @@ func bootstrapWritePeers(w io.Writer, prefix string, peers []*config.BootstrapPe
return nil
}
func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
split := func(addr string) (string, string) {
idx := strings.LastIndex(addr, "/")
if idx == -1 {
return "", addr
}
return addr[:idx], addr[idx+1:]
}
peers := []*config.BootstrapPeer{}
for _, addr := range input {
addrS, peeridS := split(addr)
// make sure addrS parses as a multiaddr.
if len(addrS) > 0 {
maddr, err := ma.NewMultiaddr(addrS)
if err != nil {
return nil, err
}
addrS = maddr.String()
}
// make sure idS parses as a peer.ID
_, err := mh.FromB58String(peeridS)
if err != nil {
return nil, err
}
// construct config entry
peers = append(peers, &config.BootstrapPeer{
Address: addrS,
PeerID: peeridS,
})
}
return peers, nil
}
func bootstrapAdd(filename string, cfg *config.Config, peers []*config.BootstrapPeer) ([]*config.BootstrapPeer, error) {
added := make([]*config.BootstrapPeer, 0, len(peers))
func bootstrapAdd(filename string, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
added := make([]config.BootstrapPeer, 0, len(peers))
for _, peer := range peers {
duplicate := false
@ -261,9 +258,9 @@ func bootstrapAdd(filename string, cfg *config.Config, peers []*config.Bootstrap
return added, nil
}
func bootstrapRemove(filename string, cfg *config.Config, toRemove []*config.BootstrapPeer) ([]*config.BootstrapPeer, error) {
removed := make([]*config.BootstrapPeer, 0, len(toRemove))
keep := make([]*config.BootstrapPeer, 0, len(cfg.Bootstrap))
func bootstrapRemove(filename string, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
removed := make([]config.BootstrapPeer, 0, len(toRemove))
keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap))
for _, peer := range cfg.Bootstrap {
found := false
@ -289,8 +286,8 @@ func bootstrapRemove(filename string, cfg *config.Config, toRemove []*config.Boo
return removed, nil
}
func bootstrapRemoveAll(filename string, cfg *config.Config) ([]*config.BootstrapPeer, error) {
removed := make([]*config.BootstrapPeer, len(cfg.Bootstrap))
func bootstrapRemoveAll(filename string, cfg *config.Config) ([]config.BootstrapPeer, error) {
removed := make([]config.BootstrapPeer, len(cfg.Bootstrap))
copy(removed, cfg.Bootstrap)
cfg.Bootstrap = nil
@ -302,6 +299,18 @@ func bootstrapRemoveAll(filename string, cfg *config.Config) ([]*config.Bootstra
return removed, nil
}
// DefaultBootstrapPeers returns the (parsed) set of default bootstrap peers.
// if it fails, it returns a meaningful error for the user.
// This is here (and not inside cmd/ipfs/init) because of module dependency problems.
func DefaultBootstrapPeers() ([]config.BootstrapPeer, error) {
ps, err := config.ParseBootstrapPeers(DefaultBootstrapAddresses)
if err != nil {
return nil, errors.Errorf(`failed to parse hardcoded bootstrap peers: %s
This is a problem with the ipfs codebase. Please report it to the dev team.`, err)
}
return ps, nil
}
const bootstrapSecurityWarning = `
SECURITY WARNING: