forked from planetdecred/dcrlibwallet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
816 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package dcrlibwallet | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strconv" | ||
"strings" | ||
"sync" | ||
|
||
"decred.org/dcrwallet/v2/errors" | ||
"github.com/asdine/storm" | ||
"github.com/asdine/storm/q" | ||
"github.com/planetdecred/dcrlibwallet/btcwallet" | ||
) | ||
|
||
const walletTypeSPV = "SPV" | ||
|
||
type btcWallet struct { | ||
db *storm.DB | ||
wallets map[int]*btcwallet.Wallet | ||
cancelCoreCtx context.CancelFunc | ||
btcDataDir string | ||
} | ||
|
||
func (mw *MultiWallet) initBtcWallet() error { | ||
if mw.btcWallet != nil { | ||
return nil | ||
} | ||
|
||
btcDataDir := filepath.Join(mw.rootDir, "btc") | ||
|
||
err := os.MkdirAll(btcDataDir, os.ModePerm) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
walletsDB, err := storm.Open(filepath.Join(btcDataDir, walletsDbName)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// init database for saving/reading wallet objects | ||
err = walletsDB.Init(&btcwallet.Wallet{}) | ||
if err != nil { | ||
log.Errorf("Error initializing wallets database BTC: %s", err.Error()) | ||
return err | ||
} | ||
|
||
mw.btcWallet = &btcWallet{ | ||
btcDataDir: filepath.Join(mw.rootDir, "btc"), | ||
db: walletsDB, | ||
wallets: make(map[int]*btcwallet.Wallet), | ||
} | ||
|
||
// read saved wallets info from db and initialize wallets | ||
query := walletsDB.Select(q.True()).OrderBy("ID") | ||
var wallets []*btcwallet.Wallet | ||
err = query.Find(&wallets) | ||
if err != nil && err != storm.ErrNotFound { | ||
return err | ||
} | ||
|
||
// prepare the wallets loaded from db for use | ||
for _, wallet := range wallets { | ||
err = wallet.Prepare(mw.btcWallet.btcDataDir, mw.NetType(), log) | ||
if err == nil && !WalletExistsAt(wallet.DataDir()) { | ||
err = fmt.Errorf("missing wallet database file") | ||
} | ||
if err != nil { | ||
log.Warnf("Ignored wallet load error for wallet %d (%s)", wallet.ID, wallet.Name) | ||
} else { | ||
mw.btcWallet.wallets[wallet.ID] = wallet | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (mw *MultiWallet) CreateNewBTCWallet(walletName, password string) (*btcwallet.Wallet, error) { | ||
seed := "witch collapse practice feed shame open despair" | ||
encryptedSeed := []byte(seed) | ||
|
||
wallet, err := btcwallet.NewSpvWallet(walletName, encryptedSeed, mw.NetType(), log) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
walletNameExists := func(walletName string) (bool, error) { | ||
if strings.HasPrefix(walletName, "wallet-") { | ||
return false, errors.E(ErrReservedWalletName) | ||
} | ||
|
||
err := mw.btcWallet.db.One("Name", walletName, &btcwallet.Wallet{}) | ||
if err == nil { | ||
return true, nil | ||
} else if err != storm.ErrNotFound { | ||
return false, err | ||
} | ||
|
||
return false, nil | ||
} | ||
|
||
exists, err := walletNameExists(wallet.Name) | ||
if err != nil { | ||
return nil, err | ||
} else if exists { | ||
return nil, errors.New(ErrExist) | ||
} | ||
|
||
batchDbTransaction := func(dbOp func(node storm.Node) error) (err error) { | ||
dbTx, err := mw.btcWallet.db.Begin(true) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Commit or rollback the transaction after f returns or panics. Do not | ||
// recover from the panic to keep the original stack trace intact. | ||
panicked := true | ||
defer func() { | ||
if panicked || err != nil { | ||
dbTx.Rollback() | ||
return | ||
} | ||
|
||
err = dbTx.Commit() | ||
}() | ||
|
||
err = dbOp(dbTx) | ||
panicked = false | ||
return err | ||
} | ||
|
||
// Perform database save operations in batch transaction | ||
// for automatic rollback if error occurs at any point. | ||
err = batchDbTransaction(func(db storm.Node) error { | ||
// saving struct to update ID property with an auto-generated value | ||
err := db.Save(wallet) | ||
if err != nil { | ||
return err | ||
} | ||
walletDataDir := filepath.Join(mw.btcWallet.btcDataDir, strconv.Itoa(wallet.ID)) | ||
|
||
dirExists, err := fileExists(walletDataDir) | ||
if err != nil { | ||
return err | ||
} else if dirExists { | ||
newDirName, err := backupFile(walletDataDir, 1) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
log.Infof("Undocumented file at %s moved to %s", walletDataDir, newDirName) | ||
} | ||
|
||
os.MkdirAll(walletDataDir, os.ModePerm) // create wallet dir | ||
|
||
if wallet.Name == "" { | ||
wallet.Name = "wallet-" + strconv.Itoa(wallet.ID) // wallet-# | ||
} | ||
err = db.Save(wallet) // update database with complete wallet information | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = wallet.CreateSPVWallet([]byte(password), encryptedSeed, mw.btcWallet.btcDataDir) | ||
if err != nil { | ||
return fmt.Errorf("Create BTC wallet error: %v", err) | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return wallet, nil | ||
} | ||
|
||
func (mw *MultiWallet) ConnectBTCSPVWallets() error { | ||
ctx, _ := mw.contextWithShutdownCancel() | ||
var wg sync.WaitGroup | ||
for _, wall := range mw.btcWallet.wallets { | ||
err := wall.ConnectSPVWallet(ctx, &wg) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
wg.Wait() | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
module github.com/planetdecred/dcrlibwallet/btcwallet | ||
|
||
require ( | ||
github.com/btcsuite/btcd v0.22.0-beta.0.20211026140004-31791ba4dc6e | ||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f | ||
github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890 // note: hoists btcd's own require of btcutil | ||
github.com/btcsuite/btcwallet v0.12.0 | ||
github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0 // indirect | ||
github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 // indirect | ||
github.com/btcsuite/btcwallet/walletdb v1.4.0 | ||
github.com/btcsuite/btcwallet/wtxmgr v1.3.0 | ||
github.com/decred/dcrd/lru v1.1.1 // indirect | ||
github.com/decred/slog v1.2.0 | ||
github.com/jrick/logrotate v1.0.0 | ||
github.com/kkdai/bstream v1.0.0 // indirect | ||
github.com/lightninglabs/neutrino v0.13.1-0.20211214231330-53b628ce1756 | ||
github.com/stretchr/testify v1.7.0 // indirect | ||
go.etcd.io/bbolt v1.3.5 // indirect | ||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect | ||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect | ||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect | ||
) | ||
|
||
go 1.16 |
Oops, something went wrong.