Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asset: create btcwallet+neutrino log dir and file without initialization #1946

Merged
merged 6 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions client/asset/bch/spv.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import (

const (
DefaultM uint64 = 784931 // From bchutil. Used for gcs filters.
logDirName = "logs"
logDirName = "spvlogs"
neutrinoDBName = "neutrino.db"
defaultAcctNum = 0
)
Expand Down Expand Up @@ -115,19 +115,14 @@ func openSPVWallet(dir string, cfg *btc.WalletConfig, btcParams *chaincfg.Params

// createSPVWallet creates a new SPV wallet.
func createSPVWallet(privPass []byte, seed []byte, bday time.Time, dbDir string, log dex.Logger, extIdx, intIdx uint32, net *bchchaincfg.Params) error {
netDir := filepath.Join(dbDir, net.Name, "spv")
netDir := filepath.Join(dbDir, net.Name)
walletDir := filepath.Join(netDir, "spv")

if err := logNeutrino(netDir, log); err != nil {
return fmt.Errorf("error initializing bchwallet+neutrino logging: %w", err)
}

logDir := filepath.Join(netDir, logDirName)
err := os.MkdirAll(logDir, 0744)
if err != nil {
return fmt.Errorf("error creating wallet directories: %w", err)
}

loader := wallet.NewLoader(net, netDir, true, 250)
loader := wallet.NewLoader(net, walletDir, true, 250)

pubPass := []byte(wallet.InsecurePubPassphrase)

Expand All @@ -148,7 +143,7 @@ func createSPVWallet(privPass []byte, seed []byte, bday time.Time, dbDir string,
}

// The chain service DB
neutrinoDBPath := filepath.Join(netDir, neutrinoDBName)
neutrinoDBPath := filepath.Join(walletDir, neutrinoDBName)
db, err := walletdb.Create("bdb", neutrinoDBPath, true)
if err != nil {
return fmt.Errorf("unable to create neutrino db at %q: %w", neutrinoDBPath, err)
Expand All @@ -168,7 +163,8 @@ func createSPVWallet(privPass []byte, seed []byte, bday time.Time, dbDir string,
// Start initializes the *bchwallet.Wallet and its supporting players and starts
// syncing.
func (w *bchSPVWallet) Start() (btc.SPVService, error) {
if err := logNeutrino(w.dir, w.log); err != nil {
netDir := filepath.Dir(w.dir)
if err := logNeutrino(netDir, w.log); err != nil {
return nil, fmt.Errorf("error initializing bchwallet+neutrino logging: %v", err)
}
// recoverWindow arguments borrowed from bchwallet directly.
Expand Down Expand Up @@ -973,7 +969,7 @@ func logRotator(netDir string) (*rotator.Rotator, error) {
// only has to be initialized once, so an atomic flag is used internally to
// return early on subsequent invocations.
//
// In theory, the the rotating file logger must be Close'd at some point, but
// In theory, the rotating file logger must be Closed at some point, but
// there are concurrency issues with that since btcd and btcwallet have
// unsupervised goroutines still running after shutdown. So we leave the rotator
// running at the risk of losing some logs.
Expand Down
32 changes: 14 additions & 18 deletions client/asset/btc/spv.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"sync/atomic"
"time"
Expand Down Expand Up @@ -60,18 +59,14 @@ var _ BTCWallet = (*btcSPVWallet)(nil)

// createSPVWallet creates a new SPV wallet.
func createSPVWallet(privPass []byte, seed []byte, bday time.Time, dataDir string, log dex.Logger, extIdx, intIdx uint32, net *chaincfg.Params) error {
dir := filepath.Join(dataDir, net.Name, "spv")
if err := logNeutrino(dir); err != nil {
return fmt.Errorf("error initializing btcwallet+neutrino logging: %w", err)
}
netDir := filepath.Join(dataDir, net.Name)
walletDir := filepath.Join(netDir, spvDir)

logDir := filepath.Join(dir, logDirName)
err := os.MkdirAll(logDir, 0744)
if err != nil {
return fmt.Errorf("error creating wallet directories: %w", err)
if err := logNeutrino(netDir); err != nil {
return fmt.Errorf("error initializing btcwallet+neutrino logging: %w", err)
}

loader := wallet.NewLoader(net, dir, true, dbTimeout, 250)
loader := wallet.NewLoader(net, walletDir, true, dbTimeout, 250)

pubPass := []byte(wallet.InsecurePubPassphrase)

Expand All @@ -95,7 +90,7 @@ func createSPVWallet(privPass []byte, seed []byte, bday time.Time, dataDir strin
}

// The chain service DB
neutrinoDBPath := filepath.Join(dir, neutrinoDBName)
neutrinoDBPath := filepath.Join(walletDir, neutrinoDBName)
db, err := walletdb.Create("bdb", neutrinoDBPath, true, dbTimeout)
if err != nil {
bailOnWallet()
Expand Down Expand Up @@ -142,10 +137,11 @@ func (w *btcSPVWallet) updateDBBirthday(bday time.Time) error {
})
}

// startWallet initializes the *btcwallet.Wallet and its supporting players and
// Start initializes the *btcwallet.Wallet and its supporting players and
// starts syncing.
func (w *btcSPVWallet) Start() (SPVService, error) {
if err := logNeutrino(w.dir); err != nil {
netDir := filepath.Dir(w.dir)
if err := logNeutrino(netDir); err != nil {
return nil, fmt.Errorf("error initializing btcwallet+neutrino logging: %v", err)
}
// timeout and recoverWindow arguments borrowed from btcwallet directly.
Expand Down Expand Up @@ -242,7 +238,7 @@ func (w *btcSPVWallet) Start() (SPVService, error) {
return &btcChainService{w.cl}, nil
}

// stop stops the wallet and database threads.
// Stop stops the wallet and database threads.
func (w *btcSPVWallet) Stop() {
w.log.Info("Unloading wallet")
if err := w.loader.UnloadWallet(); err != nil {
Expand Down Expand Up @@ -351,7 +347,7 @@ func (w *btcSPVWallet) ForceRescan() {
}
}

// walletTransaction pulls the transaction from the database.
// WalletTransaction pulls the transaction from the database.
func (w *btcSPVWallet) WalletTransaction(txHash *chainhash.Hash) (*wtxmgr.TxDetails, error) {
details, err := wallet.UnstableAPI(w.Wallet).TxDetails(txHash)
if err != nil {
Expand Down Expand Up @@ -383,12 +379,12 @@ func (w *btcSPVWallet) SyncedTo() waddrmgr.BlockStamp {
// return err
// })
// if err != nil {
// return nil, err // sadly, waddrmgr.ErrBirthdayBlockNotSet is expected during most of chain sync
// return nil, err // sadly, waddrmgr.ErrBirthdayBlockNotSet is expected during most of the chain sync
// }
// return &birthdayBlock, nil
// }

// signTransaction signs the transaction inputs.
// SignTx signs the transaction inputs.
func (w *btcSPVWallet) SignTx(tx *wire.MsgTx) error {
var prevPkScripts [][]byte
var inputValues []btcutil.Amount
Expand Down Expand Up @@ -500,7 +496,7 @@ func (s *secretSource) GetScript(addr btcutil.Address) ([]byte, error) {
// only has to be initialized once, so an atomic flag is used internally to
// return early on subsequent invocations.
//
// In theory, the the rotating file logger must be Close'd at some point, but
// In theory, the rotating file logger must be Closed at some point, but
// there are concurrency issues with that since btcd and btcwallet have
// unsupervised goroutines still running after shutdown. So we leave the rotator
// running at the risk of losing some logs.
Expand Down
55 changes: 51 additions & 4 deletions client/asset/btc/spv_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ const (

maxFutureBlockTime = 2 * time.Hour // see MaxTimeOffsetSeconds in btcd/blockchain/validate.go
neutrinoDBName = "neutrino.db"
logDirName = "logs"
spvDir = "spv"
logDirName = "spvlogs"
logFileName = "neutrino.log"
defaultAcctNum = 0
defaultAcctName = "default"
Expand Down Expand Up @@ -1086,7 +1087,7 @@ func (w *spvWallet) getBestBlockHeader() (*blockHeader, error) {
}

func (w *spvWallet) logFilePath() string {
return filepath.Join(w.dir, logDirName, logFileName)
return filepath.Join(filepath.Dir(w.dir), logDirName, logFileName)
}

// connect will start the wallet and begin syncing.
Expand Down Expand Up @@ -1157,8 +1158,54 @@ func (w *spvWallet) moveWalletData(backupDir string) error {
if err != nil {
return err
}
backupFolder := filepath.Join(backupDir, timeString)
return os.Rename(w.dir, backupFolder)

backupFolder := filepath.Join(backupDir, w.chainParams.Name, timeString)
// Copy wallet logs first. Even if there is an error, wallet files are
// still intact.
backupLogDir := filepath.Join(backupFolder, logDirName)
walletLogDir := filepath.Dir(w.logFilePath())
if err := copyDir(walletLogDir, backupLogDir); err != nil {
return err
}

walletBackupDir := filepath.Join(backupFolder, spvDir)
if err := os.Rename(w.dir, walletBackupDir); err != nil {
return err
}
return nil
}

// copyDir recursively copies the directories and files in source directory to
// destination directory without preserving the original file permissions.
func copyDir(srcDir, dstDir string) error {
dirFiles, err := os.ReadDir(srcDir)
if err != nil {
return err
}

if err := os.MkdirAll(dstDir, 0744); err != nil {
return err
}
ukane-philemon marked this conversation as resolved.
Show resolved Hide resolved

for _, file := range dirFiles {
srcFile := filepath.Join(srcDir, file.Name())
dstFile := filepath.Join(dstDir, file.Name())
if file.IsDir() {
if err := copyDir(srcFile, dstFile); err != nil {
return err
}
} else if file.Type().IsRegular() {
logBytes, err := os.ReadFile(srcFile)
ukane-philemon marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}
if err := os.WriteFile(dstFile, logBytes, 0744); err != nil {
return err
}
}
}

return nil
}

// numDerivedAddresses returns the number of internal and external addresses
Expand Down
30 changes: 16 additions & 14 deletions client/asset/dcr/spv.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const (
defaultAcctName = "default"
walletDbName = "wallet.db"
dbDriver = "bdb"
logDirName = "logs"
logDirName = "spvlogs"
logFileName = "neutrino.log"
)

Expand Down Expand Up @@ -138,22 +138,23 @@ var _ Wallet = (*spvWallet)(nil)
var _ tipNotifier = (*spvWallet)(nil)

func createSPVWallet(pw, seed []byte, dataDir string, extIdx, intIdx uint32, chainParams *chaincfg.Params) error {
dir := filepath.Join(dataDir, chainParams.Name, "spv")
netDir := filepath.Join(dataDir, chainParams.Name)
walletDir := filepath.Join(netDir, "spv")

if err := initLogging(dir); err != nil {
if err := initLogging(netDir); err != nil {
return fmt.Errorf("error initializing dcrwallet logging: %w", err)
}

if exists, err := walletExists(dir); err != nil {
if exists, err := walletExists(walletDir); err != nil {
return err
} else if exists {
return fmt.Errorf("wallet at %q already exists", dir)
return fmt.Errorf("wallet at %q already exists", walletDir)
}

ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

dbPath := filepath.Join(dir, walletDbName)
dbPath := filepath.Join(walletDir, walletDbName)
exists, err := fileExists(dbPath)
if err != nil {
return fmt.Errorf("error checking file existence for %q: %w", dbPath, err)
Expand All @@ -163,7 +164,7 @@ func createSPVWallet(pw, seed []byte, dataDir string, extIdx, intIdx uint32, cha
}

// Ensure the data directory for the network exists.
if err := checkCreateDir(dir); err != nil {
if err := checkCreateDir(walletDir); err != nil {
return fmt.Errorf("checkCreateDir error: %w", err)
}

Expand All @@ -172,7 +173,7 @@ func createSPVWallet(pw, seed []byte, dataDir string, extIdx, intIdx uint32, cha
// attempts to remove any wallet remnants.
defer func() {
if err != nil {
_ = os.Remove(dir)
_ = os.Remove(walletDir)
}
}()

Expand Down Expand Up @@ -232,7 +233,8 @@ func (w *spvWallet) Reconfigure(ctx context.Context, cfg *asset.WalletConfig, ne
}

func (w *spvWallet) startWallet(ctx context.Context) error {
if err := initLogging(w.dir); err != nil {
netDir := filepath.Dir(w.dir)
if err := initLogging(netDir); err != nil {
return fmt.Errorf("error initializing dcrwallet logging: %w", err)
}

Expand Down Expand Up @@ -952,11 +954,11 @@ func logRotator(netDir string) (*rotator.Rotator, error) {
// to be initialized once, so an atomic flag is used internally to return early
// on subsequent invocations.
//
// TODO: See if the below precaution is even necessary for dcrwallet.
// // In theory, the the rotating file logger must be Close'd at some point, but
// // there are concurrency issues with that since btcd and btcwallet have
// // unsupervised goroutines still running after shutdown. So we leave the rotator
// // running at the risk of losing some logs.
// TODO: See if the below precaution is even necessary for dcrwallet. In theory,
// the the rotating file logger must be Close'd at some point, but there are
// concurrency issues with that since btcd and btcwallet have unsupervised
// goroutines still running after shutdown. So we leave the rotator running at
// the risk of losing some logs.
func initLogging(netDir string) error {
if !atomic.CompareAndSwapUint32(&loggingInited, 0, 1) {
return nil
Expand Down
20 changes: 8 additions & 12 deletions client/asset/ltc/spv.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import (

const (
DefaultM uint64 = 784931 // From ltcutil. Used for gcs filters.
logDirName = "logs"
logDirName = "spvlogs"
neutrinoDBName = "neutrino.db"
defaultAcctNum = 0
dbTimeout = 20 * time.Second
Expand Down Expand Up @@ -121,20 +121,15 @@ func openSPVWallet(dir string, cfg *btc.WalletConfig, btcParams *chaincfg.Params

// createSPVWallet creates a new SPV wallet.
func createSPVWallet(privPass []byte, seed []byte, bday time.Time, dbDir string, log dex.Logger, extIdx, intIdx uint32, net *ltcchaincfg.Params) error {
netDir := filepath.Join(dbDir, net.Name, "spv")
netDir := filepath.Join(dbDir, net.Name)
walletDir := filepath.Join(netDir, "spv")

if err := logNeutrino(netDir, log); err != nil {
return fmt.Errorf("error initializing dcrwallet+neutrino logging: %w", err)
}

logDir := filepath.Join(netDir, logDirName)
err := os.MkdirAll(logDir, 0744)
if err != nil {
return fmt.Errorf("error creating wallet directories: %w", err)
}

// timeout and recoverWindow arguments borrowed from btcwallet directly.
loader := wallet.NewLoader(net, netDir, true, dbTimeout, 250)
loader := wallet.NewLoader(net, walletDir, true, dbTimeout, 250)

pubPass := []byte(wallet.InsecurePubPassphrase)

Expand All @@ -155,7 +150,7 @@ func createSPVWallet(privPass []byte, seed []byte, bday time.Time, dbDir string,
}

// The chain service DB
neutrinoDBPath := filepath.Join(netDir, neutrinoDBName)
neutrinoDBPath := filepath.Join(walletDir, neutrinoDBName)
db, err := walletdb.Create("bdb", neutrinoDBPath, true, dbTimeout)
if err != nil {
return fmt.Errorf("unable to create neutrino db at %q: %w", neutrinoDBPath, err)
Expand Down Expand Up @@ -188,7 +183,8 @@ func (w *ltcSPVWallet) walletParams() *ltcchaincfg.Params {
// Start initializes the *ltcwallet.Wallet and its supporting players and starts
// syncing.
func (w *ltcSPVWallet) Start() (btc.SPVService, error) {
if err := logNeutrino(w.dir, w.log); err != nil {
netDir := filepath.Dir(w.dir)
if err := logNeutrino(netDir, w.log); err != nil {
return nil, fmt.Errorf("error initializing dcrwallet+neutrino logging: %v", err)
}
// recoverWindow arguments borrowed from ltcwallet directly.
Expand Down Expand Up @@ -1005,7 +1001,7 @@ func logRotator(netDir string) (*rotator.Rotator, error) {
// only has to be initialized once, so an atomic flag is used internally to
// return early on subsequent invocations.
//
// In theory, the the rotating file logger must be Close'd at some point, but
// In theory, the rotating file logger must be Closed at some point, but
// there are concurrency issues with that since btcd and btcwallet have
// unsupervised goroutines still running after shutdown. So we leave the rotator
// running at the risk of losing some logs.
Expand Down