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:
@ -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{
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
Reference in New Issue
Block a user