github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/p2p/test/ipfs.go (about) 1 package p2ptest 2 3 import ( 4 "context" 5 "fmt" 6 7 datastore "github.com/ipfs/go-datastore" 8 syncds "github.com/ipfs/go-datastore/sync" 9 config "github.com/ipfs/go-ipfs-config" 10 core "github.com/ipfs/go-ipfs/core" 11 corebs "github.com/ipfs/go-ipfs/core/bootstrap" 12 coreapi "github.com/ipfs/go-ipfs/core/coreapi" 13 mock "github.com/ipfs/go-ipfs/core/mock" 14 repo "github.com/ipfs/go-ipfs/repo" 15 coreiface "github.com/ipfs/interface-go-ipfs-core" 16 peer "github.com/libp2p/go-libp2p-core/peer" 17 mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" 18 qfs "github.com/qri-io/qfs" 19 "github.com/qri-io/qfs/localfs" 20 "github.com/qri-io/qfs/muxfs" 21 qipfs "github.com/qri-io/qfs/qipfs" 22 "github.com/qri-io/qri/auth/key" 23 testkeys "github.com/qri-io/qri/auth/key/test" 24 "github.com/qri-io/qri/event" 25 profile "github.com/qri-io/qri/profile" 26 qrirepo "github.com/qri-io/qri/repo" 27 ) 28 29 // MakeRepoFromIPFSNode wraps an ipfs node with a mock qri repo 30 func MakeRepoFromIPFSNode(ctx context.Context, node *core.IpfsNode, username string, bus event.Bus) (qrirepo.Repo, error) { 31 p := &profile.Profile{ 32 ID: profile.IDFromPeerID(node.Identity), 33 Peername: username, 34 PrivKey: node.PrivateKey, 35 PubKey: node.PrivateKey.GetPublic(), 36 } 37 38 // TODO (b5) - we can't supply the usual {Type: "mem"} {Type: "local"}, configuration options here 39 // b/c we want ipfs to be the "DefaultWriteFS", and muxFS doesn't give us an explicit API for setting 40 // the write filesystem 41 mux, err := muxfs.New(ctx, []qfs.Config{}) 42 if err != nil { 43 return nil, err 44 } 45 46 ipfs, err := qipfs.NewFilesystemFromNode(ctx, node) 47 if err != nil { 48 return nil, err 49 } 50 if err := mux.SetFilesystem(ipfs.(qfs.Filesystem)); err != nil { 51 return nil, err 52 } 53 54 localFS, err := localfs.NewFilesystem(ctx, nil) 55 if err != nil { 56 return nil, err 57 } 58 if err := mux.SetFilesystem(localFS); err != nil { 59 return nil, err 60 } 61 62 if err := mux.SetFilesystem(qfs.NewMemFS()); err != nil { 63 return nil, err 64 } 65 66 return qrirepo.NewMemRepoWithProfile(ctx, p, mux, bus) 67 } 68 69 // MakeIPFSNode creates a single mock IPFS Node 70 func MakeIPFSNode(ctx context.Context) (*core.IpfsNode, coreiface.CoreAPI, error) { 71 nd, api, err := MakeIPFSSwarm(ctx, true, 1) 72 if err != nil { 73 return nil, nil, err 74 } 75 76 return nd[0], api[0], nil 77 } 78 79 const testPeerID = "QmTFauExutTsy4XP6JbMFcw2Wa9645HJt2bTqL6qYDCKfe" 80 81 // MakeIPFSSwarm creates and connects n number of mock IPFS Nodes 82 func MakeIPFSSwarm(ctx context.Context, fullIdentity bool, n int) ([]*core.IpfsNode, []coreiface.CoreAPI, error) { 83 if n > 10 { 84 return nil, nil, fmt.Errorf("cannot generate a network of more than 10 peers") 85 } 86 mn := mocknet.New(ctx) 87 88 nodes := make([]*core.IpfsNode, n) 89 apis := make([]coreiface.CoreAPI, n) 90 91 for i := 0; i < n; i++ { 92 var ident config.Identity 93 if fullIdentity { 94 95 kd := testkeys.GetKeyData(i) 96 sk, pk := kd.PrivKey, kd.PrivKey.GetPublic() 97 98 id, err := peer.IDFromPublicKey(pk) 99 if err != nil { 100 return nil, nil, err 101 } 102 103 pkstr, err := key.EncodePrivKeyB64(sk) 104 if err != nil { 105 return nil, nil, err 106 } 107 108 ident = config.Identity{ 109 PeerID: id.Pretty(), 110 PrivKey: pkstr, 111 } 112 } else { 113 ident = config.Identity{ 114 PeerID: testPeerID, 115 } 116 } 117 118 c := config.Config{} 119 c.Addresses.Swarm = []string{fmt.Sprintf("/ip4/127.0.%d.1/tcp/4001", i)} 120 c.Identity = ident 121 122 r := &repo.Mock{ 123 C: c, 124 D: syncds.MutexWrap(datastore.NewMapDatastore()), 125 } 126 127 node, err := core.NewNode(ctx, &core.BuildCfg{ 128 Repo: r, 129 Host: mock.MockHostOption(mn), 130 Online: fullIdentity, 131 ExtraOpts: map[string]bool{ 132 "pubsub": true, 133 }, 134 }) 135 if err != nil { 136 return nil, nil, err 137 } 138 nodes[i] = node 139 apis[i], err = coreapi.NewCoreAPI(node) 140 if err != nil { 141 return nil, nil, err 142 } 143 } 144 145 err := mn.LinkAll() 146 if err != nil { 147 return nil, nil, err 148 } 149 150 bsinf := corebs.BootstrapConfigWithPeers( 151 []peer.AddrInfo{ 152 nodes[0].Peerstore.PeerInfo(nodes[0].Identity), 153 }, 154 ) 155 156 for _, n := range nodes[1:] { 157 if err := n.Bootstrap(bsinf); err != nil { 158 return nil, nil, err 159 } 160 } 161 162 return nodes, apis, nil 163 }