mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-30 01:52:26 +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"
|
cmds "github.com/jbenet/go-ipfs/commands"
|
||||||
config "github.com/jbenet/go-ipfs/config"
|
config "github.com/jbenet/go-ipfs/config"
|
||||||
core "github.com/jbenet/go-ipfs/core"
|
core "github.com/jbenet/go-ipfs/core"
|
||||||
|
corecmds "github.com/jbenet/go-ipfs/core/commands"
|
||||||
imp "github.com/jbenet/go-ipfs/importer"
|
imp "github.com/jbenet/go-ipfs/importer"
|
||||||
chunk "github.com/jbenet/go-ipfs/importer/chunk"
|
chunk "github.com/jbenet/go-ipfs/importer/chunk"
|
||||||
ci "github.com/jbenet/go-ipfs/p2p/crypto"
|
ci "github.com/jbenet/go-ipfs/p2p/crypto"
|
||||||
@ -179,6 +180,11 @@ func initConfig(configFilename string, dspathOverride string, nBitsForKeypair in
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bootstrapPeers, err := corecmds.DefaultBootstrapPeers()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
conf := &config.Config{
|
conf := &config.Config{
|
||||||
|
|
||||||
// setup the node's default addresses.
|
// 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",
|
API: "/ip4/127.0.0.1/tcp/5001",
|
||||||
},
|
},
|
||||||
|
|
||||||
Bootstrap: []*config.BootstrapPeer{
|
Bootstrap: bootstrapPeers,
|
||||||
&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",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
Datastore: ds,
|
Datastore: ds,
|
||||||
|
Logs: logConfig,
|
||||||
Logs: logConfig,
|
Identity: identity,
|
||||||
|
|
||||||
Identity: identity,
|
|
||||||
|
|
||||||
// setup the node mount points.
|
// setup the node mount points.
|
||||||
Mounts: config.Mounts{
|
Mounts: config.Mounts{
|
||||||
|
@ -3,8 +3,13 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"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"
|
ic "github.com/jbenet/go-ipfs/p2p/crypto"
|
||||||
u "github.com/jbenet/go-ipfs/util"
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
@ -55,6 +60,49 @@ func (bp *BootstrapPeer) String() string {
|
|||||||
return bp.Address + "/" + bp.PeerID
|
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
|
// Tour stores the ipfs tour read-list and resume point
|
||||||
type Tour struct {
|
type Tour struct {
|
||||||
Last string // last tour topic read
|
Last string // last tour topic read
|
||||||
@ -63,14 +111,14 @@ type Tour struct {
|
|||||||
|
|
||||||
// Config is used to load IPFS config files.
|
// Config is used to load IPFS config files.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Identity Identity // local node's peer identity
|
Identity Identity // local node's peer identity
|
||||||
Datastore Datastore // local node's storage
|
Datastore Datastore // local node's storage
|
||||||
Addresses Addresses // local node's addresses
|
Addresses Addresses // local node's addresses
|
||||||
Mounts Mounts // local node's mount points
|
Mounts Mounts // local node's mount points
|
||||||
Version Version // local node's version management
|
Version Version // local node's version management
|
||||||
Bootstrap []*BootstrapPeer // local nodes's bootstrap peers
|
Bootstrap []BootstrapPeer // local nodes's bootstrap peers
|
||||||
Tour Tour // local node's tour position
|
Tour Tour // local node's tour position
|
||||||
Logs Logs // local node's event log configuration
|
Logs Logs // local node's event log configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultPathRoot is the path to the default config dir location.
|
// DefaultPathRoot is the path to the default config dir location.
|
||||||
|
@ -29,7 +29,7 @@ func superviseConnections(parent context.Context,
|
|||||||
h host.Host,
|
h host.Host,
|
||||||
route *dht.IpfsDHT, // TODO depend on abstract interface for testing purposes
|
route *dht.IpfsDHT, // TODO depend on abstract interface for testing purposes
|
||||||
store peer.Peerstore,
|
store peer.Peerstore,
|
||||||
peers []*config.BootstrapPeer) error {
|
peers []config.BootstrapPeer) error {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
ctx, _ := context.WithTimeout(parent, connectiontimeout)
|
ctx, _ := context.WithTimeout(parent, connectiontimeout)
|
||||||
@ -51,7 +51,7 @@ func bootstrap(ctx context.Context,
|
|||||||
h host.Host,
|
h host.Host,
|
||||||
r *dht.IpfsDHT,
|
r *dht.IpfsDHT,
|
||||||
ps peer.Peerstore,
|
ps peer.Peerstore,
|
||||||
boots []*config.BootstrapPeer) error {
|
boots []config.BootstrapPeer) error {
|
||||||
|
|
||||||
connectedPeers := h.Network().Peers()
|
connectedPeers := h.Network().Peers()
|
||||||
if len(connectedPeers) >= recoveryThreshold {
|
if len(connectedPeers) >= recoveryThreshold {
|
||||||
@ -137,7 +137,7 @@ func connect(ctx context.Context, ps peer.Peerstore, r *dht.IpfsDHT, peers []pee
|
|||||||
return nil
|
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)
|
id, err := peer.IDB58Decode(bootstrap.PeerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -3,18 +3,29 @@ package commands
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"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"
|
cmds "github.com/jbenet/go-ipfs/commands"
|
||||||
config "github.com/jbenet/go-ipfs/config"
|
config "github.com/jbenet/go-ipfs/config"
|
||||||
u "github.com/jbenet/go-ipfs/util"
|
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 {
|
type BootstrapOutput struct {
|
||||||
Peers []*config.BootstrapPeer
|
Peers []config.BootstrapPeer
|
||||||
}
|
}
|
||||||
|
|
||||||
var peerOptionDesc = "A peer to add to the bootstrap list (in the format '<multiaddr>/<peerID>')"
|
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{
|
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) {
|
Run: func(req cmds.Request) (interface{}, error) {
|
||||||
input, err := bootstrapInputToPeers(req.Arguments())
|
inputPeers, err := config.ParseBootstrapPeers(req.Arguments())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -70,11 +86,30 @@ in the bootstrap list).
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
added, err := bootstrapAdd(filename, cfg, input)
|
deflt, _, err := req.Option("default").Bool()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return &BootstrapOutput{added}, nil
|
||||||
},
|
},
|
||||||
Type: &BootstrapOutput{},
|
Type: &BootstrapOutput{},
|
||||||
@ -106,7 +141,7 @@ var bootstrapRemoveCmd = &cmds.Command{
|
|||||||
cmds.BoolOption("all", "Remove all bootstrap peers."),
|
cmds.BoolOption("all", "Remove all bootstrap peers."),
|
||||||
},
|
},
|
||||||
Run: func(req cmds.Request) (interface{}, error) {
|
Run: func(req cmds.Request) (interface{}, error) {
|
||||||
input, err := bootstrapInputToPeers(req.Arguments())
|
input, err := config.ParseBootstrapPeers(req.Arguments())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -126,7 +161,7 @@ var bootstrapRemoveCmd = &cmds.Command{
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var removed []*config.BootstrapPeer
|
var removed []config.BootstrapPeer
|
||||||
if all {
|
if all {
|
||||||
removed, err = bootstrapRemoveAll(filename, cfg)
|
removed, err = bootstrapRemoveAll(filename, cfg)
|
||||||
} else {
|
} else {
|
||||||
@ -185,7 +220,7 @@ func bootstrapMarshaler(res cmds.Response) ([]byte, error) {
|
|||||||
return buf.Bytes(), err
|
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 {
|
for _, peer := range peers {
|
||||||
s := prefix + peer.Address + "/" + peer.PeerID + "\n"
|
s := prefix + peer.Address + "/" + peer.PeerID + "\n"
|
||||||
@ -197,46 +232,8 @@ func bootstrapWritePeers(w io.Writer, prefix string, peers []*config.BootstrapPe
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootstrapInputToPeers(input []string) ([]*config.BootstrapPeer, error) {
|
func bootstrapAdd(filename string, cfg *config.Config, peers []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
|
||||||
split := func(addr string) (string, string) {
|
added := make([]config.BootstrapPeer, 0, len(peers))
|
||||||
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))
|
|
||||||
|
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
duplicate := false
|
duplicate := false
|
||||||
@ -261,9 +258,9 @@ func bootstrapAdd(filename string, cfg *config.Config, peers []*config.Bootstrap
|
|||||||
return added, nil
|
return added, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootstrapRemove(filename string, cfg *config.Config, toRemove []*config.BootstrapPeer) ([]*config.BootstrapPeer, error) {
|
func bootstrapRemove(filename string, cfg *config.Config, toRemove []config.BootstrapPeer) ([]config.BootstrapPeer, error) {
|
||||||
removed := make([]*config.BootstrapPeer, 0, len(toRemove))
|
removed := make([]config.BootstrapPeer, 0, len(toRemove))
|
||||||
keep := make([]*config.BootstrapPeer, 0, len(cfg.Bootstrap))
|
keep := make([]config.BootstrapPeer, 0, len(cfg.Bootstrap))
|
||||||
|
|
||||||
for _, peer := range cfg.Bootstrap {
|
for _, peer := range cfg.Bootstrap {
|
||||||
found := false
|
found := false
|
||||||
@ -289,8 +286,8 @@ func bootstrapRemove(filename string, cfg *config.Config, toRemove []*config.Boo
|
|||||||
return removed, nil
|
return removed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bootstrapRemoveAll(filename string, cfg *config.Config) ([]*config.BootstrapPeer, error) {
|
func bootstrapRemoveAll(filename string, cfg *config.Config) ([]config.BootstrapPeer, error) {
|
||||||
removed := make([]*config.BootstrapPeer, len(cfg.Bootstrap))
|
removed := make([]config.BootstrapPeer, len(cfg.Bootstrap))
|
||||||
copy(removed, cfg.Bootstrap)
|
copy(removed, cfg.Bootstrap)
|
||||||
|
|
||||||
cfg.Bootstrap = nil
|
cfg.Bootstrap = nil
|
||||||
@ -302,6 +299,18 @@ func bootstrapRemoveAll(filename string, cfg *config.Config) ([]*config.Bootstra
|
|||||||
return removed, nil
|
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 = `
|
const bootstrapSecurityWarning = `
|
||||||
SECURITY WARNING:
|
SECURITY WARNING:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user