Skip to content

Commit

Permalink
feat(ipfs): Add coreapi create methods
Browse files Browse the repository at this point in the history
  • Loading branch information
gfanton authored and moul committed Oct 10, 2019
1 parent 835f39f commit 273c11a
Show file tree
Hide file tree
Showing 8 changed files with 879 additions and 15 deletions.
15 changes: 14 additions & 1 deletion go/cmd/bertychat/main.go
@@ -1,6 +1,7 @@
package main

import (
"context"
"flag"
"fmt"
"log"
Expand All @@ -11,6 +12,7 @@ import (
"berty.tech/go/internal/banner"
_ "berty.tech/go/internal/buildconstraints" // fail if bad go version
"berty.tech/go/internal/chatdb"
"berty.tech/go/internal/ipfsutil"
"berty.tech/go/internal/protocoldb"
"berty.tech/go/pkg/bertychat"
"berty.tech/go/pkg/bertyprotocol"
Expand Down Expand Up @@ -115,14 +117,24 @@ func main() {
return errors.Wrap(err, "failed to initialize datastore")
}

// initialize ipfs
coreapi, err := ipfsutil.NewInMemoryCoreAPI(context.TODO())
if err != nil {
return errors.Wrap(err, "failed to initialize ipfsutil")
}

// initialize new protocol client
protocolOpts := bertyprotocol.Opts{
Logger: logger.Named("bertyprotocol"),
}
protocol, err = bertyprotocol.New(db, protocolOpts)
protocol, err = bertyprotocol.New(db, coreapi, protocolOpts)
if err != nil {
return errors.Wrap(err, "failed to initialize protocol")
}

// log ipfs informations
protocol.LogIPFSInformations()

defer protocol.Close()
}

Expand All @@ -149,6 +161,7 @@ func main() {
if err != nil {
return errors.Wrap(err, "failed to initialize chat")
}

defer chat.Close()
}

Expand Down
11 changes: 9 additions & 2 deletions go/go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

664 changes: 659 additions & 5 deletions go/go.sum

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions go/internal/ipfsutil/api_inmemory.go
@@ -0,0 +1,87 @@
package ipfsutil

import (
"context"
"crypto/rand"
"encoding/base64"

ipfs_datastore "github.com/ipfs/go-datastore"
ipfs_datastoresync "github.com/ipfs/go-datastore/sync"
ipfs_cfg "github.com/ipfs/go-ipfs-config"
ipfs_core "github.com/ipfs/go-ipfs/core"
ipfs_coreapi "github.com/ipfs/go-ipfs/core/coreapi"
ipfs_node "github.com/ipfs/go-ipfs/core/node"
ipfs_libp2p "github.com/ipfs/go-ipfs/core/node/libp2p"
ipfs_repo "github.com/ipfs/go-ipfs/repo"
ipfs_interface "github.com/ipfs/interface-go-ipfs-core"

libp2p_ci "github.com/libp2p/go-libp2p-crypto" // nolint:staticcheck
libp2p_peer "github.com/libp2p/go-libp2p-peer" // nolint:staticcheck

"github.com/pkg/errors"
)

func NewInMemoryCoreAPI(ctx context.Context) (ipfs_interface.CoreAPI, error) {
cfg, err := createBuildConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to create ipfs build config")
}

node, err := ipfs_core.NewNode(ctx, cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to create a new ipfs node")
}

return ipfs_coreapi.NewCoreAPI(node)
}

func createBuildConfig() (*ipfs_node.BuildCfg, error) {
ds := ipfs_datastore.NewMapDatastore()
repo, err := createRepo(ipfs_datastoresync.MutexWrap(ds))
if err != nil {
return nil, errors.Wrap(err, "failed to create ipfs repo")
}

routing := ipfs_libp2p.DHTOption
hostopts := ipfs_libp2p.DefaultHostOption
return &ipfs_node.BuildCfg{
Online: true,
Permanent: true,
DisableEncryptedConnections: false,
NilRepo: false,
Routing: routing,
Host: hostopts,
Repo: repo,
}, nil
}

func createRepo(dstore ipfs_repo.Datastore) (ipfs_repo.Repo, error) {
c := ipfs_cfg.Config{}
priv, pub, err := libp2p_ci.GenerateKeyPairWithReader(libp2p_ci.RSA, 2048, rand.Reader) // nolint:staticcheck
if err != nil {
return nil, errors.Wrap(err, "failed to create ipfs build config")
}

pid, err := libp2p_peer.IDFromPublicKey(pub) // nolint:staticcheck
if err != nil {
return nil, errors.Wrap(err, "failed to convert public key to PeerID")
}

privkeyb, err := priv.Bytes()
if err != nil {
return nil, errors.Wrap(err, "failed to get serialized private key")
}

c.Bootstrap = ipfs_cfg.DefaultBootstrapAddresses
c.Addresses.Swarm = []string{
"/ip4/0.0.0.0/tcp/4001",
"/ip6/0.0.0.0/tcp/4001",
}
c.Identity.PeerID = pid.Pretty()
c.Identity.PrivKey = base64.StdEncoding.EncodeToString(privkeyb)

return &ipfs_repo.Mock{
D: dstore,
C: c,
}, nil
}
58 changes: 58 additions & 0 deletions go/internal/ipfsutil/api_mock.go
@@ -0,0 +1,58 @@
package ipfsutil

import (
"context"

ipfs_core "github.com/ipfs/go-ipfs/core"
ipfs_coreapi "github.com/ipfs/go-ipfs/core/coreapi"
ipfs_mock "github.com/ipfs/go-ipfs/core/mock"
ipfs_interface "github.com/ipfs/interface-go-ipfs-core"

libp2p_mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"

"github.com/pkg/errors"
)

type MockedCoreAPI interface {
ipfs_interface.CoreAPI

MockNetwork() libp2p_mocknet.Mocknet
MockNode() *ipfs_core.IpfsNode
}

func NewMockCoreAPI(ctx context.Context) (MockedCoreAPI, error) {
mocknet := libp2p_mocknet.New(ctx)
node, err := ipfs_core.NewNode(ctx, &ipfs_core.BuildCfg{
Online: true,
Host: ipfs_mock.MockHostOption(mocknet),
ExtraOpts: map[string]bool{
"pubsub": true,
},
})

if err != nil {
return nil, errors.Wrap(err, "failed to mocked ipfs node")
}

coreapi, err := ipfs_coreapi.NewCoreAPI(node)
if err != nil {
return nil, errors.Wrap(err, "failed to init coreapi")
}

return &mockedCoreAPI{coreapi, mocknet, node}, nil
}

type mockedCoreAPI struct {
ipfs_interface.CoreAPI

mocknet libp2p_mocknet.Mocknet
node *ipfs_core.IpfsNode
}

func (m *mockedCoreAPI) MockNetwork() libp2p_mocknet.Mocknet {
return m.mocknet
}

func (m *mockedCoreAPI) MockNode() *ipfs_core.IpfsNode {
return m.node
}
42 changes: 37 additions & 5 deletions go/pkg/bertyprotocol/client.go
@@ -1,6 +1,9 @@
package bertyprotocol

import (
context "context"

ipfs_coreapi "github.com/ipfs/interface-go-ipfs-core"
"github.com/jinzhu/gorm"
"go.uber.org/zap"
)
Expand All @@ -13,12 +16,15 @@ type Client interface {

Close() error
Status() Status

LogIPFSInformations()
}

type client struct {
// variables
db *gorm.DB
opts Opts
db *gorm.DB
opts Opts
ipfsCoreAPI ipfs_coreapi.CoreAPI
}

// Opts contains optional configuration flags for building a new Client
Expand All @@ -27,16 +33,42 @@ type Opts struct {
}

// New initializes a new Client
func New(db *gorm.DB, opts Opts) (Client, error) {
func New(db *gorm.DB, IpfsCoreAPI ipfs_coreapi.CoreAPI, opts Opts) (Client, error) {
if opts.Logger == nil {
opts.Logger = zap.NewNop()
}

return &client{
db: db,
opts: opts,
db: db,
opts: opts,
ipfsCoreAPI: IpfsCoreAPI,
}, nil
}

func (c *client) LogIPFSInformations() {
key, err := c.ipfsCoreAPI.Key().Self(context.TODO())
if err != nil {
c.opts.Logger.Error("unable to log ipfs identity", zap.Error(err))
return
}

maddrs, err := c.ipfsCoreAPI.Swarm().ListenAddrs(context.TODO())
if err != nil {
c.opts.Logger.Error("unable to log ipfs listener", zap.Error(err))
return
}

addrs := make([]string, len(maddrs))
for i, addr := range maddrs {
addrs[i] = addr.String()
}

c.opts.Logger.Info("ipfs node",
zap.String("PeerID", key.ID().Pretty()),
zap.Strings("Listeners", addrs),
)
}

func (c *client) Close() error {
return nil
}
Expand Down
8 changes: 7 additions & 1 deletion go/pkg/bertyprotocol/client_test.go
@@ -1,8 +1,10 @@
package bertyprotocol

import (
context "context"
"testing"

"berty.tech/go/internal/ipfsutil"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
Expand All @@ -23,8 +25,12 @@ func ExampleNew() {
// Opts is optional
opts := Opts{}

coreapi, err := ipfsutil.NewInMemoryCoreAPI(context.TODO())
if err != nil {
panic(err)
}
// initialize new client
client, err := New(db, opts)
client, err := New(db, coreapi, opts)
if err != nil {
panic(err)
}
Expand Down
9 changes: 8 additions & 1 deletion go/pkg/bertyprotocol/testing.go
@@ -1,8 +1,10 @@
package bertyprotocol

import (
context "context"
"testing"

"berty.tech/go/internal/ipfsutil"
"berty.tech/go/internal/protocoldb"
"go.uber.org/zap"
)
Expand All @@ -15,9 +17,14 @@ func TestingClient(t *testing.T, opts Opts) (Client, func()) {
opts.Logger = zap.NewNop()
}

coreapi, err := ipfsutil.NewMockCoreAPI(context.TODO())
if err != nil {
t.Fatalf("failed to initialize ipfs: %v", err)
}

db := protocoldb.TestingSqliteDB(t, opts.Logger)

client, err := New(db, opts)
client, err := New(db, coreapi, opts)
if err != nil {
t.Fatalf("failed to initialize client: %v", err)
}
Expand Down

0 comments on commit 273c11a

Please sign in to comment.