-
-
Save geoah/ff70271a3be05f57f37f911e54f549e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"flag" | |
"fmt" | |
"sync" | |
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log" | |
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer" | |
host "gx/ipfs/QmXnaDLonE9YBTVDdWBM6Jb5YxxmW1MHMkXzgsnu1jTEmK/go-libp2p/p2p/host" | |
bhost "gx/ipfs/QmXnaDLonE9YBTVDdWBM6Jb5YxxmW1MHMkXzgsnu1jTEmK/go-libp2p/p2p/host/basic" | |
swarm "gx/ipfs/QmXnaDLonE9YBTVDdWBM6Jb5YxxmW1MHMkXzgsnu1jTEmK/go-libp2p/p2p/net/swarm" | |
testutil "gx/ipfs/QmYpVUnnedgGrp6cX2pBii5HRQgcSr778FiKVe7o7nF5Z3/go-testutil" | |
ma "gx/ipfs/QmYzDkkgAEmrcNzFCiYo6L1dTX4EAG1gZkbtdbd9trL4vd/go-multiaddr" | |
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore" | |
dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync" | |
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key" | |
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore" | |
record "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record" | |
iaddr "github.com/ipfs/go-ipfs/thirdparty/ipfsaddr" | |
dht "github.com/libp2p/go-libp2p-kad-dht" | |
) | |
var log = logging.Logger("dht-example") | |
var defaultBootstrapAddresses = []string{ | |
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", // mars.i.ipfs.io | |
// "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", // neptune.i.ipfs.io | |
// "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", // pluto.i.ipfs.io | |
// "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", // uranus.i.ipfs.io | |
// "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", // saturn.i.ipfs.io | |
// "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", // venus.i.ipfs.io | |
// "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", // earth.i.ipfs.io | |
// "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", // mercury.i.ipfs.io | |
// "/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", // jupiter.i.ipfs.io | |
} | |
func init() { | |
logging.SetLogLevel("*", "CRIT") | |
} | |
// create a Host with a random peer to listen on the given address. | |
// shamelessly copy-pasted from libp2p examples, minus the secio. | |
func makeDummyHost(listen string) (host.Host, error) { | |
// create a new random identity | |
ident, err := testutil.RandIdentity() | |
if err != nil { | |
return nil, err | |
} | |
// create new peerstore | |
ps := pstore.NewPeerstore() | |
// and add our keys to it | |
ps.AddPrivKey(ident.ID(), ident.PrivateKey()) | |
ps.AddPubKey(ident.ID(), ident.PublicKey()) | |
// a context to pass around | |
ctx := context.Background() | |
// create a new multiaddr for our host | |
addr, err := ma.NewMultiaddr(listen) | |
if err != nil { | |
return nil, err | |
} | |
// create a new swarm to be used by the service host | |
s, err := swarm.NewNetwork(ctx, []ma.Multiaddr{addr}, ident.ID(), ps, nil) | |
if err != nil { | |
return nil, err | |
} | |
// print something | |
log.Debugf("I am %s/ipfs/%s\n", addr, ident.ID().Pretty()) | |
// and return our new host, with enabled NAT | |
return bhost.New(s, bhost.NATPortMap), nil | |
} | |
func main() { | |
// get a port to listen to | |
listenF := flag.Int("l", 4000, "listen on port") | |
flag.Parse() | |
// and make a pretty multiaddr string | |
listenaddr := fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", *listenF) | |
// create a dummy host | |
ha, err := makeDummyHost(listenaddr) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// with a simple context | |
ctx := context.Background() | |
// create a datastore for our DHT | |
dss := dssync.MutexWrap(ds.NewMapDatastore()) | |
// and finaly create the DHT | |
d := dht.NewDHT(ctx, ha, dss) | |
// for the DHT GetValue to play nice, we seem to have to create a Selector | |
// the selector is chosen from the second part of the split-by-'/' key | |
// eg. for the key 'some/not/very/random/key' the 'not' validator will be chosen | |
// the selector then needs to select one of the returned values and return it, or error out | |
d.Selector["not"] = func(k key.Key, vals [][]byte) (int, error) { | |
return 0, nil | |
} | |
// in addition to the selector for any keys we want to put we must create a Validator. | |
// the validator again is chosen by the second part of the split-by-'/' key | |
d.Validator["not"] = &record.ValidChecker{ | |
Func: func(key.Key, []byte) error { | |
return nil | |
}, | |
Sign: false, | |
} | |
fmt.Println("Bootstrapping nodes; this might take a while.") | |
// TODO(geoah) There were some comments on IPFS code on why to do this async | |
// didn't actually have any issues running running it serially but let's leave it like this | |
// add boostrap nodes in peerstor for DHT to find. | |
var wg sync.WaitGroup | |
for _, addr := range defaultBootstrapAddresses { | |
wg.Add(1) | |
// extract the multiaddr | |
addr, _ := iaddr.ParseString(addr) | |
// make a PeerInfo that we can pass around | |
p := pstore.PeerInfo{ | |
ID: addr.ID(), | |
Addrs: []ma.Multiaddr{addr.Transport()}, | |
} | |
go func(p pstore.PeerInfo) { | |
defer wg.Done() | |
// add peer to peerstore | |
ha.Peerstore().AddAddrs(p.ID, p.Addrs, pstore.PermanentAddrTTL) | |
// dial the peer, so it can be added to the peerstore | |
if err := ha.Connect(ctx, p); err != nil { | |
log.Error("Could not connect to bootstrap peer.", err) | |
} | |
// Update peer in the DHT. | |
d.Update(ctx, p.ID) | |
}(p) | |
log.Debugf("Added ID=%v; Addr=%v; to our peerstore", p.ID, p.Addrs) | |
} | |
wg.Wait() | |
fmt.Println("> Done with bootstrapping.") | |
// everything should be ready by now | |
// let's have some fun with the DHT | |
// query the DHT for a peer (this is jupiter) | |
jup, _ := peer.IDB58Decode("QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx") | |
peer, err := d.FindPeer(ctx, jup) | |
fmt.Printf("DHT.FindPeer: peer=%v; err=%v.\n", peer, err) | |
// query the DHT for providers for an IPFS object (this is a pinned version of the go-key gx repo) | |
prov, err := d.FindProviders(ctx, key.B58KeyDecode("Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew")) | |
fmt.Printf("DHT.FindProviders: prov=%v; err=%v.\n", prov, err) | |
// now let's put a value on the DHT | |
err = d.PutValue(ctx, key.Key("some/not/very/random/key"), []byte("some-not-very-random-value")) | |
fmt.Printf("DHT.PutValue: err=%v.\n", err) | |
// and try to find it | |
value, err := d.GetValue(ctx, key.Key("some/not/very/random/key")) | |
fmt.Printf("DHT.GetValue: value=%v; err=%v.\n", string(value), err) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment