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  }