2015-12-01 19:44:58 +01:00
|
|
|
// Copyright (c) 2014 The btcsuite developers
|
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
2014-08-08 22:43:50 +02:00
|
|
|
|
|
|
|
package waddrmgr
|
|
|
|
|
|
|
|
import (
|
2017-09-19 23:53:38 +02:00
|
|
|
"time"
|
|
|
|
|
2018-05-15 07:11:11 +02:00
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/btcsuite/btcwallet/walletdb"
|
2014-08-08 22:43:50 +02:00
|
|
|
)
|
|
|
|
|
2018-02-14 06:14:49 +01:00
|
|
|
// BlockStamp defines a block (by height and a unique hash) and is used to mark
|
|
|
|
// a point in the blockchain that an address manager element is
|
2014-08-08 22:43:50 +02:00
|
|
|
// synced to.
|
|
|
|
type BlockStamp struct {
|
2018-03-05 18:10:18 +01:00
|
|
|
Height int32
|
|
|
|
Hash chainhash.Hash
|
|
|
|
Timestamp time.Time
|
2014-08-08 22:43:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// syncState houses the sync state of the manager. It consists of the recently
|
|
|
|
// seen blocks as height, as well as the start and current sync block stamps.
|
|
|
|
type syncState struct {
|
|
|
|
// startBlock is the first block that can be safely used to start a
|
2018-02-14 06:14:49 +01:00
|
|
|
// rescan. It is either the block the manager was created with, or the
|
|
|
|
// earliest block provided with imported addresses or scripts.
|
2014-08-08 22:43:50 +02:00
|
|
|
startBlock BlockStamp
|
|
|
|
|
|
|
|
// syncedTo is the current block the addresses in the manager are known
|
|
|
|
// to be synced against.
|
|
|
|
syncedTo BlockStamp
|
|
|
|
}
|
|
|
|
|
|
|
|
// newSyncState returns a new sync state with the provided parameters.
|
2017-07-12 01:13:10 +02:00
|
|
|
func newSyncState(startBlock, syncedTo *BlockStamp) *syncState {
|
2014-08-08 22:43:50 +02:00
|
|
|
|
|
|
|
return &syncState{
|
2017-07-12 01:13:10 +02:00
|
|
|
startBlock: *startBlock,
|
|
|
|
syncedTo: *syncedTo,
|
2014-08-08 22:43:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetSyncedTo marks the address manager to be in sync with the recently-seen
|
2018-02-14 06:14:49 +01:00
|
|
|
// block described by the blockstamp. When the provided blockstamp is nil, the
|
|
|
|
// oldest blockstamp of the block the manager was created at and of all
|
2014-08-08 22:43:50 +02:00
|
|
|
// imported addresses will be used. This effectively allows the manager to be
|
|
|
|
// marked as unsynced back to the oldest known point any of the addresses have
|
|
|
|
// appeared in the block chain.
|
2017-01-17 01:19:02 +01:00
|
|
|
func (m *Manager) SetSyncedTo(ns walletdb.ReadWriteBucket, bs *BlockStamp) error {
|
2014-08-08 22:43:50 +02:00
|
|
|
m.mtx.Lock()
|
|
|
|
defer m.mtx.Unlock()
|
|
|
|
|
2017-07-12 01:13:10 +02:00
|
|
|
// Use the stored start blockstamp and reset recent hashes and height
|
|
|
|
// when the provided blockstamp is nil.
|
2014-08-08 22:43:50 +02:00
|
|
|
if bs == nil {
|
|
|
|
bs = &m.syncState.startBlock
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the database.
|
2019-01-08 18:44:44 +01:00
|
|
|
err := PutSyncedTo(ns, bs)
|
2017-01-17 01:19:02 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2014-08-08 22:43:50 +02:00
|
|
|
|
|
|
|
// Update memory now that the database is updated.
|
|
|
|
m.syncState.syncedTo = *bs
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SyncedTo returns details about the block height and hash that the address
|
|
|
|
// manager is synced through at the very least. The intention is that callers
|
|
|
|
// can use this information for intelligently initiating rescans to sync back to
|
|
|
|
// the best chain from the last known good block.
|
|
|
|
func (m *Manager) SyncedTo() BlockStamp {
|
|
|
|
m.mtx.Lock()
|
|
|
|
defer m.mtx.Unlock()
|
|
|
|
|
|
|
|
return m.syncState.syncedTo
|
|
|
|
}
|
2017-07-12 01:13:10 +02:00
|
|
|
|
|
|
|
// BlockHash returns the block hash at a particular block height. This
|
|
|
|
// information is useful for comparing against the chain back-end to see if a
|
|
|
|
// reorg is taking place and how far back it goes.
|
|
|
|
func (m *Manager) BlockHash(ns walletdb.ReadBucket, height int32) (
|
|
|
|
*chainhash.Hash, error) {
|
|
|
|
m.mtx.Lock()
|
|
|
|
defer m.mtx.Unlock()
|
|
|
|
|
|
|
|
return fetchBlockHash(ns, height)
|
|
|
|
}
|
2017-09-19 23:53:38 +02:00
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
2018-11-06 02:06:21 +01:00
|
|
|
|
|
|
|
// BirthdayBlock returns the birthday block, or earliest block a key could have
|
2018-11-16 02:59:01 +01:00
|
|
|
// been used, for the manager. A boolean is also returned to indicate whether
|
|
|
|
// the birthday block has been verified as correct.
|
|
|
|
func (m *Manager) BirthdayBlock(ns walletdb.ReadBucket) (BlockStamp, bool, error) {
|
2019-01-08 18:44:44 +01:00
|
|
|
birthdayBlock, err := FetchBirthdayBlock(ns)
|
2018-11-16 02:59:01 +01:00
|
|
|
if err != nil {
|
|
|
|
return BlockStamp{}, false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return birthdayBlock, fetchBirthdayBlockVerification(ns), nil
|
2018-11-06 02:06:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetBirthdayBlock sets the birthday block, or earliest time a key could have
|
2018-11-16 02:59:01 +01:00
|
|
|
// been used, for the manager. The verified boolean can be used to specify
|
|
|
|
// whether this birthday block should be sanity checked to determine if there
|
|
|
|
// exists a better candidate to prevent less block fetching.
|
2018-11-06 02:06:21 +01:00
|
|
|
func (m *Manager) SetBirthdayBlock(ns walletdb.ReadWriteBucket,
|
2018-11-16 02:59:01 +01:00
|
|
|
block BlockStamp, verified bool) error {
|
2018-11-06 02:06:21 +01:00
|
|
|
|
2018-11-16 02:59:01 +01:00
|
|
|
if err := putBirthdayBlock(ns, block); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return putBirthdayBlockVerification(ns, verified)
|
2018-11-06 02:06:21 +01:00
|
|
|
}
|