diff --git a/account.go b/account.go index 357a09b..9d56008 100644 --- a/account.go +++ b/account.go @@ -444,7 +444,6 @@ func (a *Account) ActivePaymentAddresses() map[string]struct{} { // NewAddress returns a new payment address for an account. func (a *Account) NewAddress() (string, error) { a.mtx.Lock() - defer a.mtx.Unlock() // Get current block's height and hash. bs, err := GetCurBlock() @@ -460,6 +459,7 @@ func (a *Account) NewAddress() (string, error) { // Write updated wallet to disk. a.dirty = true + a.mtx.Unlock() if err = a.writeDirtyToDisk(); err != nil { log.Errorf("cannot sync dirty wallet: %v", err) } @@ -467,6 +467,8 @@ func (a *Account) NewAddress() (string, error) { // Request updates from btcd for new transactions sent to this address. a.ReqNewTxsForAddress(addr) + fmt.Println("after") + return addr, nil } diff --git a/cmd.go b/cmd.go index e71b568..de03fa7 100644 --- a/cmd.go +++ b/cmd.go @@ -207,8 +207,7 @@ func main() { // Open default account err = accountstore.OpenAccount("", cfg) if err != nil { - log.Errorf("cannot open account: %v", err) - os.Exit(1) + log.Warnf("cannot open default account: %v", err) } // Read CA file to verify a btcd TLS connection. diff --git a/wallet/wallet.go b/wallet/wallet.go index 0479e57..ddfd1ae 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -402,6 +402,11 @@ func NewWallet(name, desc string, passphrase []byte, net btcwire.BitcoinNet, return nil, err } + // Verify root address keypairs. + if err := root.verifyKeypairs(); err != nil { + return nil, err + } + // Compute AES key and encrypt root address. kdfp, err := computeKdfParameters(defaultKdfComputeTime, defaultKdfMaxMem) if err != nil { @@ -754,6 +759,9 @@ func (w *Wallet) extendKeypool(n uint, aeskey []byte, bs *BlockStamp) error { if err != nil { return err } + if err := newaddr.verifyKeypairs(); err != nil { + return err + } if err = newaddr.encrypt(aeskey); err != nil { return err } @@ -1238,6 +1246,40 @@ func newRootBtcAddress(privKey, iv, chaincode []byte, return addr, err } +// verifyKeypairs creates a signature using the parsed private key and +// verifies the signature with the parsed public key. If either of these +// steps fail, the keypair generation failed and any funds sent to this +// address will be unspendable. This step requires an unencrypted or +// unlocked btcAddress. +func (a *btcAddress) verifyKeypairs() error { + // Parse public key. + pubkey, err := btcec.ParsePubKey(a.pubKey, btcec.S256()) + if err != nil { + return err + } + + if len(a.privKeyCT.key) != 32 { + return errors.New("private key unavailable") + } + + privkey := &ecdsa.PrivateKey{ + PublicKey: *pubkey, + D: new(big.Int).SetBytes(a.privKeyCT.key), + } + + data := "String to sign." + r, s, err := ecdsa.Sign(rand.Reader, privkey, []byte(data)) + if err != nil { + return err + } + + ok := ecdsa.Verify(&privkey.PublicKey, []byte(data), r, s) + if !ok { + return errors.New("ecdsa verification failed") + } + return nil +} + // ReadFrom reads an encrypted address from an io.Reader. func (a *btcAddress) ReadFrom(r io.Reader) (n int64, err error) { var read int64