-
Notifications
You must be signed in to change notification settings - Fork 1k
/
bootstrap.go
130 lines (117 loc) · 3.7 KB
/
bootstrap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"net/http"
"sync"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/peerstore"
ma "github.com/multiformats/go-multiaddr"
)
var (
IPFS_PEERS = convertPeers([]string{
"/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
"/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",
"/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
"/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",
"/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",
"/ip6/2604:a880:1:20::203:d001/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM",
"/ip6/2400:6180:0:d0::151:6001/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu",
"/ip6/2604:a880:800:10::4a:5001/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64",
"/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd",
})
LOCAL_PEER_ENDPOINT = "http://localhost:5001/api/v0/id"
)
// Borrowed from ipfs code to parse the results of the command `ipfs id`
type IdOutput struct {
ID string
PublicKey string
Addresses []string
AgentVersion string
ProtocolVersion string
}
// quick and dirty function to get the local ipfs daemons address for bootstrapping
func getLocalPeerInfo() []peer.AddrInfo {
resp, err := http.PostForm(LOCAL_PEER_ENDPOINT, nil)
if err != nil {
log.Fatalln(err)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
var js IdOutput
err = json.Unmarshal(body, &js)
if err != nil {
log.Fatalln(err)
}
for _, addr := range js.Addresses {
// For some reason, possibly NAT traversal, we need to grab the loopback ip address
if addr[0:8] == "/ip4/127" {
return convertPeers([]string{addr})
}
}
log.Fatalln(err)
return make([]peer.AddrInfo, 1) // not reachable, but keeps the compiler happy
}
func convertPeers(peers []string) []peer.AddrInfo {
pinfos := make([]peer.AddrInfo, len(peers))
for i, addr := range peers {
maddr := ma.StringCast(addr)
p, err := peer.AddrInfoFromP2pAddr(maddr)
if err != nil {
log.Fatalln(err)
}
pinfos[i] = *p
}
return pinfos
}
// This code is borrowed from the go-ipfs bootstrap process
func bootstrapConnect(ctx context.Context, ph host.Host, peers []peer.AddrInfo) error {
if len(peers) < 1 {
return errors.New("not enough bootstrap peers")
}
errs := make(chan error, len(peers))
var wg sync.WaitGroup
for _, p := range peers {
// performed asynchronously because when performed synchronously, if
// one `Connect` call hangs, subsequent calls are more likely to
// fail/abort due to an expiring context.
// Also, performed asynchronously for dial speed.
wg.Add(1)
go func(p peer.AddrInfo) {
defer wg.Done()
defer log.Println(ctx, "bootstrapDial", ph.ID(), p.ID)
log.Printf("%s bootstrapping to %s", ph.ID(), p.ID)
ph.Peerstore().AddAddrs(p.ID, p.Addrs, peerstore.PermanentAddrTTL)
if err := ph.Connect(ctx, p); err != nil {
log.Println(ctx, "bootstrapDialFailed", p.ID)
log.Printf("failed to bootstrap with %v: %s", p.ID, err)
errs <- err
return
}
log.Println(ctx, "bootstrapDialSuccess", p.ID)
log.Printf("bootstrapped with %v", p.ID)
}(p)
}
wg.Wait()
// our failure condition is when no connection attempt succeeded.
// So drain the errs channel, counting the results.
close(errs)
count := 0
var err error
for err = range errs {
if err != nil {
count++
}
}
if count == len(peers) {
return fmt.Errorf("failed to bootstrap. %s", err)
}
return nil
}