Skip to content

Commit

Permalink
feat(migration): Add config migration
Browse files Browse the repository at this point in the history
  • Loading branch information
matevz committed Mar 13, 2023
1 parent 0349e59 commit 5138642
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 14 deletions.
6 changes: 6 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ func initConfig() {
// Load and validate global configuration.
err := config.Load(v)
cobra.CheckErr(err)
changes, err := config.Global().Migrate()
cobra.CheckErr(err)
if changes {
err = config.Global().Save()
cobra.CheckErr(err)
}
err = config.Global().Validate()
cobra.CheckErr(err)
}
Expand Down
10 changes: 10 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,16 @@ func (cfg *Config) Save() error {
return cfg.viper.WriteConfig()
}

// Migrate migrates the given wallet config entry to the latest version and returns true, if any changes were needed.
func (cfg *Config) Migrate() (bool, error) {
changes, err := cfg.Wallet.Migrate()
if err != nil {
return false, fmt.Errorf("failed to migrate wallet configuration: %w", err)
}

return changes, nil
}

// Validate performs config validation.
func (cfg *Config) Validate() error {
if err := cfg.Networks.Validate(); err != nil {
Expand Down
23 changes: 21 additions & 2 deletions config/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package config
import (
"fmt"

"github.com/oasisprotocol/cli/wallet"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/config"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"

"github.com/oasisprotocol/cli/wallet"
)

// Wallet contains the configuration of the wallet.
Expand All @@ -18,6 +17,21 @@ type Wallet struct {
All map[string]*Account `mapstructure:",remain"`
}

// Migrate migrates configs of all accounts to the latest version and returns true, if any changes were needed.
func (w *Wallet) Migrate() (bool, error) {
var changes bool
for _, acc := range w.All {
af, err := acc.LoadFactory()
if err != nil {
return false, err
}

changes = af.Migrate(acc.Config) || changes
}

return changes, nil
}

// Validate performs config validation.
func (w *Wallet) Validate() error {
// Make sure the default account actually exists.
Expand Down Expand Up @@ -255,6 +269,11 @@ func (a *Account) Validate() error {
return fmt.Errorf("malformed address '%s': %w", a.Address, err)
}

// Check the algorithm is not empty.
if _, ok := a.Config["algorithm"]; !ok {
return fmt.Errorf("algorithm field not defined")
}

return nil
}

Expand Down
5 changes: 5 additions & 0 deletions wallet/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ func (af *fileAccountFactory) Create(name string, passphrase string, rawCfg map[
return newAccount(state, cfg)
}

// Migrate migrates the given wallet config entry to the latest version and returns true, if any changes were needed.
func (af *fileAccountFactory) Migrate(rawCfg map[string]interface{}) bool {
return false
}

func (af *fileAccountFactory) Load(name string, passphrase string, rawCfg map[string]interface{}) (wallet.Account, error) {
cfg, err := af.unmarshalConfig(rawCfg)
if err != nil {
Expand Down
19 changes: 7 additions & 12 deletions wallet/ledger/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/crypto/signature/secp256k1"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"

"github.com/oasisprotocol/cli/config"
"github.com/oasisprotocol/cli/wallet"
)

Expand Down Expand Up @@ -98,22 +97,22 @@ func (af *ledgerAccountFactory) HasConsensusSigner(rawCfg map[string]interface{}
return false
}

// migrate migrates the given config ledger account entry to the latest version of the config and
// Migrate migrates the given config ledger account entry to the latest version of the config and
// returns true, if any changes were needed.
func (af *ledgerAccountFactory) migrate(raw map[string]interface{}) bool {
func (af *ledgerAccountFactory) Migrate(rawCfg map[string]interface{}) bool {
var changed bool

// CONFIG MIGRATION 1 (add legacy derivation support): Set default derivation to ADR 8, if not set.
if raw["derivation"] == nil && raw["algorithm"] == nil {
raw["derivation"] = "adr8"
if rawCfg["derivation"] == nil && rawCfg["algorithm"] == nil {
rawCfg["derivation"] = "adr8"

changed = true
}

// CONFIG MIGRATION 2 (convert derivation -> algorithm).
if val, ok := raw["derivation"]; ok {
raw["algorithm"] = fmt.Sprintf("ed25519-%s", val)
delete(raw, "derivation")
if val, ok := rawCfg["derivation"]; ok {
rawCfg["algorithm"] = fmt.Sprintf("ed25519-%s", val)
delete(rawCfg, "derivation")

changed = true
}
Expand All @@ -126,10 +125,6 @@ func (af *ledgerAccountFactory) unmarshalConfig(raw map[string]interface{}) (*ac
return nil, fmt.Errorf("missing configuration")
}

if changed := af.migrate(raw); changed {
config.Global().Save()
}

var cfg accountConfig
if err := mapstructure.Decode(raw, &cfg); err != nil {
return nil, err
Expand Down
3 changes: 3 additions & 0 deletions wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ type Factory interface {
// Create creates a new account.
Create(name string, passphrase string, cfg map[string]interface{}) (Account, error)

// Migrate migrates the given wallet config entry to the latest version and returns true, if any changes were needed.
Migrate(rawCfg map[string]interface{}) bool

// Load loads an existing account.
Load(name string, passphrase string, cfg map[string]interface{}) (Account, error)

Expand Down

0 comments on commit 5138642

Please sign in to comment.