Skip to content

Commit

Permalink
Merge pull request #144 from SiaFoundation/fix-host-locked-wallet
Browse files Browse the repository at this point in the history
Unlock wallet before other modules startup
  • Loading branch information
lukechampine authored Jul 19, 2022
2 parents 0c91a08 + 793a8da commit ea79021
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 23 deletions.
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ linters-settings:
- equalFold
gosec:
excludes:
- G112 # http ReadHeaderTimeout
- G113 # Rat.SetString uncontrolled memory consumption
- G307

linters:
Expand Down
18 changes: 2 additions & 16 deletions cmd/siad/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,19 +182,6 @@ func installKillSignalHandler() chan os.Signal {
return sigChan
}

// tryAutoUnlock will try to automatically unlock the server's wallet if the
// environment variable is set.
func tryAutoUnlock(srv *server.Server) {
if password := build.WalletPassword(); password != "" {
fmt.Println("Sia Wallet Password found, attempting to auto-unlock wallet")
if err := srv.Unlock(password); err != nil {
fmt.Println("Auto-unlock failed:", err)
} else {
fmt.Println("Auto-unlock successful.")
}
}
}

// startDaemon uses the config parameters to initialize Sia modules and start
// siad.
func startDaemon(config Config) (err error) {
Expand All @@ -218,16 +205,15 @@ func startDaemon(config Config) (err error) {

// Create the node params by parsing the modules specified in the config.
nodeParams := parseModules(config)
// set the wallet password from the environment variable
nodeParams.WalletPassword = build.WalletPassword()

// Start and run the server.
srv, err := server.New(config.Siad.APIaddr, config.Siad.RequiredUserAgent, config.APIPassword, nodeParams, loadStart)
if err != nil {
return err
}

// Attempt to auto-unlock the wallet using the SIA_WALLET_PASSWORD env variable
tryAutoUnlock(srv)

// listen for kill signals
sigChan := installKillSignalHandler()

Expand Down
54 changes: 47 additions & 7 deletions node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import (
"path/filepath"
"time"

mnemonics "gitlab.com/NebulousLabs/entropy-mnemonics"
"gitlab.com/NebulousLabs/errors"
"gitlab.com/NebulousLabs/ratelimit"
"gitlab.com/NebulousLabs/siamux"

"go.sia.tech/siad/build"
"go.sia.tech/siad/crypto"
"go.sia.tech/siad/modules"
"go.sia.tech/siad/modules/accounting"
"go.sia.tech/siad/modules/consensus"
Expand Down Expand Up @@ -101,12 +103,13 @@ type NodeParams struct {
SiaMuxWSAddress string

// Custom settings for modules
Allowance modules.Allowance
Bootstrap bool
UseUPNP bool
HostAddress string
HostStorage uint64
RPCAddress string
Allowance modules.Allowance
Bootstrap bool
UseUPNP bool
HostAddress string
HostStorage uint64
RPCAddress string
WalletPassword string

// Initialize node from existing seed.
PrimarySeed string
Expand Down Expand Up @@ -236,6 +239,29 @@ func (n *Node) Close() (err error) {
return err
}

// Unlock unlocks the server's wallet using the provided password.
func tryUnlockWallet(w modules.Wallet, password string) error {
if w == nil {
return errors.New("server doesn't have a wallet")
}
var validKeys []crypto.CipherKey
dicts := []mnemonics.DictionaryID{"english", "german", "japanese"}
for _, dict := range dicts {
seed, err := modules.StringToSeed(password, dict)
if err != nil {
continue
}
validKeys = append(validKeys, crypto.NewWalletKey(crypto.HashObject(seed)))
}
validKeys = append(validKeys, crypto.NewWalletKey(crypto.HashObject(password)))
for _, key := range validKeys {
if err := w.Unlock(key); err == nil {
return nil
}
}
return modules.ErrBadEncryptionKey
}

// New will create a new node. The inputs to the function are the respective
// 'New' calls for each module. We need to use this awkward method of
// initialization because the siatest package cannot import any of the modules
Expand Down Expand Up @@ -380,7 +406,21 @@ func New(params NodeParams, loadStartTime time.Time) (*Node, <-chan error) {
}
i++
printfRelease("(%d/%d) Loading wallet...\n", i, numModules)
return wallet.NewCustomWallet(cs, tp, filepath.Join(dir, modules.WalletDir), walletDeps)
wallet, err := wallet.NewCustomWallet(cs, tp, filepath.Join(dir, modules.WalletDir), walletDeps)
if err != nil {
return nil, err
}
// automatically unlock the wallet if the password is provided
if len(params.WalletPassword) != 0 {
printfRelease(" Wallet password found, attempting to unlock wallet...\n")
unlockErr := tryUnlockWallet(wallet, params.WalletPassword)
if unlockErr != nil {
fmt.Println(" Auto-unlock failed:", unlockErr)
} else {
fmt.Println(" Auto-unlock successful.")
}
}
return wallet, nil
}()
if err != nil {
errChan <- errors.Extend(err, errors.New("unable to create wallet"))
Expand Down

0 comments on commit ea79021

Please sign in to comment.