waddrmgr: add support for wallet birthday for creating new wallet
TODO: support for wallet upgrades and key imports
This commit is contained in:
parent
44f94c4ca5
commit
555bd5d583
3 changed files with 68 additions and 2 deletions
|
@ -194,6 +194,7 @@ var (
|
||||||
// Sync related key names (sync bucket).
|
// Sync related key names (sync bucket).
|
||||||
syncedToName = []byte("syncedto")
|
syncedToName = []byte("syncedto")
|
||||||
startBlockName = []byte("startblock")
|
startBlockName = []byte("startblock")
|
||||||
|
birthdayName = []byte("birthday")
|
||||||
|
|
||||||
// Account related key names (account bucket).
|
// Account related key names (account bucket).
|
||||||
acctNumAcctsName = []byte("numaccts")
|
acctNumAcctsName = []byte("numaccts")
|
||||||
|
@ -1489,6 +1490,37 @@ func putStartBlock(ns walletdb.ReadWriteBucket, bs *BlockStamp) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fetchBirthday loads the manager's bithday timestamp from the database.
|
||||||
|
func fetchBirthday(ns walletdb.ReadBucket) (time.Time, error) {
|
||||||
|
bucket := ns.NestedReadBucket(syncBucketName)
|
||||||
|
|
||||||
|
var t time.Time
|
||||||
|
|
||||||
|
buf := bucket.Get(birthdayName)
|
||||||
|
if len(buf) != 8 {
|
||||||
|
str := "malformed birthday stored in database"
|
||||||
|
return t, managerError(ErrDatabase, str, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
t = time.Unix(int64(binary.BigEndian.Uint64(buf)), 0)
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// putBirthday stores the provided birthday timestamp to the database.
|
||||||
|
func putBirthday(ns walletdb.ReadWriteBucket, t time.Time) error {
|
||||||
|
bucket := ns.NestedReadWriteBucket(syncBucketName)
|
||||||
|
|
||||||
|
buf := make([]byte, 8)
|
||||||
|
binary.BigEndian.PutUint64(buf, uint64(t.Unix()))
|
||||||
|
|
||||||
|
err := bucket.Put(birthdayName, buf)
|
||||||
|
if err != nil {
|
||||||
|
str := "failed to store birthday"
|
||||||
|
return managerError(ErrDatabase, str, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// managerExists returns whether or not the manager has already been created
|
// managerExists returns whether or not the manager has already been created
|
||||||
// in the given database namespace.
|
// in the given database namespace.
|
||||||
func managerExists(ns walletdb.ReadBucket) bool {
|
func managerExists(ns walletdb.ReadBucket) bool {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/chaincfg"
|
"github.com/roasbeef/btcd/chaincfg"
|
||||||
|
@ -249,6 +250,7 @@ type Manager struct {
|
||||||
chainParams *chaincfg.Params
|
chainParams *chaincfg.Params
|
||||||
addrs map[addrKey]ManagedAddress
|
addrs map[addrKey]ManagedAddress
|
||||||
syncState syncState
|
syncState syncState
|
||||||
|
birthday time.Time
|
||||||
watchingOnly bool
|
watchingOnly bool
|
||||||
locked bool
|
locked bool
|
||||||
closed bool
|
closed bool
|
||||||
|
@ -1985,12 +1987,13 @@ func (m *Manager) Decrypt(keyType CryptoKeyType, in []byte) ([]byte, error) {
|
||||||
func newManager(chainParams *chaincfg.Params, masterKeyPub *snacl.SecretKey,
|
func newManager(chainParams *chaincfg.Params, masterKeyPub *snacl.SecretKey,
|
||||||
masterKeyPriv *snacl.SecretKey, cryptoKeyPub EncryptorDecryptor,
|
masterKeyPriv *snacl.SecretKey, cryptoKeyPub EncryptorDecryptor,
|
||||||
cryptoKeyPrivEncrypted, cryptoKeyScriptEncrypted []byte, syncInfo *syncState,
|
cryptoKeyPrivEncrypted, cryptoKeyScriptEncrypted []byte, syncInfo *syncState,
|
||||||
privPassphraseSalt [saltSize]byte) *Manager {
|
birthday time.Time, privPassphraseSalt [saltSize]byte) *Manager {
|
||||||
|
|
||||||
return &Manager{
|
return &Manager{
|
||||||
chainParams: chainParams,
|
chainParams: chainParams,
|
||||||
addrs: make(map[addrKey]ManagedAddress),
|
addrs: make(map[addrKey]ManagedAddress),
|
||||||
syncState: *syncInfo,
|
syncState: *syncInfo,
|
||||||
|
birthday: birthday,
|
||||||
locked: true,
|
locked: true,
|
||||||
acctInfo: make(map[uint32]*accountInfo),
|
acctInfo: make(map[uint32]*accountInfo),
|
||||||
masterKeyPub: masterKeyPub,
|
masterKeyPub: masterKeyPub,
|
||||||
|
@ -2124,6 +2127,10 @@ func loadManager(ns walletdb.ReadBucket, pubPassphrase []byte, chainParams *chai
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, maybeConvertDbError(err)
|
return nil, maybeConvertDbError(err)
|
||||||
}
|
}
|
||||||
|
birthday, err := fetchBirthday(ns)
|
||||||
|
if err != nil {
|
||||||
|
return nil, maybeConvertDbError(err)
|
||||||
|
}
|
||||||
|
|
||||||
// When not a watching-only manager, set the master private key params,
|
// When not a watching-only manager, set the master private key params,
|
||||||
// but don't derive it now since the manager starts off locked.
|
// but don't derive it now since the manager starts off locked.
|
||||||
|
@ -2174,7 +2181,7 @@ func loadManager(ns walletdb.ReadBucket, pubPassphrase []byte, chainParams *chai
|
||||||
// call to new with the values loaded from the database.
|
// call to new with the values loaded from the database.
|
||||||
mgr := newManager(chainParams, &masterKeyPub, &masterKeyPriv,
|
mgr := newManager(chainParams, &masterKeyPub, &masterKeyPriv,
|
||||||
cryptoKeyPub, cryptoKeyPrivEnc, cryptoKeyScriptEnc, syncInfo,
|
cryptoKeyPub, cryptoKeyPrivEnc, cryptoKeyScriptEnc, syncInfo,
|
||||||
privPassphraseSalt)
|
birthday, privPassphraseSalt)
|
||||||
mgr.watchingOnly = watchingOnly
|
mgr.watchingOnly = watchingOnly
|
||||||
return mgr, nil
|
return mgr, nil
|
||||||
}
|
}
|
||||||
|
@ -2438,6 +2445,11 @@ func Create(ns walletdb.ReadWriteBucket, seed, pubPassphrase, privPassphrase []b
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Use 48 hours as margin of safety for wallet birthday.
|
||||||
|
err = putBirthday(ns, time.Now().Add(-48*time.Hour))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Save the information for the imported account to the database.
|
// Save the information for the imported account to the database.
|
||||||
err = putAccountInfo(ns, ImportedAddrAccount, nil,
|
err = putAccountInfo(ns, ImportedAddrAccount, nil,
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
package waddrmgr
|
package waddrmgr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
"github.com/roasbeef/btcwallet/walletdb"
|
"github.com/roasbeef/btcwallet/walletdb"
|
||||||
)
|
)
|
||||||
|
@ -87,3 +89,23 @@ func (m *Manager) BlockHash(ns walletdb.ReadBucket, height int32) (
|
||||||
|
|
||||||
return fetchBlockHash(ns, height)
|
return fetchBlockHash(ns, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Birthday returns the birthday, or earliest time a key could have been used,
|
||||||
|
// for the manager.
|
||||||
|
func (m *Manager) Birthday() time.Time {
|
||||||
|
m.mtx.Lock()
|
||||||
|
defer m.mtx.Unlock()
|
||||||
|
|
||||||
|
return m.birthday
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBirthday sets the birthday, or earliest time a key could have been used,
|
||||||
|
// for the manager.
|
||||||
|
func (m *Manager) SetBirthday(ns walletdb.ReadWriteBucket,
|
||||||
|
birthday time.Time) error {
|
||||||
|
m.mtx.Lock()
|
||||||
|
defer m.mtx.Unlock()
|
||||||
|
|
||||||
|
m.birthday = birthday
|
||||||
|
return putBirthday(ns, birthday)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue