This repository has been archived by the owner on Apr 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement the bootstrapper command (#343)
* feat: implement the bootstrapper command * chore: typos * feat: also allow to connect to other bootstrappers
- Loading branch information
Showing
6 changed files
with
303 additions
and
27 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package bootstrapper | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
p2pcmd "github.com/celestiaorg/orchestrator-relayer/cmd/qgb/keys/p2p" | ||
"github.com/celestiaorg/orchestrator-relayer/helpers" | ||
"github.com/celestiaorg/orchestrator-relayer/p2p" | ||
"github.com/celestiaorg/orchestrator-relayer/store" | ||
ds "github.com/ipfs/go-datastore" | ||
dssync "github.com/ipfs/go-datastore/sync" | ||
"github.com/libp2p/go-libp2p/core/peer" | ||
"github.com/spf13/cobra" | ||
tmlog "github.com/tendermint/tendermint/libs/log" | ||
) | ||
|
||
func Command() *cobra.Command { | ||
bsCmd := &cobra.Command{ | ||
Use: "bootstrapper", | ||
Aliases: []string{"bs"}, | ||
Short: "QGB P2P network bootstrapper command", | ||
SilenceUsage: true, | ||
} | ||
|
||
bsCmd.AddCommand( | ||
Start(), | ||
Init(), | ||
p2pcmd.Root(ServiceNameBootstrapper), | ||
) | ||
|
||
bsCmd.SetHelpCommand(&cobra.Command{}) | ||
|
||
return bsCmd | ||
} | ||
|
||
func Start() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "start", | ||
Short: "Starts the bootstrapper node using the provided home. " + | ||
"Could be connected to other bootstrappers via the `-b` flag.", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
config, err := parseStartFlags(cmd) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// creating the logger | ||
logger := tmlog.NewTMLogger(os.Stdout) | ||
logger.Debug("starting bootstrapper node") | ||
|
||
ctx, cancel := context.WithCancel(cmd.Context()) | ||
defer cancel() | ||
|
||
// checking if the provided home is already initiated | ||
isInit := store.IsInit(logger, config.home, store.InitOptions{ | ||
NeedDataStore: false, | ||
NeedEVMKeyStore: false, | ||
NeedP2PKeyStore: true, | ||
}) | ||
if !isInit { | ||
return store.ErrNotInited | ||
} | ||
|
||
// creating the data store | ||
openOptions := store.OpenOptions{ | ||
HasDataStore: false, | ||
HasEVMKeyStore: false, | ||
HasP2PKeyStore: true, | ||
} | ||
s, err := store.OpenStore(logger, config.home, openOptions) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// get the p2p private key or generate a new one | ||
privKey, err := p2pcmd.GetP2PKeyOrGenerateNewOne(s.P2PKeyStore, config.p2pNickname) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// creating the host | ||
h, err := p2p.CreateHost(config.p2pListenAddr, privKey) | ||
if err != nil { | ||
return err | ||
} | ||
logger.Info( | ||
"created host", | ||
"ID", | ||
h.ID().String(), | ||
"Addresses", | ||
h.Addrs(), | ||
) | ||
|
||
// creating the data store | ||
dataStore := dssync.MutexWrap(ds.NewMapDatastore()) | ||
|
||
// get the bootstrappers | ||
var aIBootstrappers []peer.AddrInfo | ||
if config.bootstrappers == "" { | ||
aIBootstrappers = nil | ||
} else { | ||
bs := strings.Split(config.bootstrappers, ",") | ||
aIBootstrappers, err = helpers.ParseAddrInfos(logger, bs) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// creating the dht | ||
dht, err := p2p.NewQgbDHT(ctx, h, dataStore, aIBootstrappers, logger) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Listen for and trap any OS signal to graceful shutdown and exit | ||
go helpers.TrapSignal(logger, cancel) | ||
|
||
logger.Info("starting bootstrapper") | ||
|
||
ticker := time.NewTicker(time.Minute) | ||
for { | ||
select { | ||
case <-ctx.Done(): | ||
return nil | ||
case <-ticker.C: | ||
logger.Info("listening in bootstrapping mode", "peers_connected", dht.RoutingTable().Size()) | ||
} | ||
} | ||
}, | ||
} | ||
return addStartFlags(cmd) | ||
} | ||
|
||
func Init() *cobra.Command { | ||
cmd := cobra.Command{ | ||
Use: "init", | ||
Short: "Initialize the QGB bootstrapper store. Passed flags have persisted effect.", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
config, err := parseInitFlags(cmd) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
logger := tmlog.NewTMLogger(os.Stdout) | ||
|
||
initOptions := store.InitOptions{ | ||
NeedDataStore: false, | ||
NeedEVMKeyStore: false, | ||
NeedP2PKeyStore: true, | ||
} | ||
isInit := store.IsInit(logger, config.home, initOptions) | ||
if isInit { | ||
logger.Info("provided path is already initiated", "path", config.home) | ||
return nil | ||
} | ||
|
||
err = store.Init(logger, config.home, initOptions) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
return addInitFlags(&cmd) | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package bootstrapper | ||
|
||
import ( | ||
"github.com/celestiaorg/orchestrator-relayer/cmd/qgb/base" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const ( | ||
ServiceNameBootstrapper = "bootstrapper" | ||
) | ||
|
||
func addStartFlags(cmd *cobra.Command) *cobra.Command { | ||
homeDir, err := base.DefaultServicePath(ServiceNameBootstrapper) | ||
if err != nil { | ||
panic(err) | ||
} | ||
cmd.Flags().String(base.FlagHome, homeDir, "The qgb bootstrappers home directory") | ||
base.AddP2PNicknameFlag(cmd) | ||
base.AddP2PListenAddressFlag(cmd) | ||
base.AddBootstrappersFlag(cmd) | ||
return cmd | ||
} | ||
|
||
type StartConfig struct { | ||
home string | ||
p2pListenAddr, p2pNickname string | ||
bootstrappers string | ||
} | ||
|
||
func parseStartFlags(cmd *cobra.Command) (StartConfig, error) { | ||
p2pListenAddress, err := cmd.Flags().GetString(base.FlagP2PListenAddress) | ||
if err != nil { | ||
return StartConfig{}, err | ||
} | ||
p2pNickname, err := cmd.Flags().GetString(base.FlagP2PNickname) | ||
if err != nil { | ||
return StartConfig{}, err | ||
} | ||
homeDir, err := cmd.Flags().GetString(base.FlagHome) | ||
if err != nil { | ||
return StartConfig{}, err | ||
} | ||
if homeDir == "" { | ||
var err error | ||
homeDir, err = base.DefaultServicePath(ServiceNameBootstrapper) | ||
if err != nil { | ||
return StartConfig{}, err | ||
} | ||
} | ||
bootstrappers, err := cmd.Flags().GetString(base.FlagBootstrappers) | ||
if err != nil { | ||
return StartConfig{}, err | ||
} | ||
|
||
return StartConfig{ | ||
p2pNickname: p2pNickname, | ||
p2pListenAddr: p2pListenAddress, | ||
home: homeDir, | ||
bootstrappers: bootstrappers, | ||
}, nil | ||
} | ||
|
||
func addInitFlags(cmd *cobra.Command) *cobra.Command { | ||
homeDir, err := base.DefaultServicePath(ServiceNameBootstrapper) | ||
if err != nil { | ||
panic(err) | ||
} | ||
cmd.Flags().String(base.FlagHome, homeDir, "The qgb bootstrappers home directory") | ||
return cmd | ||
} | ||
|
||
type InitConfig struct { | ||
home string | ||
} | ||
|
||
func parseInitFlags(cmd *cobra.Command) (InitConfig, error) { | ||
homeDir, err := cmd.Flags().GetString(base.FlagHome) | ||
if err != nil { | ||
return InitConfig{}, err | ||
} | ||
if homeDir == "" { | ||
var err error | ||
homeDir, err = base.DefaultServicePath(ServiceNameBootstrapper) | ||
if err != nil { | ||
return InitConfig{}, err | ||
} | ||
} | ||
|
||
return InitConfig{ | ||
home: homeDir, | ||
}, nil | ||
} |
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
Oops, something went wrong.