Skip to content

Commit

Permalink
Support auto-init & auto-unlock (#90)
Browse files Browse the repository at this point in the history
* Add env vars for auto-init & auto-unlock

* Update internal/config/config.go

---------

Co-authored-by: Marco Argentieri <[email protected]>
  • Loading branch information
altafan and tiero authored Feb 26, 2024
1 parent 6cfbc67 commit 2ad255a
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 2 deletions.
4 changes: 4 additions & 0 deletions cmd/oceand/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ var (
dbName = config.GetString(config.DbNameKey)
migrationSourceURL = config.GetString(config.DbMigrationPath)
dustAmount = uint64(config.GetInt(config.DustAmountKey))
walletPassword = config.GetString(config.PasswordKey)
walletMnemonic = config.GetString(config.MnemonicKey)
)

func main() {
Expand Down Expand Up @@ -89,6 +91,8 @@ func main() {
Network: network,
UtxoExpiryDuration: utxoExpiryDuration * time.Second,
DustAmount: dustAmount,
Password: walletPassword,
Mnemonic: walletMnemonic,
RepoManagerType: dbType,
BlockchainScannerType: bcScannerType,
RepoManagerConfig: repoManagerConfig,
Expand Down
19 changes: 19 additions & 0 deletions internal/app-config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

log "github.com/sirupsen/logrus"
"github.com/vulpemventures/go-bip39"
"github.com/vulpemventures/go-elements/network"
"github.com/vulpemventures/ocean/internal/config"
"github.com/vulpemventures/ocean/internal/core/application"
Expand Down Expand Up @@ -39,6 +40,8 @@ type AppConfig struct {
Network *network.Network
UtxoExpiryDuration time.Duration
DustAmount uint64
Password string
Mnemonic string

RepoManagerType string
BlockchainScannerType string
Expand All @@ -53,6 +56,14 @@ type AppConfig struct {
notifySvc *application.NotificationService
}

func (c *AppConfig) WithAutoUnlock() bool {
return len(c.Password) > 0
}

func (c *AppConfig) WithAutoInit() bool {
return len(c.Mnemonic) > 0
}

func (c *AppConfig) Validate() error {
if c.Network == nil {
return fmt.Errorf("missing network")
Expand Down Expand Up @@ -93,6 +104,14 @@ func (c *AppConfig) Validate() error {
if _, err := path.ParseRootDerivationPath(c.RootPath); err != nil {
return err
}
if len(c.Mnemonic) > 0 {
if !bip39.IsMnemonicValid(c.Mnemonic) {
return fmt.Errorf("invalid mnemonic")
}
if c.Password == "" {
return fmt.Errorf("missing password for auto init&unlock")
}
}

return nil
}
Expand Down
8 changes: 8 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ const (
DbMigrationPath = "DB_MIGRATION_PATH"
// DustAmountKey is the key to customize the dust amount threshold
DustAmountKey = "DUST_AMOUNT"
// PasswordKey is the key to set the password for auto-init/auto-unlock.
PasswordKey = "PASSWORD"
// MnemonicKey is the key to set the mnemonic for auto-init.
MnemonicKey = "MNEMONIC"

// DbLocation is the folder inside the datadir containing db files.
DbLocation = "db"
Expand Down Expand Up @@ -222,6 +226,10 @@ func validate() error {
}
}

if IsSet(MnemonicKey) && !IsSet(PasswordKey) {
return fmt.Errorf("password must be defined if mnemonic is set")
}

return nil
}

Expand Down
68 changes: 66 additions & 2 deletions internal/interfaces/grpc/service.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package grpc_interface

import (
"context"
"fmt"
"math/big"
"strings"
"time"

log "github.com/sirupsen/logrus"
pb "github.com/vulpemventures/ocean/api-spec/protobuf/gen/go/ocean/v1"
Expand All @@ -25,14 +28,19 @@ type service struct {
grpcServer *grpc.Server
chCloseStreamConnections chan (struct{})

log func(format string, a ...interface{})
log func(format string, a ...interface{})
warn func(err error, format string, a ...interface{})
}

func NewService(config ServiceConfig, appConfig *appconfig.AppConfig) (*service, error) {
logFn := func(format string, a ...interface{}) {
format = fmt.Sprintf("service: %s", format)
log.Infof(format, a...)
}
warnFn := func(err error, format string, a ...interface{}) {
format = fmt.Sprintf("account service: %s", format)
log.WithError(err).Warnf(format, a...)
}
if err := config.validate(); err != nil {
return nil, fmt.Errorf("invalid config: %s", err)
}
Expand All @@ -49,7 +57,9 @@ func NewService(config ServiceConfig, appConfig *appconfig.AppConfig) (*service,
logFn("created TLS keypair in path %s", config.TLSLocation)
}
chCloseStreamConnections := make(chan struct{})
return &service{config, appConfig, nil, chCloseStreamConnections, logFn}, nil
return &service{
config, appConfig, nil, chCloseStreamConnections, logFn, warnFn,
}, nil
}

func (s *service) Start() error {
Expand Down Expand Up @@ -110,6 +120,13 @@ func (s *service) start() (*grpc.Server, error) {

go grpcServer.Serve(s.config.listener())

switch {
case s.appConfig.WithAutoInit():
go s.autoInitAndUnlock()
case s.appConfig.WithAutoUnlock():
go s.autoUnlock()
}

return grpcServer, nil
}

Expand All @@ -131,3 +148,50 @@ func (s *service) stop(onlyGrpcServer bool) {
s.appConfig.RepoManager().Close()
s.log("closed connection with db")
}

func (s *service) autoInitAndUnlock() {
wallet := s.appConfig.WalletService()
status := wallet.GetStatus(context.Background())
if !status.IsInitialized {
s.autoInit()
}

s.autoUnlock()
}

func (s *service) autoUnlock() {
attempts := 0
ctx := context.Background()
wallet := s.appConfig.WalletService()
for attempts < 3 {
if err := wallet.Unlock(ctx, s.appConfig.Password); err != nil {
attempts++
s.warn(err, "failed to auto unlock, retrying...")
time.Sleep(100 * time.Millisecond)
continue
}
s.log("wallet auto unlocked")
return
}
s.warn(nil, "failed to auto unlock, the operation must be done manually")
}

func (s *service) autoInit() {
attempts := 0
ctx := context.Background()
wallet := s.appConfig.WalletService()
for attempts < 3 {
mnemonic := strings.Split(s.appConfig.Mnemonic, " ")
if err := wallet.CreateWallet(
ctx, mnemonic, s.appConfig.Password,
); err != nil {
attempts++
s.warn(err, "failed to auto init, retrying...")
time.Sleep(100 * time.Millisecond)
continue
}
s.log("wallet auto initialized")
return
}
s.warn(nil, "failed to auto initialize, the operation must be done manually")
}

0 comments on commit 2ad255a

Please sign in to comment.