From 7b6203d0d421a3362b58d1a8b7c68459afc16034 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Tue, 21 Sep 2021 08:09:49 +0300 Subject: [PATCH 1/2] wallet: allow to open in read-only mode, fix #2182 If wallet was opened via `NewWalletFromFile`, open it as read-only first and re-open for write if needed. Signed-off-by: Evgeniy Stratonikov --- pkg/wallet/wallet.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/wallet/wallet.go b/pkg/wallet/wallet.go index ca32a4790..fe18ac7d2 100644 --- a/pkg/wallet/wallet.go +++ b/pkg/wallet/wallet.go @@ -56,12 +56,13 @@ func NewWallet(location string) (*Wallet, error) { // NewWalletFromFile creates a Wallet from the given wallet file path. func NewWalletFromFile(path string) (*Wallet, error) { - file, err := os.OpenFile(path, os.O_RDWR, os.ModeAppend) + file, err := os.Open(path) if err != nil { return nil, err } + defer file.Close() + wall := &Wallet{ - rw: file, path: file.Name(), } if err := json.NewDecoder(file).Decode(wall); err != nil { @@ -162,6 +163,13 @@ func (w *Wallet) savePretty() error { } func (w *Wallet) writeRaw(data []byte) error { + if w.rw == nil { + f, err := os.OpenFile(w.path, os.O_RDWR, os.ModeAppend) + if err != nil { + return err + } + w.rw = f + } if err := w.rewind(); err != nil { return err } From cb5b075e7da52fa49c00e4c43885befaa760e5ca Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Mon, 27 Sep 2021 10:45:42 +0300 Subject: [PATCH 2/2] wallet: do not store file handle Close immediately after read/write. This can be a bit slower but we store everything in memory anyway and code size is smaller. `wallet.Close()` method is now a no-op. Signed-off-by: Evgeniy Stratonikov --- pkg/wallet/wallet.go | 41 +++-------------------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/pkg/wallet/wallet.go b/pkg/wallet/wallet.go index fe18ac7d2..63d74fcca 100644 --- a/pkg/wallet/wallet.go +++ b/pkg/wallet/wallet.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "io" + "io/ioutil" "os" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -34,9 +35,6 @@ type Wallet struct { // Path where the wallet file is located.. path string - - // ReadWriter for reading and writing wallet data. - rw io.ReadWriter } // Extra stores imported token contracts. @@ -51,6 +49,7 @@ func NewWallet(location string) (*Wallet, error) { if err != nil { return nil, err } + defer file.Close() return newWallet(file), nil } @@ -80,7 +79,6 @@ func newWallet(rw io.ReadWriter) *Wallet { Version: walletVersion, Accounts: []*Account{}, Scrypt: keys.NEP2ScryptParams(), - rw: rw, path: path, } } @@ -163,37 +161,7 @@ func (w *Wallet) savePretty() error { } func (w *Wallet) writeRaw(data []byte) error { - if w.rw == nil { - f, err := os.OpenFile(w.path, os.O_RDWR, os.ModeAppend) - if err != nil { - return err - } - w.rw = f - } - if err := w.rewind(); err != nil { - return err - } - - _, err := w.rw.Write(data) - if err != nil { - return err - } - - if f, ok := w.rw.(*os.File); ok { - if err := f.Truncate(int64(len(data))); err != nil { - return err - } - } - return nil -} - -func (w *Wallet) rewind() error { - if s, ok := w.rw.(io.Seeker); ok { - if _, err := s.Seek(0, io.SeekStart); err != nil { - return err - } - } - return nil + return ioutil.WriteFile(w.path, data, 0644) } // JSON outputs a pretty JSON representation of the wallet. @@ -203,9 +171,6 @@ func (w *Wallet) JSON() ([]byte, error) { // Close closes the internal rw if its an io.ReadCloser. func (w *Wallet) Close() { - if rc, ok := w.rw.(io.ReadCloser); ok { - rc.Close() - } } // GetAccount returns account corresponding to the provided scripthash.