Skip to content

Commit

Permalink
Integrate ipld plugin and ipfs (#152)
Browse files Browse the repository at this point in the history
* config: add IPFS config

* Add ConfigRoot option

* also init ipfs on "tendermint init"

* add repo root to config

* spawn an ipfs node together with a tendermint node

* update to new rsmt2d API and update go.mod

* init ipfs node on integration test

* go fmt

* Moved (pre)loading the plugin to init() of the plugin package itself

* run Ipfs node OnStart

* minor doc changes and a few sacrificies to the linter gods

* Thanks for catching this @Wondertan

* rebased onto master

* Fix those e2e docker issues:

 - go mod download requires submodules mod/sum files to be copied over too

* Fix quotes glitch in the toml template

* Fix the e2e tests by initializing ipfs repos before running tendemrint nodes

* Fix typo

Co-authored-by: Evan Forbes <42654277+evan-forbes@users.noreply.github.com>

* Invert if-statements

* Clarifying comments instead of TODOs

* Fix typo in error string

Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>

* Captialize IPFS

Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>

* fix sentence

Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>

* review feedback:

 - move comments on top of function
 - spaces instead of tabs
 - fix typo
 - explain code duplication
 - add todo about unsafe-reset-all

Co-authored-by: Evan Forbes <42654277+evan-forbes@users.noreply.github.com>
Co-authored-by: John Adler <adlerjohn@users.noreply.github.com>
  • Loading branch information
3 people authored Feb 26, 2021
1 parent 0eccfb2 commit ceb881a
Show file tree
Hide file tree
Showing 13 changed files with 1,304 additions and 13 deletions.
92 changes: 92 additions & 0 deletions cmd/tendermint/commands/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ package commands

import (
"fmt"
"os"
"path/filepath"
"sync"

ipfscfg "github.com/ipfs/go-ipfs-config"
"github.com/ipfs/go-ipfs/plugin/loader"
"github.com/ipfs/go-ipfs/repo/fsrepo"
"github.com/ipfs/interface-go-ipfs-core/options"
"github.com/spf13/cobra"

cfg "github.com/lazyledger/lazyledger-core/config"
Expand Down Expand Up @@ -99,5 +106,90 @@ func initFilesWithConfig(config *cfg.Config) error {
logger.Info("Generated genesis file", "path", genFile)
}

if err := InitIpfs(config); err != nil {
return err
}

return nil
}

// InitIpfs takes a few config flags from the tendermint config.IPFS
// and applies them to the freshly created IPFS repo.
// The IPFS config will stored under config.IPFS.ConfigRootPath.
// TODO(ismail) move into separate file, and consider making IPFS initialization
// independent from the `tendermint init` subcommand.
// TODO(ismail): add counter part in ResetAllCmd
func InitIpfs(config *cfg.Config) error {
repoRoot := config.IPFSRepoRoot()
if fsrepo.IsInitialized(repoRoot) {
logger.Info("IPFS was already initialized", "ipfs-path", repoRoot)
return nil
}
var conf *ipfscfg.Config

identity, err := ipfscfg.CreateIdentity(os.Stdout, []options.KeyGenerateOption{
options.Key.Type(options.Ed25519Key),
})
if err != nil {
return err
}

logger.Info("initializing IPFS node", "ipfs-path", repoRoot)

if err := tmos.EnsureDir(repoRoot, 0700); err != nil {
return err
}

conf, err = ipfscfg.InitWithIdentity(identity)
if err != nil {
return err
}

applyFromTmConfig(conf, config.IPFS)
if err := setupPlugins(repoRoot); err != nil {
return err
}

if err := fsrepo.Init(repoRoot, conf); err != nil {
return err
}
return nil
}

// Inject replies on several global vars internally.
// For instance fsrepo.AddDatastoreConfigHandler will error
// if called multiple times with the same datastore.
// But for CI and integration tests, we want to setup the plugins
// for each repo but only inject once s.t. we can init multiple
// repos from the same runtime.
// TODO(ismail): find a more elegant way to achieve the same.
var injectPluginsOnce sync.Once

func setupPlugins(path string) error {
// Load plugins. This will skip the repo if not available.
plugins, err := loader.NewPluginLoader(filepath.Join(path, "plugins"))
if err != nil {
return fmt.Errorf("error loading plugins: %s", err)
}

if err := plugins.Initialize(); err != nil {
return fmt.Errorf("error initializing plugins: %s", err)
}

injectPluginsOnce.Do(func() {
err = plugins.Inject()
})
if err != nil {
return fmt.Errorf("error injecting plugins once: %w", err)
}

return nil
}

func applyFromTmConfig(ipfsConf *ipfscfg.Config, tmConf *cfg.IPFSConfig) {
ipfsConf.Addresses.API = ipfscfg.Strings{tmConf.API}
ipfsConf.Addresses.Gateway = ipfscfg.Strings{tmConf.Gateway}
ipfsConf.Addresses.Swarm = tmConf.Swarm
ipfsConf.Addresses.Announce = tmConf.Announce
ipfsConf.Addresses.NoAnnounce = tmConf.NoAnnounce
}
8 changes: 8 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ type Config struct {
Consensus *ConsensusConfig `mapstructure:"consensus"`
TxIndex *TxIndexConfig `mapstructure:"tx-index"`
Instrumentation *InstrumentationConfig `mapstructure:"instrumentation"`
// Options for IPFS service
IPFS *IPFSConfig `mapstructure:"ipfs"`
}

// DefaultConfig returns a default configuration for a Tendermint node
Expand All @@ -79,6 +81,7 @@ func DefaultConfig() *Config {
Consensus: DefaultConsensusConfig(),
TxIndex: DefaultTxIndexConfig(),
Instrumentation: DefaultInstrumentationConfig(),
IPFS: DefaultIPFSConfig(),
}
}

Expand All @@ -94,6 +97,7 @@ func TestConfig() *Config {
Consensus: TestConsensusConfig(),
TxIndex: TestTxIndexConfig(),
Instrumentation: TestInstrumentationConfig(),
IPFS: TetsIpfsConfig(),
}
}

Expand Down Expand Up @@ -1026,6 +1030,10 @@ func DefaultInstrumentationConfig() *InstrumentationConfig {
}
}

func TetsIpfsConfig() *IPFSConfig {
return DefaultIPFSConfig()
}

// TestInstrumentationConfig returns a default configuration for metrics
// reporting.
func TestInstrumentationConfig() *InstrumentationConfig {
Expand Down
34 changes: 34 additions & 0 deletions config/ipfs_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package config

// IPFSConfig defines a subset of the IPFS config that will be passed to the IPFS init and IPFS node (as a service)
// spun up by the tendermint node.
// It is mostly concerned about port configuration (Addresses).
type IPFSConfig struct {
// is where the generated IPFS config and files will be stored.
// The default is ~/.tendermint/ipfs.
ConfigRootPath string
// TODO: can we avoid copying the fields from ipfs' config.Addresses here?
// TODO: also, these are only used on init. Maybe ConfigRootPath is sufficient?
API string // address for the local API (RPC)
Gateway string // address to listen on for IPFS HTTP object gateway
// swarm related options:
Swarm []string // addresses for the swarm to listen on
Announce []string // swarm addresses to announce to the network
NoAnnounce []string // swarm addresses not to announce to the network
}

// DefaultIPFSConfig returns a default config different from the default IPFS config.
// This avoids conflicts with existing installations when running LazyLedger-core node
// locally for testing purposes.
func DefaultIPFSConfig() *IPFSConfig {
return &IPFSConfig{
ConfigRootPath: "ipfs/",
API: "/ip4/127.0.0.1/tcp/5002",
Gateway: "/ip4/127.0.0.1/tcp/5002",
Swarm: []string{"/ip4/0.0.0.0/tcp/4002", "/ip6/::/tcp/4002"},
}
}

func (cfg *Config) IPFSRepoRoot() string {
return rootify(cfg.IPFS.ConfigRootPath, cfg.RootDir)
}
23 changes: 23 additions & 0 deletions config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,29 @@ max-open-connections = {{ .Instrumentation.MaxOpenConnections }}
# Instrumentation namespace
namespace = "{{ .Instrumentation.Namespace }}"
#######################################################
### IPFS Configuration Options ###
#######################################################
[ipfs]
# IPFS repo root.
repo-root = "{{ .IPFS.ConfigRootPath}}"
## Below options will be passed to ipfs when initializing an ipfs repo.
## They will be written into the repo-root/config on init.
## To modify the generated config, edit repo-root/config accordingly.
# Address for the local API (RPC).
api = "{{ .IPFS.API }}"
# Address to listen on for IPFS HTTP object gateway.
gateway = "{{ .IPFS.Gateway }}"
# Addresses for the swarm to listen on
swarm = [{{ range .IPFS.Swarm }}{{ printf "%q, " . }}{{end}}]
# Swarm addresses to announce to the network
announce = [{{ range .IPFS.Announce }}{{ printf "%q, " . }}{{end}}]
# Swarm addresses not to announce to the network
no-announce = [{{ range .IPFS.NoAnnounce }}{{ printf "%q, " . }}{{end}}]
`

/****** these are for test settings ***********/
Expand Down
2 changes: 1 addition & 1 deletion consensus/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ func (cs *State) handleMsg(mi msgInfo) {
// We probably don't want to stop the peer here. The vote does not
// necessarily comes from a malicious peer but can be just broadcasted by
// a typical peer.
// https://github.com/lazyledger/lazyledger-core/issues/1281
// https://github.com/tendermint/tendermint/issues/1281
// }

// NOTE: the vote is broadcast to peers by the reactor listening
Expand Down
13 changes: 10 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ require (
github.com/go-logfmt/logfmt v0.5.0
github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.4.3
github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect
github.com/gorilla/websocket v1.4.2
github.com/gtank/merlin v0.1.1
github.com/hdevalence/ed25519consensus v0.0.0-20201207055737-7fde80a9d5ff
github.com/ipfs/go-ipfs v0.7.0
github.com/ipfs/go-ipfs-config v0.12.0
github.com/ipfs/interface-go-ipfs-core v0.4.0
github.com/lazyledger/lazyledger-core/p2p/ipld/plugin v0.0.0-20210219190522-0eccfb24e2aa
github.com/lazyledger/nmt v0.2.0
github.com/lazyledger/rsmt2d v0.0.0-20201215203123-e5ec7910ddd4
github.com/libp2p/go-buffer-pool v0.0.2
Expand All @@ -28,16 +31,20 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
github.com/rs/cors v1.7.0
github.com/sasha-s/go-deadlock v0.2.0
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa
github.com/spf13/cobra v1.1.1
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0
github.com/tendermint/tm-db v0.6.4
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5 // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 // indirect
google.golang.org/grpc v1.35.0
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
)

replace (
github.com/ipfs/go-ipfs => github.com/lazyledger/go-ipfs v0.7.0-lazypatch
github.com/lazyledger/lazyledger-core/p2p/ipld/plugin => ./p2p/ipld/plugin
)
Loading

0 comments on commit ceb881a

Please sign in to comment.